Updated record control system.
[idzebra-moved-to-github.git] / index / retrieve.c
1 /*
2  * Copyright (C) 1995-1998, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: retrieve.c,v $
7  * Revision 1.2  1998-10-16 08:14:33  adam
8  * Updated record control system.
9  *
10  * Revision 1.1  1998/03/05 08:45:13  adam
11  * New result set model and modular ranking system. Moved towards
12  * descent server API. System information stored as "SGML" records.
13  *
14  */
15
16 #include <stdio.h>
17 #include <assert.h>
18
19 #include <fcntl.h>
20 #ifdef WINDOWS
21 #include <io.h>
22 #include <process.h>
23 #else
24 #include <unistd.h>
25 #endif
26
27 #include <recctrl.h>
28 #include "zserver.h"
29
30 struct fetch_control {
31     int record_offset;
32     int record_int_pos;
33     char *record_int_buf;
34     int record_int_len;
35     int fd;
36 };
37
38 static int record_ext_read (void *fh, char *buf, size_t count)
39 {
40     struct fetch_control *fc = fh;
41     return read (fc->fd, buf, count);
42 }
43
44 static off_t record_ext_seek (void *fh, off_t offset)
45 {
46     struct fetch_control *fc = fh;
47     return lseek (fc->fd, offset + fc->record_offset, SEEK_SET);
48 }
49
50 static off_t record_ext_tell (void *fh)
51 {
52     struct fetch_control *fc = fh;
53     return lseek (fc->fd, 0, SEEK_CUR) - fc->record_offset;
54 }
55
56 static off_t record_int_seek (void *fh, off_t offset)
57 {
58     struct fetch_control *fc = fh;
59     return (off_t) (fc->record_int_pos = offset);
60 }
61
62 static off_t record_int_tell (void *fh)
63 {
64     struct fetch_control *fc = fh;
65     return (off_t) fc->record_int_pos;
66 }
67
68 static int record_int_read (void *fh, char *buf, size_t count)
69 {
70     struct fetch_control *fc = fh;
71     int l = fc->record_int_len - fc->record_int_pos;
72     if (l <= 0)
73         return 0;
74     l = (l < count) ? l : count;
75     memcpy (buf, fc->record_int_buf + fc->record_int_pos, l);
76     fc->record_int_pos += l;
77     return l;
78 }
79
80 int zebra_record_fetch (ZebraHandle zh, int sysno, int score, ODR stream,
81                         oid_value input_format, Z_RecordComposition *comp,
82                         oid_value *output_format, char **rec_bufp,
83                         int *rec_lenp, char **basenamep)
84 {
85     Record rec;
86     char *fname, *file_type, *basename;
87     RecType rt;
88     struct recRetrieveCtrl retrieveCtrl;
89     char subType[128];
90     struct fetch_control fc;
91     RecordAttr *recordAttr;
92
93     rec = rec_get (zh->records, sysno);
94     if (!rec)
95     {
96         logf (LOG_DEBUG, "rec_get fail on sysno=%d", sysno);
97         return 14;
98     }
99     recordAttr = rec_init_attr (zh->zei, rec);
100
101     file_type = rec->info[recInfo_fileType];
102     fname = rec->info[recInfo_filename];
103     basename = rec->info[recInfo_databaseName];
104     *basenamep = odr_malloc (stream, strlen(basename)+1);
105     strcpy (*basenamep, basename);
106
107     if (!(rt = recType_byName (zh->recTypes, file_type, subType)))
108     {
109         logf (LOG_WARN, "Retrieve: Cannot handle type %s",  file_type);
110         return 14;
111     }
112     logf (LOG_DEBUG, "retrieve localno=%d score=%d", sysno, score);
113     retrieveCtrl.fh = &fc;
114     fc.fd = -1;
115     if (rec->size[recInfo_storeData] > 0)
116     {
117         retrieveCtrl.readf = record_int_read;
118         retrieveCtrl.seekf = record_int_seek;
119         retrieveCtrl.tellf = record_int_tell;
120         fc.record_int_len = rec->size[recInfo_storeData];
121         fc.record_int_buf = rec->info[recInfo_storeData];
122         fc.record_int_pos = 0;
123         logf (LOG_DEBUG, "Internal retrieve. %d bytes", fc.record_int_len);
124     }
125     else 
126     {
127         if ((fc.fd = open (fname, O_BINARY|O_RDONLY)) == -1)
128         {
129             logf (LOG_WARN|LOG_ERRNO, "Retrieve fail; missing file: %s",
130                   fname);
131             rec_rm (&rec);
132             return 14;
133         }
134         fc.record_offset = recordAttr->recordOffset;
135
136         retrieveCtrl.readf = record_ext_read;
137         retrieveCtrl.seekf = record_ext_seek;
138         retrieveCtrl.tellf = record_ext_tell;
139
140         record_ext_seek (retrieveCtrl.fh, 0);
141     }
142     retrieveCtrl.subType = subType;
143     retrieveCtrl.localno = sysno;
144     retrieveCtrl.score = score;
145     retrieveCtrl.recordSize = recordAttr->recordSize;
146     retrieveCtrl.odr = stream;
147     retrieveCtrl.input_format = retrieveCtrl.output_format = input_format;
148     retrieveCtrl.comp = comp;
149     retrieveCtrl.diagnostic = 0;
150     retrieveCtrl.dh = zh->dh;
151     (*rt->retrieve)(&retrieveCtrl);
152     *output_format = retrieveCtrl.output_format;
153     *rec_bufp = retrieveCtrl.rec_buf;
154     *rec_lenp = retrieveCtrl.rec_len;
155     if (fc.fd != -1)
156         close (fc.fd);
157     rec_rm (&rec);
158
159     return retrieveCtrl.diagnostic;
160 }