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