Better error reporting for result sets.
[idzebra-moved-to-github.git] / index / zebraapi.c
1 /*
2  * Copyright (C) 1995-1998, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: zebraapi.c,v $
7  * Revision 1.12  1998-11-16 10:18:10  adam
8  * Better error reporting for result sets.
9  *
10  * Revision 1.11  1998/10/16 08:14:34  adam
11  * Updated record control system.
12  *
13  * Revision 1.10  1998/09/22 10:03:42  adam
14  * Changed result sets to be persistent in the sense that they can
15  * be re-searched if needed.
16  * Fixed memory leak in rsm_or.
17  *
18  * Revision 1.9  1998/09/02 13:53:17  adam
19  * Extra parameter decode added to search routines to implement
20  * persistent queries.
21  *
22  * Revision 1.8  1998/08/24 17:29:23  adam
23  * Minor changes.
24  *
25  * Revision 1.7  1998/06/24 12:16:13  adam
26  * Support for relations on text operands. Open range support in
27  * DFA module (i.e. [-j], [g-]).
28  *
29  * Revision 1.6  1998/06/22 11:36:47  adam
30  * Added authentication check facility to zebra.
31  *
32  * Revision 1.5  1998/06/13 00:14:08  adam
33  * Minor changes.
34  *
35  * Revision 1.4  1998/06/12 12:22:12  adam
36  * Work on Zebra API.
37  *
38  * Revision 1.3  1998/05/27 16:57:44  adam
39  * Zebra returns surrogate diagnostic for single records when
40  * appropriate.
41  *
42  * Revision 1.2  1998/05/20 10:12:19  adam
43  * Implemented automatic EXPLAIN database maintenance.
44  * Modified Zebra to work with ASN.1 compiled version of YAZ.
45  *
46  * Revision 1.1  1998/03/05 08:45:13  adam
47  * New result set model and modular ranking system. Moved towards
48  * descent server API. System information stored as "SGML" records.
49  *
50  */
51
52 #include <stdio.h>
53 #ifdef WINDOWS
54 #include <io.h>
55 #include <process.h>
56 #else
57 #include <unistd.h>
58 #endif
59
60 #include <diagbib1.h>
61 #include "zserver.h"
62
63 static int zebra_register_lock (ZebraHandle zh)
64 {
65     time_t lastChange;
66     int state = zebra_server_lock_get_state(zh, &lastChange);
67
68     switch (state)
69     {
70     case 'c':
71         state = 1;
72         break;
73     default:
74         state = 0;
75     }
76     zebra_server_lock (zh, state);
77 #if USE_TIMES
78     times (&zh->tms1);
79 #endif
80     if (zh->registerState == state)
81     {
82         if (zh->registerChange >= lastChange)
83             return 0;
84         logf (LOG_LOG, "Register completely updated since last access");
85     }
86     else if (zh->registerState == -1)
87         logf (LOG_LOG, "Reading register using state %d pid=%ld", state,
88               (long) getpid());
89     else
90         logf (LOG_LOG, "Register has changed state from %d to %d",
91               zh->registerState, state);
92     zh->registerChange = lastChange;
93     if (zh->records)
94     {
95         zebraExplain_close (zh->zei, 0, 0);
96         dict_close (zh->dict);
97         sortIdx_close (zh->sortIdx);
98         if (zh->isam)
99             is_close (zh->isam);
100         if (zh->isamc)
101             isc_close (zh->isamc);
102         rec_close (&zh->records);
103     }
104     bf_cache (zh->bfs, state ? res_get (zh->res, "shadow") : NULL);
105     zh->registerState = state;
106     zh->records = rec_open (zh->bfs, 0);
107     if (!(zh->dict = dict_open (zh->bfs, FNAME_DICT, 40, 0)))
108     {
109         logf (LOG_WARN, "dict_open");
110         return -1;
111     }
112     if (!(zh->sortIdx = sortIdx_open (zh->bfs, 0)))
113     {
114         logf (LOG_WARN, "sortIdx_open");
115         return -1;
116     }
117     zh->isam = NULL;
118     zh->isamc = NULL;
119     if (!res_get_match (zh->res, "isam", "i", NULL))
120     {
121         if (!(zh->isamc = isc_open (zh->bfs, FNAME_ISAMC,
122                                     0, key_isamc_m(zh->res))))
123         {
124             logf (LOG_WARN, "isc_open");
125             return -1;
126         }
127
128     }
129     else
130     {
131         if (!(zh->isam = is_open (zh->bfs, FNAME_ISAM, key_compare, 0,
132                                   sizeof (struct it_key), zh->res)))
133         {
134             logf (LOG_WARN, "is_open");
135             return -1;
136         }
137     }
138     zh->zei = zebraExplain_open (zh->records, zh->dh, zh->res, 0, 0, 0);
139
140     return 0;
141 }
142
143 static void zebra_register_unlock (ZebraHandle zh)
144 {
145     static int waitSec = -1;
146
147 #if USE_TIMES
148     times (&zh->tms2);
149     logf (LOG_LOG, "user/system: %ld/%ld",
150                         (long) (zh->tms2.tms_utime - zh->tms1.tms_utime),
151                         (long) (zh->tms2.tms_stime - zh->tms1.tms_stime));
152 #endif
153     if (waitSec == -1)
154     {
155         char *s = res_get (zh->res, "debugRequestWait");
156         if (s)
157             waitSec = atoi (s);
158         else
159             waitSec = 0;
160     }
161 #ifdef WINDOWS
162 #else
163     if (waitSec > 0)
164         sleep (waitSec);
165 #endif
166     if (zh->registerState != -1)
167         zebra_server_unlock (zh, zh->registerState);
168 }
169
170 ZebraHandle zebra_open (const char *configName)
171 {
172     ZebraHandle zh = xmalloc (sizeof(*zh));
173
174     if (!(zh->res = res_open (configName)))
175     {
176         logf (LOG_WARN, "Failed to read resources `%s'", configName);
177         return NULL;
178     }
179     zebra_server_lock_init (zh);
180     zh->dh = data1_create ();
181     zh->bfs = bfs_create (res_get (zh->res, "register"));
182     bf_lockDir (zh->bfs, res_get (zh->res, "lockDir"));
183     data1_set_tabpath (zh->dh, res_get(zh->res, "profilePath"));
184     zh->sets = NULL;
185     zh->registerState = -1;  /* trigger open of registers! */
186     zh->registerChange = 0;
187     zh->recTypes = recTypes_init (zh->dh);
188     recTypes_default_handlers (zh->recTypes);
189
190     zh->records = NULL;
191     zh->zebra_maps = zebra_maps_open (zh->res);
192     zh->rank_classes = NULL;
193     zh->errCode = 0;
194     zh->errString = 0;
195     
196     zebraRankInstall (zh, rank1_class);
197
198     if (!res_get (zh->res, "passwd"))
199         zh->passwd_db = NULL;
200     else
201     {
202         zh->passwd_db = passwd_db_open ();
203         if (!zh->passwd_db)
204             logf (LOG_WARN|LOG_ERRNO, "passwd_db_open failed");
205         else
206             passwd_db_file (zh->passwd_db, res_get (zh->res, "passwd"));
207     }
208     return zh;
209 }
210
211 void zebra_close (ZebraHandle zh)
212 {
213     if (zh->records)
214     {
215         resultSetDestroy (zh);
216         zebraExplain_close (zh->zei, 0, 0);
217         dict_close (zh->dict);
218         sortIdx_close (zh->sortIdx);
219         if (zh->isam)
220             is_close (zh->isam);
221         if (zh->isamc)
222             isc_close (zh->isamc);
223         rec_close (&zh->records);
224         zebra_register_unlock (zh);
225     }
226     recTypes_destroy (zh->recTypes);
227     zebra_maps_close (zh->zebra_maps);
228     zebraRankDestroy (zh);
229     bfs_destroy (zh->bfs);
230     data1_destroy (zh->dh);
231     zebra_server_lock_destroy (zh);
232
233     if (zh->passwd_db)
234         passwd_db_close (zh->passwd_db);
235     res_close (zh->res);
236     xfree (zh);
237 }
238
239 void zebra_search_rpn (ZebraHandle zh, ODR stream, ODR decode,
240                        Z_RPNQuery *query, int num_bases, char **basenames, 
241                        const char *setname)
242 {
243     zebra_register_lock (zh);
244     zh->errCode = 0;
245     zh->errString = NULL;
246     zh->hits = 0;
247
248     resultSetAddRPN (zh, stream, decode, query, num_bases, basenames, setname);
249
250     zebra_register_unlock (zh);
251 }
252
253 void zebra_records_retrieve (ZebraHandle zh, ODR stream,
254                              const char *setname, Z_RecordComposition *comp,
255                              oid_value input_format, int num_recs,
256                              ZebraRetrievalRecord *recs)
257 {
258     ZebraPosSet poset;
259     int i, *pos_array;
260
261     zh->errCode = 0;
262     zh->errString = NULL;
263     pos_array = xmalloc (num_recs * sizeof(*pos_array));
264     for (i = 0; i<num_recs; i++)
265         pos_array[i] = recs[i].position;
266
267     zebra_register_lock (zh);
268
269     poset = zebraPosSetCreate (zh, setname, num_recs, pos_array);
270     if (!poset)
271     {
272         logf (LOG_DEBUG, "zebraPosSetCreate error");
273         zh->errCode = 30;
274         zh->errString = nmem_strdup (stream->mem, setname);
275     }
276     else
277     {
278         for (i = 0; i<num_recs; i++)
279         {
280             if (!poset[i].sysno)
281             {
282                 char num_str[20];
283
284                 sprintf (num_str, "%d", pos_array[i]);  
285                 zh->errCode = 13;
286                 zh->errString = nmem_strdup (stream->mem, num_str);
287                 break;
288             }
289             else
290             {
291                 recs[i].errCode =
292                     zebra_record_fetch (zh, poset[i].sysno, poset[i].score,
293                                         stream, input_format, comp,
294                                         &recs[i].format, &recs[i].buf,
295                                         &recs[i].len,
296                                         &recs[i].base);
297                 recs[i].errString = NULL;
298             }
299         }
300         zebraPosSetDestroy (zh, poset, num_recs);
301     }
302     zebra_register_unlock (zh);
303     xfree (pos_array);
304 }
305
306 void zebra_scan (ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt,
307                  oid_value attributeset,
308                  int num_bases, char **basenames,
309                  int *position, int *num_entries, ZebraScanEntry **entries,
310                  int *is_partial)
311 {
312     zh->errCode = 0;
313     zh->errString = NULL;
314     zebra_register_lock (zh);
315     rpn_scan (zh, stream, zapt, attributeset,
316               num_bases, basenames, position,
317               num_entries, entries, is_partial);
318     zebra_register_unlock (zh);
319 }
320
321 void zebra_sort (ZebraHandle zh, ODR stream,
322                  int num_input_setnames, const char **input_setnames,
323                  const char *output_setname, Z_SortKeySpecList *sort_sequence,
324                  int *sort_status)
325 {
326     zh->errCode = 0;
327     zh->errString = NULL;
328     zebra_register_lock (zh);
329     resultSetSort (zh, stream->mem, num_input_setnames, input_setnames,
330                    output_setname, sort_sequence, sort_status);
331     zebra_register_unlock (zh);
332 }
333
334 int zebra_errCode (ZebraHandle zh)
335 {
336     return zh->errCode;
337 }
338
339 const char *zebra_errString (ZebraHandle zh)
340 {
341     return diagbib1_str (zh->errCode);
342 }
343
344 char *zebra_errAdd (ZebraHandle zh)
345 {
346     return zh->errString;
347 }
348
349 int zebra_hits (ZebraHandle zh)
350 {
351     return zh->hits;
352 }
353
354 int zebra_auth (ZebraHandle zh, const char *user, const char *pass)
355 {
356     if (!zh->passwd_db || !passwd_db_auth (zh->passwd_db, user, pass))
357         return 0;
358     return 1;
359 }
360
361 void zebra_setDB (ZebraHandle zh, int num_bases, char **basenames)
362 {
363
364 }
365
366 void zebra_setRecordType (ZebraHandle zh, const char *type)
367 {
368
369 }
370
371 void zebra_setGroup (ZebraHandle zh, const char *group)
372 {
373
374 }
375
376 void zebra_admin (ZebraHandle zh, const char *command)
377 {
378
379 }