Added LICENSE.
[idzebra-moved-to-github.git] / index / retrieve.c
1 /*
2  * Copyright (C) 1995-1999, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: retrieve.c,v $
7  * Revision 1.11  1999-10-29 10:00:00  adam
8  * Fixed minor bug where database name wasn't set in zebra_record_fetch.
9  *
10  * Revision 1.10  1999/05/26 07:49:13  adam
11  * C++ compilation.
12  *
13  * Revision 1.9  1999/05/20 12:57:18  adam
14  * Implemented TCL filter. Updated recctrl system.
15  *
16  * Revision 1.8  1999/03/09 16:27:49  adam
17  * More work on SDRKit integration.
18  *
19  * Revision 1.7  1999/03/02 16:15:43  quinn
20  * Added "tagsysno" and "tagrank" directives to zebra.cfg.
21  *
22  * Revision 1.6  1999/02/18 15:01:25  adam
23  * Minor changes.
24  *
25  * Revision 1.5  1999/02/17 11:29:56  adam
26  * Fixed in record_fetch. Minor updates to API.
27  *
28  * Revision 1.4  1999/02/02 14:51:07  adam
29  * Updated WIN32 code specific sections. Changed header.
30  *
31  * Revision 1.3  1998/10/28 10:54:40  adam
32  * SDRKit integration.
33  *
34  * Revision 1.2  1998/10/16 08:14:33  adam
35  * Updated record control system.
36  *
37  * Revision 1.1  1998/03/05 08:45:13  adam
38  * New result set model and modular ranking system. Moved towards
39  * descent server API. System information stored as "SGML" records.
40  *
41  */
42
43 #include <stdio.h>
44 #include <assert.h>
45
46 #include <fcntl.h>
47 #ifdef WIN32
48 #include <io.h>
49 #include <process.h>
50 #else
51 #include <unistd.h>
52 #endif
53
54 #include <recctrl.h>
55 #include "zserver.h"
56
57 #ifndef ZEBRASDR
58 #define ZEBRASDR 0
59 #endif
60
61 #if ZEBRASDR
62 #include "zebrasdr.h"
63 #endif
64
65 struct fetch_control {
66     int record_offset;
67     int record_int_pos;
68     char *record_int_buf;
69     int record_int_len;
70     int fd;
71 };
72
73 static int record_ext_read (void *fh, char *buf, size_t count)
74 {
75     struct fetch_control *fc = (struct fetch_control *) fh;
76     return read (fc->fd, buf, count);
77 }
78
79 static off_t record_ext_seek (void *fh, off_t offset)
80 {
81     struct fetch_control *fc = (struct fetch_control *) fh;
82     return lseek (fc->fd, offset + fc->record_offset, SEEK_SET);
83 }
84
85 static off_t record_ext_tell (void *fh)
86 {
87     struct fetch_control *fc = (struct fetch_control *) fh;
88     return lseek (fc->fd, 0, SEEK_CUR) - fc->record_offset;
89 }
90
91 static off_t record_int_seek (void *fh, off_t offset)
92 {
93     struct fetch_control *fc = (struct fetch_control *) fh;
94     return (off_t) (fc->record_int_pos = offset);
95 }
96
97 static off_t record_int_tell (void *fh)
98 {
99     struct fetch_control *fc = (struct fetch_control *) fh;
100     return (off_t) fc->record_int_pos;
101 }
102
103 static int record_int_read (void *fh, char *buf, size_t count)
104 {
105     struct fetch_control *fc = (struct fetch_control *) fh;
106     int l = fc->record_int_len - fc->record_int_pos;
107     if (l <= 0)
108         return 0;
109     l = (l < (int) count) ? l : count;
110     memcpy (buf, fc->record_int_buf + fc->record_int_pos, l);
111     fc->record_int_pos += l;
112     return l;
113 }
114
115 int zebra_record_fetch (ZebraHandle zh, int sysno, int score, ODR stream,
116                         oid_value input_format, Z_RecordComposition *comp,
117                         oid_value *output_format, char **rec_bufp,
118                         int *rec_lenp, char **basenamep)
119 {
120     Record rec;
121     char *fname, *file_type, *basename;
122     RecType rt;
123     struct recRetrieveCtrl retrieveCtrl;
124     char subType[128];
125     struct fetch_control fc;
126     RecordAttr *recordAttr;
127     void *clientData;
128
129     rec = rec_get (zh->records, sysno);
130     if (!rec)
131     {
132         logf (LOG_DEBUG, "rec_get fail on sysno=%d", sysno);
133         *basenamep = 0;
134         return 14;
135     }
136     recordAttr = rec_init_attr (zh->zei, rec);
137
138     file_type = rec->info[recInfo_fileType];
139     fname = rec->info[recInfo_filename];
140     basename = rec->info[recInfo_databaseName];
141     *basenamep = (char *) odr_malloc (stream, strlen(basename)+1);
142     strcpy (*basenamep, basename);
143
144     if (!(rt = recType_byName (zh->recTypes, file_type, subType, &clientData)))
145     {
146         logf (LOG_WARN, "Retrieve: Cannot handle type %s",  file_type);
147         return 14;
148     }
149     logf (LOG_DEBUG, "retrieve localno=%d score=%d", sysno, score);
150     retrieveCtrl.fh = &fc;
151     fc.fd = -1;
152     if (rec->size[recInfo_storeData] > 0)
153     {
154         retrieveCtrl.readf = record_int_read;
155         retrieveCtrl.seekf = record_int_seek;
156         retrieveCtrl.tellf = record_int_tell;
157         fc.record_int_len = rec->size[recInfo_storeData];
158         fc.record_int_buf = rec->info[recInfo_storeData];
159         fc.record_int_pos = 0;
160         logf (LOG_DEBUG, "Internal retrieve. %d bytes", fc.record_int_len);
161     }
162 #if ZEBRASDR
163     else if (*fname == '%')
164     {   
165         ZebraSdrHandle h;
166         int segment = 0, r;
167         char *cp, xname[128];
168         unsigned char *buf;
169
170         logf (LOG_DEBUG, "SDR");
171         strcpy (xname, fname+1);
172         if ((cp = strrchr (xname, '.')))
173         {
174             *cp++ = 0;
175             segment = atoi(cp);
176         }
177         h = zebraSdr_open (xname);
178         if (!h)
179         {
180             logf (LOG_WARN, "sdr open %s", xname);
181             return 0;
182         }
183         if (zebraSdr_segment (h, &segment) < 0)
184         {
185             logf (LOG_WARN, "zebraSdr_segment fail segment=%d",
186                 segment);
187             rec_rm (&rec);
188             return 14;
189         }    
190         r = zebraSdr_read (h, &buf);
191         if (r < 1)
192         {
193             logf (LOG_WARN, "zebraSdr_read fail segment=%d",
194                 segment);
195             rec_rm (&rec);
196             return 14;
197         }
198         zebraSdr_close (h);
199
200         fc.record_int_len = recordAttr->recordSize;
201         fc.record_int_buf = buf + recordAttr->recordOffset;
202         fc.record_int_pos = 0;
203
204         logf (LOG_LOG, "segment = %d len=%d off=%d",
205             segment,
206             recordAttr->recordSize,
207             recordAttr->recordOffset);
208         if (fc.record_int_len > 180)
209         {
210             logf (LOG_LOG, "%.70s", fc.record_int_buf);
211             logf (LOG_LOG, "%.70s", fc.record_int_buf +
212                 (fc.record_int_len - 70));
213         }
214         else
215             logf (LOG_LOG, "%.*s",
216                 fc.record_int_len, fc.record_int_buf);
217
218         /* the following two lines makes rec_rm delete buf */
219         rec->size[recInfo_storeData] = r;
220         rec->info[recInfo_storeData] = buf;
221
222         retrieveCtrl.readf = record_int_read;
223         retrieveCtrl.seekf = record_int_seek;
224         retrieveCtrl.tellf = record_int_tell;
225     }
226 #endif
227     else
228     {
229         if ((fc.fd = open (fname, O_BINARY|O_RDONLY)) == -1)
230         {
231             logf (LOG_WARN|LOG_ERRNO, "Retrieve fail; missing file: %s",
232                   fname);
233             rec_rm (&rec);
234             return 14;
235         }
236         fc.record_offset = recordAttr->recordOffset;
237
238         retrieveCtrl.readf = record_ext_read;
239         retrieveCtrl.seekf = record_ext_seek;
240         retrieveCtrl.tellf = record_ext_tell;
241
242         record_ext_seek (retrieveCtrl.fh, 0);
243     }
244     retrieveCtrl.subType = subType;
245     retrieveCtrl.localno = sysno;
246     retrieveCtrl.score = score;
247     retrieveCtrl.recordSize = recordAttr->recordSize;
248     retrieveCtrl.odr = stream;
249     retrieveCtrl.input_format = retrieveCtrl.output_format = input_format;
250     retrieveCtrl.comp = comp;
251     retrieveCtrl.diagnostic = 0;
252     retrieveCtrl.dh = zh->dh;
253     retrieveCtrl.res = zh->res;
254     (*rt->retrieve)(clientData, &retrieveCtrl);
255     *output_format = retrieveCtrl.output_format;
256     *rec_bufp = (char *) retrieveCtrl.rec_buf;
257     *rec_lenp = retrieveCtrl.rec_len;
258     if (fc.fd != -1)
259         close (fc.fd);
260     rec_rm (&rec);
261
262     return retrieveCtrl.diagnostic;
263 }