Common stream reader interface for record filters (struct ZebraRecStream).
[idzebra-moved-to-github.git] / index / retrieve.c
1 /* $Id: retrieve.c,v 1.44 2006-08-22 13:39:27 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 <direntz.h>
37
38 int zebra_record_fetch (ZebraHandle zh, SYSNO sysno, int score,
39                         zebra_snippets *hit_snippet, ODR odr,
40                         oid_value input_format, Z_RecordComposition *comp,
41                         oid_value *output_format, char **rec_bufp,
42                         int *rec_lenp, char **basenamep,
43                         char **addinfo)
44 {
45     Record rec;
46     char *fname, *file_type, *basename;
47     RecType rt;
48     struct recRetrieveCtrl retrieveCtrl;
49     struct ZebraRecStream stream;
50     RecordAttr *recordAttr;
51     void *clientData;
52     int raw_mode = 0;
53
54     *basenamep = 0;
55     *addinfo = 0;
56     if (comp && comp->which == Z_RecordComp_simple &&
57         comp->u.simple->which == Z_ElementSetNames_generic && 
58         !strcmp (comp->u.simple->u.generic, "_sysno_"))
59     {
60         char rec_str[60];
61         sprintf(rec_str, ZINT_FORMAT, sysno);
62         *output_format = VAL_SUTRS;
63         *rec_lenp = strlen(rec_str);
64         *rec_bufp = odr_strdup(odr, rec_str);
65         return 0;
66     }
67     rec = rec_get (zh->reg->records, sysno);
68     if (!rec)
69     {
70         yaz_log (YLOG_DEBUG, "rec_get fail on sysno=" ZINT_FORMAT, sysno);
71         *basenamep = 0;
72         return 14;
73     }
74     recordAttr = rec_init_attr (zh->reg->zei, rec);
75
76     file_type = rec->info[recInfo_fileType];
77     fname = rec->info[recInfo_filename];
78     basename = rec->info[recInfo_databaseName];
79     *basenamep = (char *) odr_malloc (odr, strlen(basename)+1);
80     strcpy (*basenamep, basename);
81
82     if (comp && comp->which == Z_RecordComp_simple &&
83         comp->u.simple->which == Z_ElementSetNames_generic && 
84         !strcmp (comp->u.simple->u.generic, "_storekeys_"))
85     {
86         WRBUF wrbuf = wrbuf_alloc();
87         zebra_rec_keys_t keys = zebra_rec_keys_open();
88         zebra_rec_keys_set_buf(keys,
89                                rec->info[recInfo_delKeys],
90                                rec->size[recInfo_delKeys],
91                                0);
92         if (zebra_rec_keys_rewind(keys))
93         {
94             size_t slen;
95             const char *str;
96             struct it_key key_in;
97             while(zebra_rec_keys_read(keys, &str, &slen, &key_in))
98             {
99                 int i;
100                 int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
101                 int index_type;
102                 const char *db = 0;
103                 int set = 0;
104                 int use = 0;
105                 const char *string_index = 0;
106                 char dst_buf[IT_MAX_WORD];
107                 
108                 zebraExplain_lookup_ord(zh->reg->zei, ord, &index_type, &db,
109                                         &string_index);
110
111                 if (string_index)
112                     wrbuf_printf(wrbuf, "%s", string_index);
113                 else
114                     wrbuf_printf(wrbuf, "set=%d,use=%d", set, use);
115
116                 zebra_term_untrans(zh, index_type, dst_buf, str);
117                 wrbuf_printf(wrbuf, " %s", dst_buf);
118
119                 for (i = 1; i < key_in.len; i++)
120                     wrbuf_printf(wrbuf, " " ZINT_FORMAT, key_in.mem[i]);
121                 wrbuf_printf(wrbuf, "\n");
122
123             }
124         }
125         *output_format = VAL_SUTRS;
126         *rec_lenp = wrbuf_len(wrbuf);
127         *rec_bufp = odr_malloc(odr, *rec_lenp);
128         memcpy(*rec_bufp, wrbuf_buf(wrbuf), *rec_lenp);
129         wrbuf_free(wrbuf, 1);
130         zebra_rec_keys_close(keys);
131         return 0;
132     }
133     if (comp && comp->which == Z_RecordComp_simple &&
134         comp->u.simple->which == Z_ElementSetNames_generic && 
135         !strcmp (comp->u.simple->u.generic, "R"))
136     {
137         raw_mode = 1;
138     }
139     if (!(rt = recType_byName (zh->reg->recTypes, zh->res,
140                                file_type, &clientData)))
141     {
142         yaz_log (YLOG_WARN, "Retrieve: Cannot handle type %s",  file_type);
143         return 14;
144     }
145     yaz_log (YLOG_DEBUG, "retrieve localno=" ZINT_FORMAT " score=%d", sysno,score);
146     retrieveCtrl.stream = &stream;
147     retrieveCtrl.fname = fname;
148     if (rec->size[recInfo_storeData] > 0)
149     {
150         zebra_create_stream_mem(&stream, rec->info[recInfo_storeData],
151                                 rec->size[recInfo_storeData]);
152         if (raw_mode)
153         {
154             *output_format = VAL_SUTRS;
155             *rec_lenp = rec->size[recInfo_storeData];
156             *rec_bufp = (char *) odr_malloc(odr, *rec_lenp);
157             memcpy(*rec_bufp, rec->info[recInfo_storeData], *rec_lenp);
158             rec_rm (&rec);
159             stream.destroy(&stream);
160             return 0;
161         }
162     }
163     else
164     {
165         char full_rep[1024];
166         int fd;
167
168         if (zh->path_reg && !yaz_is_abspath (fname))
169         {
170             strcpy (full_rep, zh->path_reg);
171             strcat (full_rep, "/");
172             strcat (full_rep, fname);
173         }
174         else
175             strcpy (full_rep, fname);
176
177         if ((fd = open (full_rep, O_BINARY|O_RDONLY)) == -1)
178         {
179             yaz_log (YLOG_WARN|YLOG_ERRNO, "Retrieve fail; missing file: %s",
180                   full_rep);
181             rec_rm (&rec);
182             stream.destroy(&stream);
183             return 14;
184         }
185
186         zebra_create_stream_fd(&stream, fd, recordAttr->recordOffset);
187         if (raw_mode)
188         {
189             *output_format = VAL_SUTRS;
190             *rec_lenp = recordAttr->recordSize;
191             *rec_bufp = (char *) odr_malloc(odr, *rec_lenp);
192             stream.readf(&stream, *rec_bufp, *rec_lenp);
193             rec_rm (&rec);
194             stream.destroy(&stream);
195             return 0;
196         }
197     }
198     retrieveCtrl.localno = sysno;
199     retrieveCtrl.staticrank = recordAttr->staticrank;
200     retrieveCtrl.score = score;
201     retrieveCtrl.recordSize = recordAttr->recordSize;
202     retrieveCtrl.odr = odr;
203     retrieveCtrl.input_format = retrieveCtrl.output_format = input_format;
204     retrieveCtrl.comp = comp;
205     retrieveCtrl.encoding = zh->record_encoding;
206     retrieveCtrl.diagnostic = 0;
207     retrieveCtrl.addinfo = 0;
208     retrieveCtrl.dh = zh->reg->dh;
209     retrieveCtrl.res = zh->res;
210     retrieveCtrl.rec_buf = 0;
211     retrieveCtrl.rec_len = -1;
212     retrieveCtrl.hit_snippet = hit_snippet;
213     retrieveCtrl.doc_snippet = zebra_snippets_create();
214     
215     if (1)
216     {
217         /* snippets code */
218         zebra_snippets *snippet;
219
220         zebra_rec_keys_t reckeys = zebra_rec_keys_open();
221         
222         zebra_rec_keys_set_buf(reckeys,
223                                rec->info[recInfo_delKeys],
224                                rec->size[recInfo_delKeys], 
225                                0);
226         zebra_snippets_rec_keys(zh, reckeys, retrieveCtrl.doc_snippet);
227         zebra_rec_keys_close(reckeys);
228
229
230 #if 0
231         /* for debugging purposes */
232         yaz_log(YLOG_LOG, "DOC SNIPPET:");
233         zebra_snippets_log(retrieveCtrl.doc_snippet, YLOG_LOG);
234         yaz_log(YLOG_LOG, "HIT SNIPPET:");
235         zebra_snippets_log(retrieveCtrl.hit_snippet, YLOG_LOG);
236 #endif
237         snippet = zebra_snippets_window(retrieveCtrl.doc_snippet,
238                                         retrieveCtrl.hit_snippet,
239                                         10);
240 #if 0
241         /* for debugging purposes */
242         yaz_log(YLOG_LOG, "WINDOW SNIPPET:");
243         zebra_snippets_log(snippet, YLOG_LOG);
244 #endif
245         (*rt->retrieve)(clientData, &retrieveCtrl);
246
247         zebra_snippets_destroy(snippet);
248     }
249     else
250     {
251         (*rt->retrieve)(clientData, &retrieveCtrl);
252     }
253
254     zebra_snippets_destroy(retrieveCtrl.doc_snippet);
255
256     *output_format = retrieveCtrl.output_format;
257     *rec_bufp = (char *) retrieveCtrl.rec_buf;
258     *rec_lenp = retrieveCtrl.rec_len;
259
260     stream.destroy(&stream);
261
262     rec_rm (&rec);
263
264     *addinfo = retrieveCtrl.addinfo;
265     return retrieveCtrl.diagnostic;
266 }
267
268 /*
269  * Local variables:
270  * c-basic-offset: 4
271  * indent-tabs-mode: nil
272  * End:
273  * vim: shiftwidth=4 tabstop=8 expandtab
274  */
275