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