New feature: databases. Implemented as prefix to words in dictionary.
[idzebra-moved-to-github.git] / index / zserver.c
1 /*
2  * Copyright (C) 1994-1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: zserver.c,v $
7  * Revision 1.19  1995-10-17 18:02:11  adam
8  * New feature: databases. Implemented as prefix to words in dictionary.
9  *
10  * Revision 1.18  1995/10/16  14:03:09  quinn
11  * Changes to support element set names and espec1
12  *
13  * Revision 1.17  1995/10/16  09:32:40  adam
14  * More work on relational op.
15  *
16  * Revision 1.16  1995/10/13  12:26:44  adam
17  * Optimization of truncation.
18  *
19  * Revision 1.15  1995/10/12  12:40:55  adam
20  * Bug fixes in rpn_prox.
21  *
22  * Revision 1.14  1995/10/09  16:18:37  adam
23  * Function dict_lookup_grep got extra client data parameter.
24  *
25  * Revision 1.13  1995/10/06  14:38:00  adam
26  * New result set method: r_score.
27  * Local no (sysno) and score is transferred to retrieveCtrl.
28  *
29  * Revision 1.12  1995/10/06  13:52:06  adam
30  * Bug fixes. Handler may abort further scanning.
31  *
32  * Revision 1.11  1995/10/06  10:43:57  adam
33  * Scan added. 'occurrences' in scan entries not set yet.
34  *
35  * Revision 1.10  1995/10/02  16:43:32  quinn
36  * Set default resulting record type in fetch.
37  *
38  * Revision 1.9  1995/10/02  15:18:52  adam
39  * New member in recRetrieveCtrl: diagnostic.
40  *
41  * Revision 1.8  1995/09/28  09:19:47  adam
42  * xfree/xmalloc used everywhere.
43  * Extract/retrieve method seems to work for text records.
44  *
45  * Revision 1.7  1995/09/27  16:17:32  adam
46  * More work on retrieve.
47  *
48  * Revision 1.6  1995/09/08  08:53:22  adam
49  * Record buffer maintained in server_info.
50  *
51  * Revision 1.5  1995/09/06  16:11:18  adam
52  * Option: only one word key per file.
53  *
54  * Revision 1.4  1995/09/06  10:33:04  adam
55  * More work on present. Some log messages removed.
56  *
57  * Revision 1.3  1995/09/05  15:28:40  adam
58  * More work on search engine.
59  *
60  * Revision 1.2  1995/09/04  12:33:43  adam
61  * Various cleanup. YAZ util used instead.
62  *
63  * Revision 1.1  1995/09/04  09:10:41  adam
64  * More work on index add/del/update.
65  * Merge sort implemented.
66  * Initial work on z39 server.
67  *
68  */
69 #include <stdio.h>
70 #include <assert.h>
71 #include <unistd.h>
72 #include <fcntl.h>
73
74 #include <recctrl.h>
75 #include <dmalloc.h>
76 #include "zserver.h"
77
78 ZServerInfo server_info;
79
80 bend_initresult *bend_init (bend_initrequest *q)
81 {
82     static bend_initresult r;
83     static char *name = "zserver";
84
85     r.errcode = 0;
86     r.errstring = 0;
87     r.handle = name;
88
89     logf (LOG_DEBUG, "bend_init");
90     server_info.sets = NULL;
91     if (!(server_info.sys_idx_fd = open (FNAME_SYS_IDX, O_RDONLY)))
92     {
93         logf (LOG_WARN|LOG_ERRNO, "sys_idx open fail");
94         r.errcode = 1;
95         r.errstring = "sys_idx open fail";
96         return &r;
97     }
98     if (!(server_info.fileDict = dict_open (FNAME_FILE_DICT, 10, 0)))
99     {
100         logf (LOG_WARN, "dict_open fail: fname dict");
101         r.errcode = 1;
102         r.errstring = "dict_open fail: fname dict";
103         return &r;
104     }    
105     if (!(server_info.wordDict = dict_open (FNAME_WORD_DICT, 40, 0)))
106     {
107         logf (LOG_WARN, "dict_open fail: word dict");
108         dict_close (server_info.fileDict);
109         r.errcode = 1;
110         r.errstring = "dict_open fail: word dict";
111         return &r;
112     }    
113     if (!(server_info.wordIsam = is_open (FNAME_WORD_ISAM, key_compare, 0,
114                                           sizeof (struct it_key))))
115     {
116         logf (LOG_WARN, "is_open fail: word isam");
117         dict_close (server_info.wordDict);
118         dict_close (server_info.fileDict);
119         r.errcode = 1;
120         r.errstring = "is_open fail: word isam";
121         return &r;
122     }
123     server_info.odr = odr_createmem (ODR_ENCODE);
124     return &r;
125 }
126
127 bend_searchresult *bend_search (void *handle, bend_searchrequest *q, int *fd)
128 {
129     static bend_searchresult r;
130
131     r.errcode = 0;
132     r.errstring = 0;
133     r.hits = 0;
134
135     odr_reset (server_info.odr);
136     server_info.errCode = 0;
137     switch (q->query->which)
138     {
139     case Z_Query_type_1:
140         r.errcode = rpn_search (&server_info, q->query->u.type_1,
141                                 q->num_bases, q->basenames, q->setname,
142                                 &r.hits);
143         break;
144     default:
145         r.errcode = 107;
146     }
147     return &r;
148 }
149
150 static int record_read (int fd, char *buf, size_t count)
151 {
152     return read (fd, buf, count);
153 }
154
155 static int record_fetch (ZServerInfo *zi, int sysno, int score, ODR stream,
156                           oid_value input_format, Z_RecordComposition *comp,
157                           oid_value *output_format, char **rec_bufp,
158                           int *rec_lenp)
159 {
160     char record_info[SYS_IDX_ENTRY_LEN];
161     char *fname, *file_type;
162     RecType rt;
163     struct recRetrieveCtrl retrieveCtrl;
164
165     if (lseek (zi->sys_idx_fd, sysno * SYS_IDX_ENTRY_LEN,
166                SEEK_SET) == -1)
167     {
168         logf (LOG_FATAL|LOG_ERRNO, "Retrieve: lseek of sys_idx");
169         exit (1);
170     }
171     if (read (zi->sys_idx_fd, record_info, SYS_IDX_ENTRY_LEN) == -1)
172     {
173         logf (LOG_FATAL|LOG_ERRNO, "Retrieve: read of sys_idx");
174         exit (1);
175     }
176     file_type = record_info;
177     fname = record_info + strlen(record_info) + 1;
178     if (!(rt = recType_byName (file_type)))
179     {
180         logf (LOG_FATAL|LOG_ERRNO, "Retrieve: Cannot handle type %s", 
181               file_type);
182         exit (1);
183     }
184     logf (LOG_DEBUG, "retrieve localno=%d score=%d", sysno, score);
185     if ((retrieveCtrl.fd = open (fname, O_RDONLY)) == -1)
186     {
187         char *msg = "Record doesn't exist";
188         logf (LOG_WARN|LOG_ERRNO, "Retrieve: Open record file %s", fname);
189         *output_format = VAL_SUTRS;
190         *rec_bufp = msg;
191         *rec_lenp = strlen (msg);
192         return 0;     /* or 14: System error in presenting records */
193     }
194     retrieveCtrl.localno = sysno;
195     retrieveCtrl.score = score;
196     retrieveCtrl.odr = stream;
197     retrieveCtrl.readf = record_read;
198     retrieveCtrl.input_format = retrieveCtrl.output_format = input_format;
199     retrieveCtrl.comp = comp;
200     retrieveCtrl.diagnostic = 0;
201     (*rt->retrieve)(&retrieveCtrl);
202     *output_format = retrieveCtrl.output_format;
203     *rec_bufp = retrieveCtrl.rec_buf;
204     *rec_lenp = retrieveCtrl.rec_len;
205     close (retrieveCtrl.fd);
206     return retrieveCtrl.diagnostic;
207 }
208
209 bend_fetchresult *bend_fetch (void *handle, bend_fetchrequest *q, int *num)
210 {
211     static bend_fetchresult r;
212     int positions[2];
213     ZServerSetSysno *records;
214
215     r.errstring = 0;
216     r.last_in_set = 0;
217     r.basename = "base";
218
219     odr_reset (server_info.odr);
220     server_info.errCode = 0;
221
222     positions[0] = q->number;
223     records = resultSetSysnoGet (&server_info, q->setname, 1, positions);
224     if (!records)
225     {
226         logf (LOG_DEBUG, "resultSetRecordGet, error");
227         r.errcode = 13;
228         return &r;
229     }
230     if (!records[0].sysno)
231     {
232         r.errcode = 13;
233         logf (LOG_DEBUG, "Out of range. pos=%d", q->number);
234         return &r;
235     }
236     r.errcode = record_fetch (&server_info, records[0].sysno,
237                               records[0].score, q->stream, q->format,
238                               q->comp, &r.format, &r.record, &r.len);
239     resultSetSysnoDel (&server_info, records, 1);
240     return &r;
241 }
242
243 bend_deleteresult *bend_delete (void *handle, bend_deleterequest *q, int *num)
244 {
245     return 0;
246 }
247
248 bend_scanresult *bend_scan (void *handle, bend_scanrequest *q, int *num)
249 {
250     static bend_scanresult r;
251     int status;
252
253     odr_reset (server_info.odr);
254     server_info.errCode = 0;
255
256     r.errstring = 0;
257     r.term_position = q->term_position;
258     r.num_entries = q->num_entries;
259     r.errcode = rpn_scan (&server_info, server_info.odr, q->term,
260                           q->num_bases, q->basenames,
261                           &r.term_position,
262                           &r.num_entries, &r.entries, &status);
263     r.status = status;
264     return &r;
265 }
266
267 void bend_close (void *handle)
268 {
269     dict_close (server_info.fileDict);
270     dict_close (server_info.wordDict);
271     is_close (server_info.wordIsam);
272     close (server_info.sys_idx_fd);
273     return;
274 }
275
276 int main (int argc, char **argv)
277 {
278     char *base_name = "base";
279
280     if (!(common_resource = res_open (base_name)))
281     {
282         logf (LOG_FATAL, "Cannot open resource `%s'", base_name);
283         exit (1);
284     }
285     return statserv_main (argc, argv);
286 }