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