idzebra:{filename,score,size,localnumber} tags for XML
[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.18  2002-07-02 20:20:09  adam
8  * idzebra:{filename,score,size,localnumber} tags for XML
9  *
10  * Revision 1.17  2002/05/03 13:49:04  adam
11  * play with shellsort
12  *
13  * Revision 1.16  2002/04/04 20:50:37  adam
14  * Multi register works with record paths and data1 profile path
15  *
16  * Revision 1.15  2002/04/04 14:14:13  adam
17  * Multiple registers (alpha early)
18  *
19  * Revision 1.14  2001/01/22 11:41:41  adam
20  * Added support for raw retrieval (element set name "R").
21  *
22  * Revision 1.13  2000/03/20 19:08:36  adam
23  * Added remote record import using Z39.50 extended services and Segment
24  * Requests.
25  *
26  * Revision 1.12  2000/03/15 15:00:30  adam
27  * First work on threaded version.
28  *
29  * Revision 1.11  1999/10/29 10:00:00  adam
30  * Fixed minor bug where database name wasn't set in zebra_record_fetch.
31  *
32  * Revision 1.10  1999/05/26 07:49:13  adam
33  * C++ compilation.
34  *
35  * Revision 1.9  1999/05/20 12:57:18  adam
36  * Implemented TCL filter. Updated recctrl system.
37  *
38  * Revision 1.8  1999/03/09 16:27:49  adam
39  * More work on SDRKit integration.
40  *
41  * Revision 1.7  1999/03/02 16:15:43  quinn
42  * Added "tagsysno" and "tagrank" directives to zebra.cfg.
43  *
44  * Revision 1.6  1999/02/18 15:01:25  adam
45  * Minor changes.
46  *
47  * Revision 1.5  1999/02/17 11:29:56  adam
48  * Fixed in record_fetch. Minor updates to API.
49  *
50  * Revision 1.4  1999/02/02 14:51:07  adam
51  * Updated WIN32 code specific sections. Changed header.
52  *
53  * Revision 1.3  1998/10/28 10:54:40  adam
54  * SDRKit integration.
55  *
56  * Revision 1.2  1998/10/16 08:14:33  adam
57  * Updated record control system.
58  *
59  * Revision 1.1  1998/03/05 08:45:13  adam
60  * New result set model and modular ranking system. Moved towards
61  * descent server API. System information stored as "SGML" records.
62  *
63  */
64
65 #include <stdio.h>
66 #include <assert.h>
67
68 #include <fcntl.h>
69 #ifdef WIN32
70 #include <io.h>
71 #include <process.h>
72 #else
73 #include <unistd.h>
74 #endif
75
76 #include "index.h"
77 #include <direntz.h>
78
79 int zebra_record_ext_read (void *fh, char *buf, size_t count)
80 {
81     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
82     return read (fc->fd, buf, count);
83 }
84
85 off_t zebra_record_ext_seek (void *fh, off_t offset)
86 {
87     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
88     return lseek (fc->fd, offset + fc->record_offset, SEEK_SET);
89 }
90
91 off_t zebra_record_ext_tell (void *fh)
92 {
93     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
94     return lseek (fc->fd, 0, SEEK_CUR) - fc->record_offset;
95 }
96
97 off_t zebra_record_int_seek (void *fh, off_t offset)
98 {
99     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
100     return (off_t) (fc->record_int_pos = offset);
101 }
102
103 off_t zebra_record_int_tell (void *fh)
104 {
105     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
106     return (off_t) fc->record_int_pos;
107 }
108
109 int zebra_record_int_read (void *fh, char *buf, size_t count)
110 {
111     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
112     int l = fc->record_int_len - fc->record_int_pos;
113     if (l <= 0)
114         return 0;
115     l = (l < (int) count) ? l : count;
116     memcpy (buf, fc->record_int_buf + fc->record_int_pos, l);
117     fc->record_int_pos += l;
118     return l;
119 }
120
121 void zebra_record_int_end (void *fh, off_t off)
122 {
123     struct zebra_fetch_control *fc = (struct zebra_fetch_control *) fh;
124     fc->offset_end = off;
125 }
126
127 int zebra_record_fetch (ZebraHandle zh, int sysno, int score, ODR stream,
128                         oid_value input_format, Z_RecordComposition *comp,
129                         oid_value *output_format, char **rec_bufp,
130                         int *rec_lenp, char **basenamep)
131 {
132     Record rec;
133     char *fname, *file_type, *basename;
134     RecType rt;
135     struct recRetrieveCtrl retrieveCtrl;
136     char subType[128];
137     struct zebra_fetch_control fc;
138     RecordAttr *recordAttr;
139     void *clientData;
140
141     rec = rec_get (zh->reg->records, sysno);
142     if (!rec)
143     {
144         logf (LOG_DEBUG, "rec_get fail on sysno=%d", sysno);
145         *basenamep = 0;
146         return 14;
147     }
148     recordAttr = rec_init_attr (zh->reg->zei, rec);
149
150     file_type = rec->info[recInfo_fileType];
151     fname = rec->info[recInfo_filename];
152     basename = rec->info[recInfo_databaseName];
153     *basenamep = (char *) odr_malloc (stream, strlen(basename)+1);
154     strcpy (*basenamep, basename);
155
156     if (comp && comp->which == Z_RecordComp_simple &&
157         comp->u.simple->which == Z_ElementSetNames_generic)
158     {
159         if (!strcmp (comp->u.simple->u.generic, "R"))
160             file_type = "text";
161     }
162     if (!(rt = recType_byName (zh->reg->recTypes,
163                                file_type, subType, &clientData)))
164     {
165         logf (LOG_WARN, "Retrieve: Cannot handle type %s",  file_type);
166         return 14;
167     }
168     logf (LOG_DEBUG, "retrieve localno=%d score=%d", sysno, score);
169     retrieveCtrl.fh = &fc;
170     fc.fd = -1;
171     retrieveCtrl.fname = fname;
172     if (rec->size[recInfo_storeData] > 0)
173     {
174         retrieveCtrl.readf = zebra_record_int_read;
175         retrieveCtrl.seekf = zebra_record_int_seek;
176         retrieveCtrl.tellf = zebra_record_int_tell;
177         fc.record_int_len = rec->size[recInfo_storeData];
178         fc.record_int_buf = rec->info[recInfo_storeData];
179         fc.record_int_pos = 0;
180         logf (LOG_DEBUG, "Internal retrieve. %d bytes", fc.record_int_len);
181     }
182     else
183     {
184         char full_rep[1024];
185
186         if (zh->path_reg && !yaz_is_abspath (fname))
187         {
188             strcpy (full_rep, zh->path_reg);
189             strcat (full_rep, "/");
190             strcat (full_rep, fname);
191         }
192         else
193             strcpy (full_rep, fname);
194         
195
196         if ((fc.fd = open (full_rep, O_BINARY|O_RDONLY)) == -1)
197         {
198             logf (LOG_WARN|LOG_ERRNO, "Retrieve fail; missing file: %s",
199                   full_rep);
200             rec_rm (&rec);
201             return 14;
202         }
203         fc.record_offset = recordAttr->recordOffset;
204
205         retrieveCtrl.readf = zebra_record_ext_read;
206         retrieveCtrl.seekf = zebra_record_ext_seek;
207         retrieveCtrl.tellf = zebra_record_ext_tell;
208
209         zebra_record_ext_seek (retrieveCtrl.fh, 0);
210     }
211     retrieveCtrl.subType = subType;
212     retrieveCtrl.localno = sysno;
213     retrieveCtrl.score = score;
214     retrieveCtrl.recordSize = recordAttr->recordSize;
215     retrieveCtrl.odr = stream;
216     retrieveCtrl.input_format = retrieveCtrl.output_format = input_format;
217     retrieveCtrl.comp = comp;
218     retrieveCtrl.diagnostic = 0;
219     retrieveCtrl.dh = zh->reg->dh;
220     retrieveCtrl.res = zh->res;
221     retrieveCtrl.rec_buf = 0;
222     retrieveCtrl.rec_len = -1;
223     
224     (*rt->retrieve)(clientData, &retrieveCtrl);
225     *output_format = retrieveCtrl.output_format;
226     *rec_bufp = (char *) retrieveCtrl.rec_buf;
227     *rec_lenp = retrieveCtrl.rec_len;
228     if (fc.fd != -1)
229         close (fc.fd);
230     rec_rm (&rec);
231
232     return retrieveCtrl.diagnostic;
233 }