26279985967edf10f2a6e1fb9bb9f148df25b25f
[idzebra-moved-to-github.git] / index / retrieve.c
1 /* $Id: retrieve.c,v 1.67 2007-03-19 21:50:39 adam Exp $
2    Copyright (C) 1995-2007
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 YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
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)
152         return -1;   /* must have a register type specified */
153     if (!retrieval_index_len ||
154         retrieval_index_len >= sizeof(retrieval_index_cstr)-1)
155     {
156         return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
157     }
158         
159     memcpy(retrieval_index_cstr, retrieval_index, retrieval_index_len);
160     retrieval_index_cstr[retrieval_index_len] = '\0';
161
162     ord = zebraExplain_lookup_attr_str(zh->reg->zei,
163                                        zinfo_index_category_sort,
164                                        retrieval_type[0],
165                                        retrieval_index_cstr);
166     if (ord == -1)
167         return -1;  /* is not a sort index */
168     else
169     {
170         char dst_buf[IT_MAX_WORD];
171         char str[IT_MAX_WORD];
172         int index_type;
173         const char *db = 0;
174         const char *string_index = 0;
175         WRBUF wrbuf = wrbuf_alloc();
176         
177         zebra_sort_sysno(zh->reg->sort_index, sysno);
178         zebra_sort_type(zh->reg->sort_index, ord);
179         zebra_sort_read(zh->reg->sort_index, str);
180
181         zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type, &db, &string_index);
182         
183         zebra_term_untrans(zh, index_type, dst_buf, str);
184         
185
186         if (input_format == VAL_TEXT_XML)
187         {
188             *output_format = VAL_TEXT_XML;
189             wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
190                          " sysno=\"" ZINT_FORMAT "\""
191                          " set=\"zebra::index%s/\">\n",
192                          sysno, elemsetname);
193
194             wrbuf_printf(wrbuf, "  <index name=\"%s\"", 
195                          string_index);
196             wrbuf_printf(wrbuf, " type=\"%c\">", index_type);
197             wrbuf_xmlputs(wrbuf, dst_buf);
198             wrbuf_printf(wrbuf, "</index>\n");
199             wrbuf_printf(wrbuf, "</record>\n");
200         }
201         else if (input_format == VAL_SUTRS)
202         {
203             *output_format = VAL_SUTRS;
204             
205             wrbuf_printf(wrbuf, "%s %c %s\n", string_index, index_type,
206                          dst_buf);
207         }
208         *rec_lenp = wrbuf_len(wrbuf);
209         *rec_bufp = odr_malloc(odr, *rec_lenp);
210         memcpy(*rec_bufp, wrbuf_buf(wrbuf), *rec_lenp);
211         wrbuf_destroy(wrbuf);
212         return 0;
213     }
214 }
215                             
216 int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr,
217                               Record rec,
218                               const char *elemsetname,
219                               oid_value input_format,
220                               oid_value *output_format,
221                               char **rec_bufp, int *rec_lenp)
222 {
223     const char *retrieval_index;
224     size_t retrieval_index_len; 
225     const char *retrieval_type;
226     size_t retrieval_type_len;
227     zebra_rec_keys_t keys;
228     int ret_code = 0;
229     
230     /* set output variables before processing possible error states */
231     /* *rec_lenp = 0; */
232
233     /* only accept XML and SUTRS requests */
234     if (input_format != VAL_TEXT_XML && input_format != VAL_SUTRS)
235     {
236         yaz_log(YLOG_WARN, "unsupported format for element set zebra::%s", 
237                 elemsetname);
238         *output_format = VAL_NONE;
239         return YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
240     }
241
242     if (!parse_zebra_elem(elemsetname,
243                      &retrieval_index, &retrieval_index_len,
244                      &retrieval_type,  &retrieval_type_len))
245         return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
246
247     if (retrieval_type_len != 0 && retrieval_type_len != 1)
248     {
249         return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
250     }
251
252     if (retrieval_index_len)
253     {
254         char retrieval_index_cstr[256];
255
256         if (retrieval_index_len < sizeof(retrieval_index_cstr) -1)
257         {
258             memcpy(retrieval_index_cstr, retrieval_index, retrieval_index_len);
259             retrieval_index_cstr[retrieval_index_len] = '\0';
260             
261             if (zebraExplain_lookup_attr_str(zh->reg->zei,
262                                              zinfo_index_category_index,
263                                              (retrieval_type_len == 0 ? -1 : 
264                                               retrieval_type[0]),
265                                              retrieval_index_cstr) == -1)
266                 return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
267         }
268     }
269
270     keys = zebra_rec_keys_open();
271     zebra_rec_keys_set_buf(keys, rec->info[recInfo_delKeys],
272                            rec->size[recInfo_delKeys], 0);
273
274     if (!zebra_rec_keys_rewind(keys))
275     {
276         ret_code = 
277             YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
278     }
279     else
280     {
281         size_t slen;
282         const char *str;
283         struct it_key key_in;
284         WRBUF wrbuf = wrbuf_alloc();
285     
286         if (input_format == VAL_TEXT_XML)
287         {
288             *output_format = VAL_TEXT_XML;
289             wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
290                          " sysno=\"" ZINT_FORMAT "\""
291                          " set=\"zebra::index%s/\">\n",
292                          sysno, elemsetname);
293         }
294         else if (input_format == VAL_SUTRS)
295             *output_format = VAL_SUTRS;
296
297         while (zebra_rec_keys_read(keys, &str, &slen, &key_in))
298         {
299             int i;
300             int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
301             int index_type;
302             const char *db = 0;
303             const char *string_index = 0;
304             size_t string_index_len;
305             char dst_buf[IT_MAX_WORD];
306             
307             zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type, &db,
308                                     &string_index);
309             string_index_len = strlen(string_index);
310
311             /* process only if index is not defined, 
312                or if defined and matching */
313             if (retrieval_index == 0 
314                 || (string_index_len == retrieval_index_len 
315                     && !memcmp(string_index, retrieval_index,
316                                string_index_len)))
317             {
318                 /* process only if type is not defined, or is matching */
319                 if (retrieval_type == 0 
320                     || (retrieval_type_len == 1 
321                         && retrieval_type[0] == index_type))
322                 {
323                     zebra_term_untrans(zh, index_type, dst_buf, str);
324                     if (strlen(dst_buf))
325                     {
326                         if (input_format == VAL_TEXT_XML){
327                             wrbuf_printf(wrbuf, "  <index name=\"%s\"", 
328                                          string_index);
329                             
330                             wrbuf_printf(wrbuf, " type=\"%c\"", index_type);
331                             
332                             wrbuf_printf(wrbuf, " seq=\"" ZINT_FORMAT "\">", 
333                                          key_in.mem[key_in.len -1]);
334                         
335                             wrbuf_xmlputs(wrbuf, dst_buf);
336                             wrbuf_printf(wrbuf, "</index>\n");
337                         }
338                         else if (input_format == VAL_SUTRS){
339                             wrbuf_printf(wrbuf, "%s ", string_index);
340                             
341                             wrbuf_printf(wrbuf, "%c", index_type);
342                             
343                             for (i = 1; i < key_in.len; i++)
344                                 wrbuf_printf(wrbuf, " " ZINT_FORMAT, 
345                                              key_in.mem[i]);
346
347                         /* zebra_term_untrans(zh, index_type, dst_buf, str); */
348                             wrbuf_printf(wrbuf, " %s", dst_buf);
349                         
350                             wrbuf_printf(wrbuf, "\n");
351                         }
352                     }
353                     
354                 }
355             }
356         }
357         if (input_format == VAL_TEXT_XML)
358             wrbuf_printf(wrbuf, "</record>\n");
359         *rec_lenp = wrbuf_len(wrbuf);
360         *rec_bufp = odr_malloc(odr, *rec_lenp);
361         memcpy(*rec_bufp, wrbuf_buf(wrbuf), *rec_lenp);
362         wrbuf_destroy(wrbuf);
363     }
364     zebra_rec_keys_close(keys);
365     return ret_code;
366 }
367
368
369 static void retrieve_puts_attr(WRBUF wrbuf, const char *name,
370                                const char *value)
371 {
372     if (value)
373     {
374         wrbuf_printf(wrbuf, " %s=\"", name);
375         wrbuf_xmlputs(wrbuf, value);
376         wrbuf_printf(wrbuf, "\"");
377     }
378 }
379
380 static void retrieve_puts_attr_int(WRBUF wrbuf, const char *name,
381                                const int value)
382 {
383     wrbuf_printf(wrbuf, " %s=\"%i\"", name, value);
384 }
385
386 static void retrieve_puts_str(WRBUF wrbuf, const char *name,
387                                const char *value)
388 {
389     if (value)
390         wrbuf_printf(wrbuf, "%s %s\n", name, value);
391 }
392
393 static void retrieve_puts_int(WRBUF wrbuf, const char *name,
394                                const int value)
395 {
396     wrbuf_printf(wrbuf, "%s %i\n", name, value);
397 }
398
399 int zebra_special_fetch(ZebraHandle zh, zint sysno, int score, ODR odr,
400                            const char *elemsetname,
401                            oid_value input_format,
402                            oid_value *output_format,
403                            char **rec_bufp, int *rec_lenp)
404 {
405     Record rec;
406     
407     /* set output variables before processing possible error states */
408     /* *rec_lenp = 0; */
409
410
411
412     /* processing zebra::meta::sysno elemset without fetching binary data */
413     if (elemsetname && 0 == strcmp(elemsetname, "meta::sysno"))
414     {
415         int ret = 0;
416         WRBUF wrbuf = wrbuf_alloc();
417         if (input_format == VAL_SUTRS)
418         {
419             wrbuf_printf(wrbuf, ZINT_FORMAT, sysno);
420             *output_format = VAL_SUTRS;
421         } 
422         else if (input_format == VAL_TEXT_XML)
423         {
424             wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
425                          " sysno=\"" ZINT_FORMAT "\"/>\n",
426                          sysno);
427             *output_format = VAL_TEXT_XML;
428         }
429         *rec_lenp = wrbuf_len(wrbuf);
430         if (*rec_lenp)
431             *rec_bufp = odr_strdup(odr, wrbuf_cstr(wrbuf));
432         else
433             ret = YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
434         wrbuf_destroy(wrbuf);
435         return ret;
436     }
437
438     /* processing special elementsetname zebra::index:: for sort elements */
439     if (elemsetname && 0 == strncmp(elemsetname, "index", 5))
440     {
441         int ret = zebra_special_sort_fetch(zh, sysno, odr,
442                                            elemsetname + 5,
443                                            input_format, output_format,
444                                            rec_bufp, rec_lenp);
445         if (ret != -1)
446             return ret;
447         /* not a sort index so we continue to get the full record */
448     }
449
450
451     /* fetching binary record up for all other display elementsets */
452     rec = rec_get(zh->reg->records, sysno);
453     if (!rec)
454     {
455         yaz_log(YLOG_WARN, "rec_get fail on sysno=" ZINT_FORMAT, sysno);
456         return YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
457     }
458
459     /* processing special elementsetnames zebra::data */    
460     if (elemsetname && 0 == strcmp(elemsetname, "data"))
461     {
462         struct ZebraRecStream stream;
463         RecordAttr *recordAttr = rec_init_attr(zh->reg->zei, rec); 
464         zebra_create_record_stream(zh, &rec, &stream);
465         *output_format = input_format;
466         *rec_lenp = recordAttr->recordSize;
467         *rec_bufp = (char *) odr_malloc(odr, *rec_lenp);
468         stream.readf(&stream, *rec_bufp, *rec_lenp);
469         stream.destroy(&stream);
470         rec_free(&rec);
471         return 0;
472     }
473
474     /* only accept XML and SUTRS requests from now */
475     if (input_format != VAL_TEXT_XML && input_format != VAL_SUTRS)
476     {
477         yaz_log(YLOG_WARN, "unsupported format for element set zebra::%s", 
478                 elemsetname);
479         return YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
480     }
481     
482
483     /* processing special elementsetnames zebra::meta:: */
484     if (elemsetname && 0 == strcmp(elemsetname, "meta"))
485     {
486         int ret = 0;
487         WRBUF wrbuf = wrbuf_alloc();
488         RecordAttr *recordAttr = rec_init_attr(zh->reg->zei, rec); 
489
490         if (input_format == VAL_TEXT_XML)
491         {
492             *output_format = VAL_TEXT_XML;
493             
494             wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
495                          " sysno=\"" ZINT_FORMAT "\"", sysno);
496             retrieve_puts_attr(wrbuf, "base", rec->info[recInfo_databaseName]);
497             retrieve_puts_attr(wrbuf, "file", rec->info[recInfo_filename]);
498             retrieve_puts_attr(wrbuf, "type", rec->info[recInfo_fileType]);
499             if (score >= 0)
500                 retrieve_puts_attr_int(wrbuf, "score", score);
501            
502             wrbuf_printf(wrbuf,
503                          " rank=\"" ZINT_FORMAT "\""
504                          " size=\"%i\""
505                          " set=\"zebra::%s\"/>\n",
506                          recordAttr->staticrank,
507                          recordAttr->recordSize,
508                          elemsetname);
509         }
510         else if (input_format == VAL_SUTRS)
511         {
512             *output_format = VAL_SUTRS;
513             wrbuf_printf(wrbuf, "sysno " ZINT_FORMAT "\n", sysno);
514             retrieve_puts_str(wrbuf, "base", rec->info[recInfo_databaseName]);
515             retrieve_puts_str(wrbuf, "file", rec->info[recInfo_filename]);
516             retrieve_puts_str(wrbuf, "type", rec->info[recInfo_fileType]);
517             if (score >= 0)
518                 retrieve_puts_int(wrbuf, "score", score);
519
520             wrbuf_printf(wrbuf,
521                          "rank " ZINT_FORMAT "\n"
522                          "size %i\n"
523                          "set zebra::%s\n",
524                          recordAttr->staticrank,
525                          recordAttr->recordSize,
526                          elemsetname);
527         }
528         *rec_lenp = wrbuf_len(wrbuf);
529         if (*rec_lenp)
530             *rec_bufp = odr_strdup(odr, wrbuf_cstr(wrbuf));
531         else
532             ret = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
533
534         wrbuf_destroy(wrbuf);
535         rec_free(&rec);
536         return ret;
537     }
538
539     /* processing special elementsetnames zebra::index:: */
540     if (elemsetname && 0 == strncmp(elemsetname, "index", 5))
541     {
542         int ret = zebra_special_index_fetch(zh, sysno, odr, rec,
543                                             elemsetname + 5,
544                                             input_format, output_format,
545                                             rec_bufp, rec_lenp);
546         
547         rec_free(&rec);
548         return ret;
549     }
550
551     if (rec)
552         rec_free(&rec);
553     return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
554 }
555
556                           
557 int zebra_record_fetch(ZebraHandle zh, zint sysno, int score,
558                        zebra_snippets *hit_snippet, ODR odr,
559                        oid_value input_format, Z_RecordComposition *comp,
560                        oid_value *output_format,
561                        char **rec_bufp, int *rec_lenp, char **basenamep,
562                        char **addinfo)
563 {
564     Record rec;
565     char *fname, *file_type, *basename;
566     const char *elemsetname;
567     struct ZebraRecStream stream;
568     RecordAttr *recordAttr;
569     void *clientData;
570     int return_code = 0;
571
572     *basenamep = 0;
573     *addinfo = 0;
574     elemsetname = yaz_get_esn(comp);
575
576     /* processing zebra special elementset names of form 'zebra:: */
577     if (elemsetname && 0 == strncmp(elemsetname, "zebra::", 7))
578         return  zebra_special_fetch(zh, sysno, score, odr,
579                                     elemsetname + 7,
580                                     input_format, output_format,
581                                     rec_bufp, rec_lenp);
582
583
584     /* processing all other element set names */
585     rec = rec_get(zh->reg->records, sysno);
586     if (!rec)
587     {
588         yaz_log(YLOG_WARN, "rec_get fail on sysno=" ZINT_FORMAT, sysno);
589         *basenamep = 0;
590         return YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
591     }
592
593
594     recordAttr = rec_init_attr(zh->reg->zei, rec);
595
596     file_type = rec->info[recInfo_fileType];
597     fname = rec->info[recInfo_filename];
598     basename = rec->info[recInfo_databaseName];
599     *basenamep = (char *) odr_malloc (odr, strlen(basename)+1);
600     strcpy (*basenamep, basename);
601
602     yaz_log(YLOG_DEBUG, "retrieve localno=" ZINT_FORMAT " score=%d",
603             sysno, score);
604
605     return_code = zebra_create_record_stream(zh, &rec, &stream);
606
607     if (rec)
608     {
609         zebra_snippets *snippet;
610         zebra_rec_keys_t reckeys = zebra_rec_keys_open();
611         RecType rt;
612         struct recRetrieveCtrl retrieveCtrl;
613
614         retrieveCtrl.stream = &stream;
615         retrieveCtrl.fname = fname;
616         retrieveCtrl.localno = sysno;
617         retrieveCtrl.staticrank = recordAttr->staticrank;
618         retrieveCtrl.score = score;
619         retrieveCtrl.recordSize = recordAttr->recordSize;
620         retrieveCtrl.odr = odr;
621         retrieveCtrl.input_format = retrieveCtrl.output_format = input_format;
622         retrieveCtrl.comp = comp;
623         retrieveCtrl.encoding = zh->record_encoding;
624         retrieveCtrl.diagnostic = 0;
625         retrieveCtrl.addinfo = 0;
626         retrieveCtrl.dh = zh->reg->dh;
627         retrieveCtrl.res = zh->res;
628         retrieveCtrl.rec_buf = 0;
629         retrieveCtrl.rec_len = -1;
630         retrieveCtrl.hit_snippet = hit_snippet;
631         retrieveCtrl.doc_snippet = zebra_snippets_create();
632
633         zebra_rec_keys_set_buf(reckeys,
634                                rec->info[recInfo_delKeys],
635                                rec->size[recInfo_delKeys], 
636                                0);
637         zebra_rec_keys_to_snippets(zh, reckeys, retrieveCtrl.doc_snippet);
638         zebra_rec_keys_close(reckeys);
639
640 #if 0
641         /* for debugging purposes */
642         yaz_log(YLOG_LOG, "DOC SNIPPET:");
643         zebra_snippets_log(retrieveCtrl.doc_snippet, YLOG_LOG);
644         yaz_log(YLOG_LOG, "HIT SNIPPET:");
645         zebra_snippets_log(retrieveCtrl.hit_snippet, YLOG_LOG);
646 #endif
647         snippet = zebra_snippets_window(retrieveCtrl.doc_snippet,
648                                         retrieveCtrl.hit_snippet,
649                                         10);
650 #if 0
651         /* for debugging purposes */
652         yaz_log(YLOG_LOG, "WINDOW SNIPPET:");
653         zebra_snippets_log(snippet, YLOG_LOG);
654 #endif
655
656         if (!(rt = recType_byName(zh->reg->recTypes, zh->res,
657                                   file_type, &clientData)))
658         {
659             char addinfo_str[100];
660
661             sprintf(addinfo_str, "Could not handle record type %.40s",
662                     file_type);
663                     
664             *addinfo = odr_strdup(odr, addinfo_str);
665             return_code = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
666         }
667         else
668         {
669             (*rt->retrieve)(clientData, &retrieveCtrl);
670             return_code = retrieveCtrl.diagnostic;
671
672             *output_format = retrieveCtrl.output_format;
673             *rec_bufp = (char *) retrieveCtrl.rec_buf;
674             *rec_lenp = retrieveCtrl.rec_len;
675             *addinfo = retrieveCtrl.addinfo;
676         }
677
678         zebra_snippets_destroy(snippet);
679         zebra_snippets_destroy(retrieveCtrl.doc_snippet);
680
681         stream.destroy(&stream);
682         rec_free(&rec);
683     }
684
685     return return_code;
686 }
687
688 /*
689  * Local variables:
690  * c-basic-offset: 4
691  * indent-tabs-mode: nil
692  * End:
693  * vim: shiftwidth=4 tabstop=8 expandtab
694  */
695