Implemented sorting via the ISAMB system. To enable, use sortindex:b
[idzebra-moved-to-github.git] / index / retrieve.c
1 /* $Id: retrieve.c,v 1.61 2006-12-18 23:40:07 adam Exp $
2    Copyright (C) 1995-2006
3    Index Data ApS
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
21 */
22
23 #include <stdio.h>
24 #include <assert.h>
25
26 #include <fcntl.h>
27 #ifdef WIN32
28 #include <io.h>
29 #include <process.h>
30 #endif
31 #if HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34
35 #include "index.h"
36 #include <yaz/diagbib1.h>
37 #include <direntz.h>
38
39
40 #define ZEBRA_XML_HEADER_STR "<record xmlns=\"http://www.indexdata.com/zebra/\""
41
42 static int zebra_create_record_stream(ZebraHandle zh, 
43                                Record *rec,
44                                struct ZebraRecStream *stream){
45
46     RecordAttr *recordAttr = rec_init_attr(zh->reg->zei, *rec);
47
48     if ((*rec)->size[recInfo_storeData] > 0)
49         zebra_create_stream_mem(stream, (*rec)->info[recInfo_storeData],
50                                 (*rec)->size[recInfo_storeData]);
51     else
52     {
53         char full_rep[1024];
54         int fd;
55             
56         if (zh->path_reg && !yaz_is_abspath((*rec)->info[recInfo_filename])){
57             strcpy(full_rep, zh->path_reg);
58             strcat(full_rep, "/");
59             strcat(full_rep, (*rec)->info[recInfo_filename]);
60         }
61         else
62             strcpy(full_rep, (*rec)->info[recInfo_filename]);
63             
64         if ((fd = open (full_rep, O_BINARY|O_RDONLY)) == -1){
65             yaz_log (YLOG_WARN|YLOG_ERRNO, "Retrieve fail; missing file: %s",
66                      full_rep);
67             rec_free(rec);
68             return 14;
69         }
70         zebra_create_stream_fd(stream, fd, recordAttr->recordOffset);
71     }
72     return 0;
73 }
74     
75
76
77 static int parse_zebra_elem(const char *elem,
78                             const char **index, size_t *index_len,
79                             const char **type, size_t *type_len)
80 {
81     *index = 0;
82     *index_len = 0;
83
84     *type = 0;
85     *type_len = 0;
86
87     if (elem && *elem)
88     {
89         char *cp;
90         /* verify that '::' is in the beginning of *elem 
91            and something more follows */
92         if (':' != *elem
93             || !(elem +1) || ':' != *(elem +1)
94             || !(elem +2) || '\0' == *(elem +2))
95             return 0;
96  
97         /* pick out info from string after '::' */
98         elem = elem + 2;
99         cp = strchr(elem, ':');
100
101         if (!cp) /* index, no colon, no type */
102         {
103             *index = elem;
104             *index_len = strlen(elem);
105         }
106         else if (cp[1] == '\0') /* colon, but no following type */
107         {
108             return 0;
109         }
110         else  /* index, colon and type */
111         {
112             *index = elem;
113             *index_len = cp - elem;
114             *type = cp+1;
115             *type_len = strlen(cp+1);
116         }
117     }
118     return 1;
119 }
120
121
122 int zebra_special_sort_fetch(ZebraHandle zh, zint sysno, ODR odr,
123                              const char *elemsetname,
124                              oid_value input_format,
125                              oid_value *output_format,
126                              char **rec_bufp, int *rec_lenp)
127 {
128     const char *retrieval_index;
129     size_t retrieval_index_len; 
130     const char *retrieval_type;
131     size_t retrieval_type_len;
132     char retrieval_index_cstr[256];
133     int ord;
134
135     /* only accept XML and SUTRS requests */
136     if (input_format != VAL_TEXT_XML && input_format != VAL_SUTRS)
137     {
138         yaz_log(YLOG_WARN, "unsupported format for element set zebra::%s", 
139                 elemsetname);
140         *output_format = VAL_NONE;
141         return YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
142     }
143     
144     if (!parse_zebra_elem(elemsetname,
145                           &retrieval_index, &retrieval_index_len,
146                           &retrieval_type,  &retrieval_type_len))
147     {
148         return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
149     }
150     
151     if (retrieval_type_len != 0 && retrieval_type_len != 1)
152     {
153         return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
154     }
155     if (!retrieval_index_len ||
156         retrieval_index_len >= sizeof(retrieval_index_cstr)-1)
157     {
158         return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
159     }
160         
161     memcpy(retrieval_index_cstr, retrieval_index, retrieval_index_len);
162     retrieval_index_cstr[retrieval_index_len] = '\0';
163
164     ord = zebraExplain_lookup_attr_str(zh->reg->zei,
165                                        zinfo_index_category_sort,
166                                        (retrieval_type_len == 0 ? -1 : 
167                                         retrieval_type[0]),
168                                        retrieval_index_cstr);
169     if (ord == -1)
170         return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
171     else
172     {
173         char dst_buf[IT_MAX_WORD];
174         char str[IT_MAX_WORD];
175         int index_type;
176         const char *db = 0;
177         const char *string_index = 0;
178         WRBUF wrbuf = wrbuf_alloc();
179         
180         zebra_sort_sysno(zh->reg->sort_index, sysno);
181         zebra_sort_type(zh->reg->sort_index, ord);
182         zebra_sort_read(zh->reg->sort_index, str);
183
184         zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type, &db, &string_index);
185         
186         zebra_term_untrans(zh, index_type, dst_buf, str);
187         
188
189         if (input_format == VAL_TEXT_XML)
190         {
191             *output_format = VAL_TEXT_XML;
192             wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
193                          " sysno=\"" ZINT_FORMAT "\""
194                          " set=\"zebra::sort%s/\">\n",
195                          sysno, elemsetname);
196
197             wrbuf_printf(wrbuf, "  <sort name=\"%s\"", 
198                          string_index);
199             wrbuf_printf(wrbuf, " type=\"%c\">", index_type);
200             wrbuf_xmlputs(wrbuf, dst_buf);
201             wrbuf_printf(wrbuf, "</sort>\n");
202             wrbuf_printf(wrbuf, "</record>\n");
203         }
204         else if (input_format == VAL_SUTRS)
205         {
206             *output_format = VAL_SUTRS;
207             
208             wrbuf_printf(wrbuf, "%s %c %s\n", string_index, index_type,
209                          dst_buf);
210         }
211         *rec_lenp = wrbuf_len(wrbuf);
212         *rec_bufp = odr_malloc(odr, *rec_lenp);
213         memcpy(*rec_bufp, wrbuf_buf(wrbuf), *rec_lenp);
214         wrbuf_free(wrbuf, 1);
215         return 0;
216     }
217 }
218                             
219 int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr,
220                               Record rec,
221                               const char *elemsetname,
222                               oid_value input_format,
223                               oid_value *output_format,
224                               char **rec_bufp, int *rec_lenp)
225 {
226     const char *retrieval_index;
227     size_t retrieval_index_len; 
228     const char *retrieval_type;
229     size_t retrieval_type_len;
230     WRBUF wrbuf = 0;
231     zebra_rec_keys_t keys;
232     
233     /* set output variables before processing possible error states */
234     /* *rec_lenp = 0; */
235
236     /* only accept XML and SUTRS requests */
237     if (input_format != VAL_TEXT_XML && input_format != VAL_SUTRS)
238     {
239         yaz_log(YLOG_WARN, "unsupported format for element set zebra::%s", 
240                 elemsetname);
241         *output_format = VAL_NONE;
242         return YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
243     }
244
245     if (!parse_zebra_elem(elemsetname,
246                      &retrieval_index, &retrieval_index_len,
247                      &retrieval_type,  &retrieval_type_len))
248         return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
249
250     if (retrieval_type_len != 0 && retrieval_type_len != 1)
251     {
252         return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
253     }
254
255     if (retrieval_index_len)
256     {
257         char retrieval_index_cstr[256];
258
259         if (retrieval_index_len < sizeof(retrieval_index_cstr) -1)
260         {
261             memcpy(retrieval_index_cstr, retrieval_index, retrieval_index_len);
262             retrieval_index_cstr[retrieval_index_len] = '\0';
263             
264             if (zebraExplain_lookup_attr_str(zh->reg->zei,
265                                              zinfo_index_category_index,
266                                              (retrieval_type_len == 0 ? -1 : 
267                                               retrieval_type[0]),
268                                              retrieval_index_cstr) == -1)
269                 return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
270         }
271     }
272
273     keys = zebra_rec_keys_open();
274     zebra_rec_keys_set_buf(keys, rec->info[recInfo_delKeys],
275                            rec->size[recInfo_delKeys], 0);
276
277     wrbuf = wrbuf_alloc();
278     if (zebra_rec_keys_rewind(keys)){
279         size_t slen;
280         const char *str;
281         struct it_key key_in;
282
283         if (input_format == VAL_TEXT_XML)
284         {
285             *output_format = VAL_TEXT_XML;
286             wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
287                          " sysno=\"" ZINT_FORMAT "\""
288                          " set=\"zebra::index%s/\">\n",
289                          sysno, elemsetname);
290         }
291         else if (input_format == VAL_SUTRS)
292             *output_format = VAL_SUTRS;
293
294         while (zebra_rec_keys_read(keys, &str, &slen, &key_in))
295         {
296             int i;
297             int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
298             int index_type;
299             const char *db = 0;
300             const char *string_index = 0;
301             size_t string_index_len;
302             char dst_buf[IT_MAX_WORD];
303             
304             zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type, &db,
305                                     &string_index);
306             string_index_len = strlen(string_index);
307
308             /* process only if index is not defined, 
309                or if defined and matching */
310             if (retrieval_index == 0 
311                 || (string_index_len == retrieval_index_len 
312                     && !memcmp(string_index, retrieval_index,
313                                string_index_len)))
314             {
315                 /* process only if type is not defined, or is matching */
316                 if (retrieval_type == 0 
317                     || (retrieval_type_len == 1 
318                         && retrieval_type[0] == index_type))
319                 {
320                     zebra_term_untrans(zh, index_type, dst_buf, str);
321                     if (strlen(dst_buf))
322                     {
323                         if (input_format == VAL_TEXT_XML){
324                             wrbuf_printf(wrbuf, "  <index name=\"%s\"", 
325                                          string_index);
326                             
327                             wrbuf_printf(wrbuf, " type=\"%c\"", index_type);
328                             
329                             wrbuf_printf(wrbuf, " seq=\"" ZINT_FORMAT "\">", 
330                                          key_in.mem[key_in.len -1]);
331                         
332                             wrbuf_xmlputs(wrbuf, dst_buf);
333                             wrbuf_printf(wrbuf, "</index>\n");
334                         }
335                         else if (input_format == VAL_SUTRS){
336                             wrbuf_printf(wrbuf, "%s ", string_index);
337                             
338                             wrbuf_printf(wrbuf, "%c", index_type);
339                             
340                             for (i = 1; i < key_in.len; i++)
341                                 wrbuf_printf(wrbuf, " " ZINT_FORMAT, 
342                                              key_in.mem[i]);
343
344                         /* zebra_term_untrans(zh, index_type, dst_buf, str); */
345                             wrbuf_printf(wrbuf, " %s", dst_buf);
346                         
347                             wrbuf_printf(wrbuf, "\n");
348                         }
349                     }
350                     
351                 }
352             }
353         }
354         if (input_format == VAL_TEXT_XML)
355             wrbuf_printf(wrbuf, "</record>\n");
356     }
357     *rec_lenp = wrbuf_len(wrbuf);
358     *rec_bufp = odr_malloc(odr, *rec_lenp);
359     memcpy(*rec_bufp, wrbuf_buf(wrbuf), *rec_lenp);
360     wrbuf_free(wrbuf, 1);
361     zebra_rec_keys_close(keys);
362     return 0;
363 }
364
365
366 static void retrieve_puts_attr(WRBUF wrbuf, const char *name,
367                                const char *value)
368 {
369     if (value)
370     {
371         wrbuf_printf(wrbuf, " %s=\"", name);
372         wrbuf_xmlputs(wrbuf, value);
373         wrbuf_printf(wrbuf, "\"");
374     }
375 }
376
377 static void retrieve_puts_attr_int(WRBUF wrbuf, const char *name,
378                                const int value)
379 {
380     wrbuf_printf(wrbuf, " %s=\"%i\"", name, value);
381 }
382
383 static void retrieve_puts_str(WRBUF wrbuf, const char *name,
384                                const char *value)
385 {
386     if (value)
387         wrbuf_printf(wrbuf, "%s %s\n", name, value);
388 }
389
390 static void retrieve_puts_int(WRBUF wrbuf, const char *name,
391                                const int value)
392 {
393     wrbuf_printf(wrbuf, "%s %i\n", name, value);
394 }
395
396 int zebra_special_fetch(ZebraHandle zh, zint sysno, int score, ODR odr,
397                            const char *elemsetname,
398                            oid_value input_format,
399                            oid_value *output_format,
400                            char **rec_bufp, int *rec_lenp)
401 {
402     Record rec;
403     
404     /* set output variables before processing possible error states */
405     /* *rec_lenp = 0; */
406
407
408
409     /* processing zebra::meta::sysno elemset without fetching binary data */
410     if (elemsetname && 0 == strcmp(elemsetname, "meta::sysno"))
411     {
412         int ret = 0;
413         WRBUF wrbuf = wrbuf_alloc();
414         if (input_format == VAL_SUTRS)
415         {
416             wrbuf_printf(wrbuf, ZINT_FORMAT, sysno);
417             *output_format = VAL_SUTRS;
418         } 
419         else if (input_format == VAL_TEXT_XML)
420         {
421             wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
422                          " sysno=\"" ZINT_FORMAT "\"/>\n",
423                          sysno);
424             *output_format = VAL_TEXT_XML;
425         }
426         *rec_lenp = wrbuf_len(wrbuf);
427         if (*rec_lenp)
428             *rec_bufp = odr_strdup(odr, wrbuf_buf(wrbuf));
429         else
430             ret = YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
431         wrbuf_free(wrbuf, 1);
432         return ret;
433     }
434
435     /* processing special elementsetnames zebra::sort:: */
436     if (elemsetname && 0 == strncmp(elemsetname, "sort", 4))
437     {
438         return zebra_special_sort_fetch(zh, sysno, odr,
439                                         elemsetname + 4,
440                                         input_format, output_format,
441                                         rec_bufp, rec_lenp);
442     }
443
444
445     /* fetching binary record up for all other display elementsets */
446     rec = rec_get(zh->reg->records, sysno);
447     if (!rec)
448     {
449         yaz_log(YLOG_WARN, "rec_get fail on sysno=" ZINT_FORMAT, sysno);
450         return YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
451     }
452
453     /* processing special elementsetnames zebra::data */    
454     if (elemsetname && 0 == strcmp(elemsetname, "data"))
455     {
456         struct ZebraRecStream stream;
457         RecordAttr *recordAttr = rec_init_attr(zh->reg->zei, rec); 
458         zebra_create_record_stream(zh, &rec, &stream);
459         *output_format = input_format;
460         *rec_lenp = recordAttr->recordSize;
461         *rec_bufp = (char *) odr_malloc(odr, *rec_lenp);
462         stream.readf(&stream, *rec_bufp, *rec_lenp);
463         stream.destroy(&stream);
464         rec_free(&rec);
465         return 0;
466     }
467
468     /* only accept XML and SUTRS requests from now */
469     if (input_format != VAL_TEXT_XML && input_format != VAL_SUTRS)
470     {
471         yaz_log(YLOG_WARN, "unsupported format for element set zebra::%s", 
472                 elemsetname);
473         return YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
474     }
475     
476
477     /* processing special elementsetnames zebra::meta:: */
478     if (elemsetname && 0 == strcmp(elemsetname, "meta"))
479     {
480         int ret = 0;
481         WRBUF wrbuf = wrbuf_alloc();
482         RecordAttr *recordAttr = rec_init_attr(zh->reg->zei, rec); 
483
484         if (input_format == VAL_TEXT_XML)
485         {
486             *output_format = VAL_TEXT_XML;
487             
488             wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
489                          " sysno=\"" ZINT_FORMAT "\"", sysno);
490             retrieve_puts_attr(wrbuf, "base", rec->info[recInfo_databaseName]);
491             retrieve_puts_attr(wrbuf, "file", rec->info[recInfo_filename]);
492             retrieve_puts_attr(wrbuf, "type", rec->info[recInfo_fileType]);
493             if (score >= 0)
494                 retrieve_puts_attr_int(wrbuf, "score", score);
495            
496             wrbuf_printf(wrbuf,
497                          " rank=\"" ZINT_FORMAT "\""
498                          " size=\"%i\""
499                          " set=\"zebra::%s\"/>\n",
500                          recordAttr->staticrank,
501                          recordAttr->recordSize,
502                          elemsetname);
503         }
504         else if (input_format == VAL_SUTRS)
505         {
506             *output_format = VAL_SUTRS;
507             wrbuf_printf(wrbuf, "sysno " ZINT_FORMAT "\n", sysno);
508             retrieve_puts_str(wrbuf, "base", rec->info[recInfo_databaseName]);
509             retrieve_puts_str(wrbuf, "file", rec->info[recInfo_filename]);
510             retrieve_puts_str(wrbuf, "type", rec->info[recInfo_fileType]);
511             if (score >= 0)
512                 retrieve_puts_int(wrbuf, "score", score);
513
514             wrbuf_printf(wrbuf,
515                          "rank " ZINT_FORMAT "\n"
516                          "size %i\n"
517                          "set zebra::%s\n",
518                          recordAttr->staticrank,
519                          recordAttr->recordSize,
520                          elemsetname);
521         }
522         *rec_lenp = wrbuf_len(wrbuf);
523         if (*rec_lenp)
524             *rec_bufp = odr_strdup(odr, wrbuf_buf(wrbuf));
525         else
526             ret = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
527
528         wrbuf_free(wrbuf, 1);
529         rec_free(&rec);
530         return ret;
531     }
532
533     /* processing special elementsetnames zebra::index:: */
534     if (elemsetname && 0 == strncmp(elemsetname, "index", 5))
535     {
536         int ret = zebra_special_index_fetch(zh, sysno, odr, rec,
537                                             elemsetname + 5,
538                                             input_format, output_format,
539                                             rec_bufp, rec_lenp);
540         
541         rec_free(&rec);
542         return ret;
543     }
544
545     if (rec)
546         rec_free(&rec);
547     return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
548 }
549
550                           
551 int zebra_record_fetch(ZebraHandle zh, zint sysno, int score,
552                        zebra_snippets *hit_snippet, ODR odr,
553                        oid_value input_format, Z_RecordComposition *comp,
554                        oid_value *output_format,
555                        char **rec_bufp, int *rec_lenp, char **basenamep,
556                        char **addinfo)
557 {
558     Record rec;
559     char *fname, *file_type, *basename;
560     const char *elemsetname;
561     struct ZebraRecStream stream;
562     RecordAttr *recordAttr;
563     void *clientData;
564     int return_code = 0;
565
566     *basenamep = 0;
567     *addinfo = 0;
568     elemsetname = yaz_get_esn(comp);
569
570     /* processing zebra special elementset names of form 'zebra:: */
571     if (elemsetname && 0 == strncmp(elemsetname, "zebra::", 7))
572         return  zebra_special_fetch(zh, sysno, score, odr,
573                                     elemsetname + 7,
574                                     input_format, output_format,
575                                     rec_bufp, rec_lenp);
576
577
578     /* processing all other element set names */
579     rec = rec_get(zh->reg->records, sysno);
580     if (!rec)
581     {
582         yaz_log(YLOG_WARN, "rec_get fail on sysno=" ZINT_FORMAT, sysno);
583         *basenamep = 0;
584         return YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
585     }
586
587
588     recordAttr = rec_init_attr(zh->reg->zei, rec);
589
590     file_type = rec->info[recInfo_fileType];
591     fname = rec->info[recInfo_filename];
592     basename = rec->info[recInfo_databaseName];
593     *basenamep = (char *) odr_malloc (odr, strlen(basename)+1);
594     strcpy (*basenamep, basename);
595
596     yaz_log(YLOG_DEBUG, "retrieve localno=" ZINT_FORMAT " score=%d",
597             sysno, score);
598
599     zebra_create_record_stream(zh, &rec, &stream);
600     
601     {
602         /* snippets code */
603         zebra_snippets *snippet;
604         zebra_rec_keys_t reckeys = zebra_rec_keys_open();
605         RecType rt;
606         struct recRetrieveCtrl retrieveCtrl;
607
608         retrieveCtrl.stream = &stream;
609         retrieveCtrl.fname = fname;
610         retrieveCtrl.localno = sysno;
611         retrieveCtrl.staticrank = recordAttr->staticrank;
612         retrieveCtrl.score = score;
613         retrieveCtrl.recordSize = recordAttr->recordSize;
614         retrieveCtrl.odr = odr;
615         retrieveCtrl.input_format = retrieveCtrl.output_format = input_format;
616         retrieveCtrl.comp = comp;
617         retrieveCtrl.encoding = zh->record_encoding;
618         retrieveCtrl.diagnostic = 0;
619         retrieveCtrl.addinfo = 0;
620         retrieveCtrl.dh = zh->reg->dh;
621         retrieveCtrl.res = zh->res;
622         retrieveCtrl.rec_buf = 0;
623         retrieveCtrl.rec_len = -1;
624         retrieveCtrl.hit_snippet = hit_snippet;
625         retrieveCtrl.doc_snippet = zebra_snippets_create();
626
627         zebra_rec_keys_set_buf(reckeys,
628                                rec->info[recInfo_delKeys],
629                                rec->size[recInfo_delKeys], 
630                                0);
631         zebra_rec_keys_to_snippets(zh, reckeys, retrieveCtrl.doc_snippet);
632         zebra_rec_keys_close(reckeys);
633
634 #if 0
635         /* for debugging purposes */
636         yaz_log(YLOG_LOG, "DOC SNIPPET:");
637         zebra_snippets_log(retrieveCtrl.doc_snippet, YLOG_LOG);
638         yaz_log(YLOG_LOG, "HIT SNIPPET:");
639         zebra_snippets_log(retrieveCtrl.hit_snippet, YLOG_LOG);
640 #endif
641         snippet = zebra_snippets_window(retrieveCtrl.doc_snippet,
642                                         retrieveCtrl.hit_snippet,
643                                         10);
644 #if 0
645         /* for debugging purposes */
646         yaz_log(YLOG_LOG, "WINDOW SNIPPET:");
647         zebra_snippets_log(snippet, YLOG_LOG);
648 #endif
649
650         if (!(rt = recType_byName(zh->reg->recTypes, zh->res,
651                                   file_type, &clientData)))
652         {
653             return_code = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
654         }
655         else
656         {
657             (*rt->retrieve)(clientData, &retrieveCtrl);
658             return_code = retrieveCtrl.diagnostic;
659
660             *output_format = retrieveCtrl.output_format;
661             *rec_bufp = (char *) retrieveCtrl.rec_buf;
662             *rec_lenp = retrieveCtrl.rec_len;
663             *addinfo = retrieveCtrl.addinfo;
664         }
665
666         zebra_snippets_destroy(snippet);
667         zebra_snippets_destroy(retrieveCtrl.doc_snippet);
668      }
669
670     stream.destroy(&stream);
671     rec_free(&rec);
672
673     return return_code;
674 }
675
676 /*
677  * Local variables:
678  * c-basic-offset: 4
679  * indent-tabs-mode: nil
680  * End:
681  * vim: shiftwidth=4 tabstop=8 expandtab
682  */
683