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