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