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