Work on new API. Locking system re-implemented
[idzebra-moved-to-github.git] / index / zserver.c
1 /*
2  * Copyright (C) 1995-2000, Index Data 
3  * All rights reserved.
4  *
5  * $Id: zserver.c,v 1.83 2002-02-20 17:30:01 adam Exp $
6  */
7
8 #include <stdio.h>
9 #include <assert.h>
10 #include <fcntl.h>
11 #ifdef WIN32
12 #include <io.h>
13 #include <process.h>
14 #else
15 #include <unistd.h>
16 #endif
17
18 #include <yaz/data1.h>
19 #ifdef ASN_COMPILED
20 #include <yaz/ill.h>
21 #endif
22
23 #include "zserver.h"
24
25 #ifndef ZEBRASDR
26 #define ZEBRASDR 0
27 #endif
28 #if ZEBRASDR
29 #include "zebrasdr.h"
30 #endif
31
32 static int bend_sort (void *handle, bend_sort_rr *rr);
33 static int bend_delete (void *handle, bend_delete_rr *rr);
34 static int bend_esrequest (void *handle, bend_esrequest_rr *rr);
35 static int bend_segment (void *handle, bend_segment_rr *rr);
36 static int bend_search (void *handle, bend_search_rr *r);
37 static int bend_fetch (void *handle, bend_fetch_rr *r);
38 static int bend_scan (void *handle, bend_scan_rr *r);
39
40 bend_initresult *bend_init (bend_initrequest *q)
41 {
42     bend_initresult *r = (bend_initresult *)
43         odr_malloc (q->stream, sizeof(*r));
44     ZebraHandle zh;
45     struct statserv_options_block *sob;
46     char *user = NULL;
47     char *passwd = NULL;
48
49     r->errcode = 0;
50     r->errstring = 0;
51     q->bend_sort = bend_sort;
52     q->bend_delete = bend_delete;
53     q->bend_esrequest = bend_esrequest;
54     q->bend_segment = bend_segment;
55     q->bend_search = bend_search;
56     q->bend_fetch = bend_fetch;
57     q->bend_scan = bend_scan;
58
59 #if ZMBOL
60     q->implementation_name = "Z'mbol Information Server";
61     q->implementation_version = "Z'mbol " ZEBRAVER;
62 #else
63     q->implementation_name = "Zebra Information Server";
64     q->implementation_version = "Zebra " ZEBRAVER;
65 #endif
66
67     logf (LOG_DEBUG, "bend_init");
68
69     sob = statserv_getcontrol ();
70     if (!(zh = zebra_open (sob->handle)))
71     {
72         logf (LOG_FATAL, "Failed to open Zebra `%s'", sob->configname);
73         r->errcode = 1;
74         return r;
75     }
76     if (q->auth)
77     {
78         if (q->auth->which == Z_IdAuthentication_open)
79         {
80             char *openpass = xstrdup (q->auth->u.open);
81             char *cp = strchr (openpass, '/');
82             if (cp)
83             {
84                 *cp = '\0';
85                 user = nmem_strdup (odr_getmem (q->stream), openpass);
86                 passwd = nmem_strdup (odr_getmem (q->stream), cp+1);
87             }
88             xfree (openpass);
89         }
90     }
91     if (zebra_auth (zh->service, user, passwd))
92     {
93         r->errcode = 222;
94         r->errstring = user;
95         zebra_close (zh);
96         return r;
97     }
98     r->handle = zh;
99     return r;
100 }
101
102 int bend_search (void *handle, bend_search_rr *r)
103 {
104     ZebraHandle zh = (ZebraHandle) handle;
105
106     r->hits = 0;
107     r->errcode = 0;
108     r->errstring = NULL;
109     
110     logf (LOG_LOG, "ResultSet '%s'", r->setname);
111     switch (r->query->which)
112     {
113     case Z_Query_type_1: case Z_Query_type_101:
114         zebra_search_rpn (zh, r->decode, r->stream, r->query->u.type_1,
115                           r->num_bases, r->basenames, r->setname);
116         r->errcode = zh->errCode;
117         r->errstring = zh->errString;
118         r->hits = zh->hits;
119         break;
120     case Z_Query_type_2:
121         r->errcode = 107;
122         r->errstring = "type-2";
123         break;
124     default:
125         r->errcode = 107;
126     }
127     return 0;
128 }
129
130 int bend_fetch (void *handle, bend_fetch_rr *r)
131 {
132     ZebraHandle zh = (ZebraHandle) handle;
133     ZebraRetrievalRecord retrievalRecord;
134
135     retrievalRecord.position = r->number;
136     
137     r->last_in_set = 0;
138     zebra_records_retrieve (zh, r->stream, r->setname, r->comp,
139                             r->request_format, 1, &retrievalRecord);
140     if (zh->errCode)                  /* non Surrogate Diagnostic */
141     {
142         r->errcode = zh->errCode;
143         r->errstring = zh->errString;
144     }
145     else if (retrievalRecord.errCode) /* Surrogate Diagnostic */
146     {
147         r->surrogate_flag = 1;
148         r->errcode = retrievalRecord.errCode;
149         r->errstring = retrievalRecord.errString;
150         r->basename = retrievalRecord.base;
151     }
152     else                              /* Database Record */
153     {
154         r->errcode = 0;
155         r->basename = retrievalRecord.base;
156         r->record = retrievalRecord.buf;
157         r->len = retrievalRecord.len;
158         r->output_format = retrievalRecord.format;
159     }
160     return 0;
161 }
162
163 static int bend_scan (void *handle, bend_scan_rr *r)
164 {
165     ZebraScanEntry *entries;
166     ZebraHandle zh = (ZebraHandle) handle;
167     int is_partial, i;
168     
169     r->entries = (struct scan_entry *)
170         odr_malloc (r->stream, sizeof(*r->entries) * r->num_entries);
171     zebra_scan (zh, r->stream, r->term,
172                 r->attributeset,
173                 r->num_bases, r->basenames,
174                 &r->term_position,
175                 &r->num_entries, &entries, &is_partial);
176     if (is_partial)
177         r->status = BEND_SCAN_PARTIAL;
178     else
179         r->status = BEND_SCAN_SUCCESS;
180     for (i = 0; i < r->num_entries; i++)
181     {
182         r->entries[i].term = entries[i].term;
183         r->entries[i].occurrences = entries[i].occurrences;
184     }
185     r->errcode = zh->errCode;
186     r->errstring = zh->errString;
187     return 0;
188 }
189
190 void bend_close (void *handle)
191 {
192     zebra_close ((ZebraHandle) handle);
193     xmalloc_trav("bend_close");
194     nmem_print_list();
195 }
196
197 int bend_sort (void *handle, bend_sort_rr *rr)
198 {
199     ZebraHandle zh = (ZebraHandle) handle;
200
201     zebra_sort (zh, rr->stream,
202                 rr->num_input_setnames, (const char **) rr->input_setnames,
203                 rr->output_setname, rr->sort_sequence, &rr->sort_status);
204     rr->errcode = zh->errCode;
205     rr->errstring = zh->errString;
206     return 0;
207 }
208
209 int bend_delete (void *handle, bend_delete_rr *rr)
210 {
211     ZebraHandle zh = (ZebraHandle) handle;
212
213     rr->delete_status = zebra_deleleResultSet(zh, rr->function,
214                                               rr->num_setnames, rr->setnames,
215                                               rr->statuses);
216     return 0;
217 }
218
219 static int es_admin_request (ZebraHandle zh, Z_AdminEsRequest *r)
220 {
221     switch (r->toKeep->which)
222     {
223     case Z_ESAdminOriginPartToKeep_reIndex:
224         yaz_log(LOG_LOG, "adm-reindex");
225         break;
226     case Z_ESAdminOriginPartToKeep_truncate:
227         yaz_log(LOG_LOG, "adm-truncate");
228         break;
229     case Z_ESAdminOriginPartToKeep_drop:
230         yaz_log(LOG_LOG, "adm-drop");
231         break;
232     case Z_ESAdminOriginPartToKeep_create:
233         yaz_log(LOG_LOG, "adm-create");
234         zebra_admin_create (zh, r->toKeep->databaseName);
235         break;
236     case Z_ESAdminOriginPartToKeep_import:
237         yaz_log(LOG_LOG, "adm-import");
238         zebra_admin_import_begin (zh, r->toKeep->databaseName);
239         break;
240     case Z_ESAdminOriginPartToKeep_refresh:
241         yaz_log(LOG_LOG, "adm-refresh");
242         break;
243     case Z_ESAdminOriginPartToKeep_commit:
244         yaz_log(LOG_LOG, "adm-commit");
245         break;
246     case Z_ESAdminOriginPartToKeep_shutdown:
247         yaz_log(LOG_LOG, "shutdown");
248         zebra_admin_shutdown(zh);
249         break;
250     case Z_ESAdminOriginPartToKeep_start:
251         yaz_log(LOG_LOG, "start");
252         zebra_admin_start(zh);
253         break;
254     default:
255         yaz_log(LOG_LOG, "unknown admin");
256         zh->errCode = 1001;
257     }
258     if (r->toKeep->databaseName)
259     {
260         yaz_log(LOG_LOG, "database %s", r->toKeep->databaseName);
261     }
262     return 0;
263 }
264
265 static int es_admin (ZebraHandle zh, Z_Admin *r)
266 {
267     switch (r->which)
268     {
269     case Z_Admin_esRequest:
270         es_admin_request (zh, r->u.esRequest);
271         break;
272     case Z_Admin_taskPackage:
273         yaz_log (LOG_LOG, "adm taskpackage (unhandled)");
274         break;
275     default:
276         zh->errCode = 1001;
277         break;
278     }
279
280     return 0;
281 }
282
283 int bend_segment (void *handle, bend_segment_rr *rr)
284 {
285     ZebraHandle zh = (ZebraHandle) handle;
286     Z_Segment *segment = rr->segment;
287
288     if (segment->num_segmentRecords)
289         zebra_admin_import_segment (zh, rr->segment);
290     else
291         zebra_admin_import_end (zh);
292     return 0;
293 }
294
295 int bend_esrequest (void *handle, bend_esrequest_rr *rr)
296 {
297     ZebraHandle zh = (ZebraHandle) handle;
298     
299     yaz_log(LOG_LOG, "function: %d", *rr->esr->function);
300     if (rr->esr->packageName)
301         yaz_log(LOG_LOG, "packagename: %s", rr->esr->packageName);
302     yaz_log(LOG_LOG, "Waitaction: %d", *rr->esr->waitAction);
303
304     if (!rr->esr->taskSpecificParameters)
305     {
306         yaz_log (LOG_WARN, "No task specific parameters");
307     }
308     else if (rr->esr->taskSpecificParameters->which == Z_External_ESAdmin)
309     {
310         es_admin (zh, rr->esr->taskSpecificParameters->u.adminService);
311         rr->errcode = zh->errCode;
312         rr->errstring = zh->errString;
313     }
314     else if (rr->esr->taskSpecificParameters->which == Z_External_itemOrder)
315     {
316         Z_ItemOrder *it = rr->esr->taskSpecificParameters->u.itemOrder;
317         yaz_log (LOG_LOG, "Received ItemOrder");
318         switch (it->which)
319         {
320 #ifdef ASN_COMPILED
321         case Z_IOItemOrder_esRequest:
322 #else
323         case Z_ItemOrder_esRequest:
324 #endif
325         {
326             Z_IORequest *ir = it->u.esRequest;
327             Z_IOOriginPartToKeep *k = ir->toKeep;
328             Z_IOOriginPartNotToKeep *n = ir->notToKeep;
329             
330             if (k && k->contact)
331             {
332                 if (k->contact->name)
333                     yaz_log(LOG_LOG, "contact name %s", k->contact->name);
334                 if (k->contact->phone)
335                     yaz_log(LOG_LOG, "contact phone %s", k->contact->phone);
336                 if (k->contact->email)
337                     yaz_log(LOG_LOG, "contact email %s", k->contact->email);
338             }
339             if (k->addlBilling)
340             {
341                 yaz_log(LOG_LOG, "Billing info (not shown)");
342             }
343             
344             if (n->resultSetItem)
345             {
346                 yaz_log(LOG_LOG, "resultsetItem");
347                 yaz_log(LOG_LOG, "setId: %s", n->resultSetItem->resultSetId);
348                 yaz_log(LOG_LOG, "item: %d", *n->resultSetItem->item);
349             }
350 #ifdef ASN_COMPILED
351             if (n->itemRequest)
352             {
353                 Z_External *r = (Z_External*) n->itemRequest;
354                 ILL_ItemRequest *item_req = 0;
355                 ILL_Request *ill_req = 0;
356                 if (r->direct_reference)
357                 {
358                     oident *ent = oid_getentbyoid(r->direct_reference);
359                     if (ent)
360                         yaz_log(LOG_LOG, "OID %s", ent->desc);
361                     if (ent && ent->value == VAL_ISO_ILL_1)
362                     {
363                         yaz_log (LOG_LOG, "ItemRequest");
364                         if (r->which == ODR_EXTERNAL_single)
365                         {
366                             odr_setbuf(rr->decode,
367                                        r->u.single_ASN1_type->buf,
368                                        r->u.single_ASN1_type->len, 0);
369                             
370                             if (!ill_ItemRequest (rr->decode, &item_req, 0, 0))
371                             {
372                                 yaz_log (LOG_LOG,
373                                     "Couldn't decode ItemRequest %s near %d",
374                                        odr_errmsg(odr_geterror(rr->decode)),
375                                        odr_offset(rr->decode));
376                                 yaz_log(LOG_LOG, "PDU dump:");
377                                 odr_dumpBER(yaz_log_file(),
378                                      r->u.single_ASN1_type->buf,
379                                      r->u.single_ASN1_type->len);
380                             }
381                             if (rr->print)
382                             {
383                                 ill_ItemRequest (rr->print, &item_req, 0,
384                                     "ItemRequest");
385                                 odr_reset (rr->print);
386                             }
387                         }
388                         if (!item_req && r->which == ODR_EXTERNAL_single)
389                         {
390                             yaz_log (LOG_LOG, "ILLRequest");
391                             odr_setbuf(rr->decode,
392                                        r->u.single_ASN1_type->buf,
393                                        r->u.single_ASN1_type->len, 0);
394                             
395                             if (!ill_Request (rr->decode, &ill_req, 0, 0))
396                             {
397                                 yaz_log (LOG_LOG,
398                                     "Couldn't decode ILLRequest %s near %d",
399                                        odr_errmsg(odr_geterror(rr->decode)),
400                                        odr_offset(rr->decode));
401                                 yaz_log(LOG_LOG, "PDU dump:");
402                                 odr_dumpBER(yaz_log_file(),
403                                      r->u.single_ASN1_type->buf,
404                                      r->u.single_ASN1_type->len);
405                             }
406                             if (rr->print)
407                             {
408                                 ill_Request (rr->print, &ill_req, 0,
409                                     "ILLRequest");
410                                 odr_reset (rr->print);
411                             }
412                         }
413                     }
414                 }
415                 if (item_req)
416                 {
417                     yaz_log (LOG_LOG, "ILL protocol version = %d",
418                              *item_req->protocol_version_num);
419                 }
420             }
421 #endif
422         }
423         break;
424         }
425     }
426     else if (rr->esr->taskSpecificParameters->which == Z_External_update)
427     {
428         Z_IUUpdate *up = rr->esr->taskSpecificParameters->u.update;
429         yaz_log (LOG_LOG, "Received DB Update");
430         if (up->which == Z_IUUpdate_esRequest)
431         {
432             Z_IUUpdateEsRequest *esRequest = up->u.esRequest;
433             Z_IUOriginPartToKeep *toKeep = esRequest->toKeep;
434             Z_IUSuppliedRecords *notToKeep = esRequest->notToKeep;
435             
436             yaz_log (LOG_LOG, "action");
437             if (toKeep->action)
438             {
439                 switch (*toKeep->action)
440                 {
441                 case Z_IUOriginPartToKeep_recordInsert:
442                     yaz_log (LOG_LOG, "recordInsert");
443                     break;
444                 case Z_IUOriginPartToKeep_recordReplace:
445                     yaz_log (LOG_LOG, "recordUpdate");
446                     break;
447                 case Z_IUOriginPartToKeep_recordDelete:
448                     yaz_log (LOG_LOG, "recordDelete");
449                     break;
450                 case Z_IUOriginPartToKeep_elementUpdate:
451                     yaz_log (LOG_LOG, "elementUpdate");
452                     break;
453                 case Z_IUOriginPartToKeep_specialUpdate:
454                     yaz_log (LOG_LOG, "specialUpdate");
455                     break;
456                 case Z_ESAdminOriginPartToKeep_shutdown:
457                     yaz_log (LOG_LOG, "shutDown");
458                     break;
459                 case Z_ESAdminOriginPartToKeep_start:
460                     yaz_log (LOG_LOG, "start");
461                     break;
462                 default:
463                     yaz_log (LOG_LOG, " unknown (%d)", *toKeep->action);
464                 }
465             }
466             if (toKeep->databaseName)
467             {
468                 yaz_log (LOG_LOG, "database: %s", toKeep->databaseName);
469                 if (!strcmp(toKeep->databaseName, "fault"))
470                 {
471                     rr->errcode = 109;
472                     rr->errstring = toKeep->databaseName;
473                 }
474                 if (!strcmp(toKeep->databaseName, "accept"))
475                     rr->errcode = -1;
476             }
477             if (notToKeep)
478             {
479                 int i;
480                 for (i = 0; i < notToKeep->num; i++)
481                 {
482                     Z_External *rec = notToKeep->elements[i]->record;
483
484                     if (rec->direct_reference)
485                     {
486                         struct oident *oident;
487                         oident = oid_getentbyoid(rec->direct_reference);
488                         if (oident)
489                             yaz_log (LOG_LOG, "record %d type %s", i,
490                                      oident->desc);
491                     }
492                     switch (rec->which)
493                     {
494                     case Z_External_sutrs:
495                         if (rec->u.octet_aligned->len > 170)
496                             yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
497                                      rec->u.sutrs->len,
498                                      rec->u.sutrs->buf);
499                         else
500                             yaz_log (LOG_LOG, "%d bytes:\n%s",
501                                      rec->u.sutrs->len,
502                                      rec->u.sutrs->buf);
503                         break;
504                     case Z_External_octet:
505                         if (rec->u.octet_aligned->len > 170)
506                             yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
507                                      rec->u.octet_aligned->len,
508                                      rec->u.octet_aligned->buf);
509                         else
510                             yaz_log (LOG_LOG, "%d bytes\n%s",
511                                      rec->u.octet_aligned->len,
512                                      rec->u.octet_aligned->buf);
513                     }
514                 }
515             }
516         }
517     }
518     else
519     {
520         yaz_log (LOG_WARN, "Unknown Extended Service(%d)",
521                  rr->esr->taskSpecificParameters->which);
522         
523     }
524     return 0;
525 }
526
527 static void bend_start (struct statserv_options_block *sob)
528 {
529 #ifdef WIN32
530     
531 #else
532     if (!sob->inetd) 
533     {
534         char *pidfile = "zebrasrv.pid";
535         int fd = creat (pidfile, 0666);
536         if (fd == -1)
537             logf (LOG_WARN|LOG_ERRNO, "creat %s", pidfile);
538         else
539         {
540             char pidstr[30];
541         
542             sprintf (pidstr, "%ld", (long) getpid ());
543             write (fd, pidstr, strlen(pidstr));
544             close (fd);
545         }
546     }
547 #endif
548     if (sob->handle)
549         zebra_stop((ZebraService) sob->handle);
550     sob->handle = zebra_start(sob->configname);
551 }
552
553 static void bend_stop(struct statserv_options_block *sob)
554 {
555     if (sob->handle)
556     {
557         ZebraService service = sob->handle;
558         zebra_stop(service);
559     }
560 }
561
562 int main (int argc, char **argv)
563 {
564     struct statserv_options_block *sob;
565
566     sob = statserv_getcontrol ();
567     strcpy (sob->configname, FNAME_CONFIG);
568     sob->bend_start = bend_start;
569     sob->bend_stop = bend_stop;
570
571     statserv_setcontrol (sob);
572
573     return statserv_main (argc, argv, bend_init, bend_close);
574 }