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