c935479740a3590ae19c8c9b85782a37e66498b9
[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.84 2002-03-20 20:24:30 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 static void search_terms (ZebraHandle zh, bend_search_rr *r)
103 {
104     int count;
105     int no_terms;
106     int i;
107     struct Z_External *ext;
108     Z_SearchInfoReport *sr;
109
110     /* get no of terms for result set */
111     zebra_resultSetTerms (zh, r->setname, -1, &count, &no_terms);
112     if (!no_terms)
113         return;
114
115     r->search_info = odr_malloc (r->stream, sizeof(*r->search_info));
116
117     r->search_info->num_elements = 1;
118     r->search_info->list =
119         odr_malloc (r->stream, sizeof(*r->search_info->list));
120     r->search_info->list[0] =
121         odr_malloc (r->stream, sizeof(**r->search_info->list));
122     r->search_info->list[0]->category = 0;
123     r->search_info->list[0]->which = Z_OtherInfo_externallyDefinedInfo;
124     ext = odr_malloc (r->stream, sizeof(*ext));
125     r->search_info->list[0]->information.externallyDefinedInfo = ext;
126     ext->direct_reference =
127         yaz_oidval_to_z3950oid (r->stream, CLASS_USERINFO, VAL_SEARCHRES1);
128     ext->indirect_reference = 0;
129     ext->descriptor = 0;
130     ext->which = Z_External_searchResult1;
131     sr = odr_malloc (r->stream, sizeof(Z_SearchInfoReport));
132     ext->u.searchResult1 = sr;
133     sr->num = no_terms;
134     sr->elements = odr_malloc (r->stream, sr->num *
135                                sizeof(*sr->elements));
136     for (i = 0; i<no_terms; i++)
137     {
138         Z_Term *term;
139         const char *termz = zebra_resultSetTerms (zh, r->setname, i,
140                                                   &count, &no_terms);
141         
142         sr->elements[i] = odr_malloc (r->stream, sizeof(**sr->elements));
143         sr->elements[i]->subqueryId = 0;
144         sr->elements[i]->fullQuery = odr_malloc (r->stream, 
145                                                  sizeof(bool_t));
146         *sr->elements[i]->fullQuery = 0;
147         sr->elements[i]->subqueryExpression = 
148             odr_malloc (r->stream, sizeof(Z_QueryExpression));
149         sr->elements[i]->subqueryExpression->which = 
150             Z_QueryExpression_term;
151         sr->elements[i]->subqueryExpression->u.term =
152             odr_malloc (r->stream, sizeof(Z_QueryExpressionTerm));
153         term = odr_malloc (r->stream, sizeof(Z_Term));
154         sr->elements[i]->subqueryExpression->u.term->queryTerm = term;
155
156         term->which = Z_Term_general;
157         term->u.general = odr_malloc (r->stream, sizeof(Odr_oct));
158         term->u.general->buf = odr_strdup (r->stream, termz);
159
160         term->u.general->len = strlen (termz);
161         term->u.general->size = strlen (termz);
162         
163         sr->elements[i]->subqueryExpression->u.term->termComment = 0;
164         sr->elements[i]->subqueryInterpretation = 0;
165         sr->elements[i]->subqueryRecommendation = 0;
166         sr->elements[i]->subqueryCount = odr_intdup (r->stream, count);
167         sr->elements[i]->subqueryWeight = 0;
168         sr->elements[i]->resultsByDB = 0;
169     }
170 }
171
172 int bend_search (void *handle, bend_search_rr *r)
173 {
174     ZebraHandle zh = (ZebraHandle) handle;
175
176     r->hits = 0;
177     r->errcode = 0;
178     r->errstring = NULL;
179     
180     logf (LOG_LOG, "ResultSet '%s'", r->setname);
181     switch (r->query->which)
182     {
183     case Z_Query_type_1: case Z_Query_type_101:
184         zebra_search_rpn (zh, r->decode, r->stream, r->query->u.type_1,
185                           r->num_bases, r->basenames, r->setname);
186         r->errcode = zh->errCode;
187         r->errstring = zh->errString;
188         r->hits = zh->hits;
189         if (!r->errcode)
190             search_terms (zh, r);
191         break;
192     case Z_Query_type_2:
193         r->errcode = 107;
194         r->errstring = "type-2";
195         break;
196     default:
197         r->errcode = 107;
198     }
199     return 0;
200 }
201
202
203 int bend_fetch (void *handle, bend_fetch_rr *r)
204 {
205     ZebraHandle zh = (ZebraHandle) handle;
206     ZebraRetrievalRecord retrievalRecord;
207
208     retrievalRecord.position = r->number;
209     
210     r->last_in_set = 0;
211     zebra_records_retrieve (zh, r->stream, r->setname, r->comp,
212                             r->request_format, 1, &retrievalRecord);
213     if (zh->errCode)                  /* non Surrogate Diagnostic */
214     {
215         r->errcode = zh->errCode;
216         r->errstring = zh->errString;
217     }
218     else if (retrievalRecord.errCode) /* Surrogate Diagnostic */
219     {
220         r->surrogate_flag = 1;
221         r->errcode = retrievalRecord.errCode;
222         r->errstring = retrievalRecord.errString;
223         r->basename = retrievalRecord.base;
224     }
225     else                              /* Database Record */
226     {
227         r->errcode = 0;
228         r->basename = retrievalRecord.base;
229         r->record = retrievalRecord.buf;
230         r->len = retrievalRecord.len;
231         r->output_format = retrievalRecord.format;
232     }
233     return 0;
234 }
235
236 static int bend_scan (void *handle, bend_scan_rr *r)
237 {
238     ZebraScanEntry *entries;
239     ZebraHandle zh = (ZebraHandle) handle;
240     int is_partial, i;
241     
242     r->entries = (struct scan_entry *)
243         odr_malloc (r->stream, sizeof(*r->entries) * r->num_entries);
244     zebra_scan (zh, r->stream, r->term,
245                 r->attributeset,
246                 r->num_bases, r->basenames,
247                 &r->term_position,
248                 &r->num_entries, &entries, &is_partial);
249     if (is_partial)
250         r->status = BEND_SCAN_PARTIAL;
251     else
252         r->status = BEND_SCAN_SUCCESS;
253     for (i = 0; i < r->num_entries; i++)
254     {
255         r->entries[i].term = entries[i].term;
256         r->entries[i].occurrences = entries[i].occurrences;
257     }
258     r->errcode = zh->errCode;
259     r->errstring = zh->errString;
260     return 0;
261 }
262
263 void bend_close (void *handle)
264 {
265     zebra_close ((ZebraHandle) handle);
266     xmalloc_trav("bend_close");
267     nmem_print_list();
268 }
269
270 int bend_sort (void *handle, bend_sort_rr *rr)
271 {
272     ZebraHandle zh = (ZebraHandle) handle;
273
274     zebra_sort (zh, rr->stream,
275                 rr->num_input_setnames, (const char **) rr->input_setnames,
276                 rr->output_setname, rr->sort_sequence, &rr->sort_status);
277     rr->errcode = zh->errCode;
278     rr->errstring = zh->errString;
279     return 0;
280 }
281
282 int bend_delete (void *handle, bend_delete_rr *rr)
283 {
284     ZebraHandle zh = (ZebraHandle) handle;
285
286     rr->delete_status = zebra_deleleResultSet(zh, rr->function,
287                                               rr->num_setnames, rr->setnames,
288                                               rr->statuses);
289     return 0;
290 }
291
292 static int es_admin_request (ZebraHandle zh, Z_AdminEsRequest *r)
293 {
294     switch (r->toKeep->which)
295     {
296     case Z_ESAdminOriginPartToKeep_reIndex:
297         yaz_log(LOG_LOG, "adm-reindex");
298         break;
299     case Z_ESAdminOriginPartToKeep_truncate:
300         yaz_log(LOG_LOG, "adm-truncate");
301         break;
302     case Z_ESAdminOriginPartToKeep_drop:
303         yaz_log(LOG_LOG, "adm-drop");
304         break;
305     case Z_ESAdminOriginPartToKeep_create:
306         yaz_log(LOG_LOG, "adm-create");
307         zebra_admin_create (zh, r->toKeep->databaseName);
308         break;
309     case Z_ESAdminOriginPartToKeep_import:
310         yaz_log(LOG_LOG, "adm-import");
311         zebra_admin_import_begin (zh, r->toKeep->databaseName);
312         break;
313     case Z_ESAdminOriginPartToKeep_refresh:
314         yaz_log(LOG_LOG, "adm-refresh");
315         break;
316     case Z_ESAdminOriginPartToKeep_commit:
317         yaz_log(LOG_LOG, "adm-commit");
318         break;
319     case Z_ESAdminOriginPartToKeep_shutdown:
320         yaz_log(LOG_LOG, "shutdown");
321         zebra_admin_shutdown(zh);
322         break;
323     case Z_ESAdminOriginPartToKeep_start:
324         yaz_log(LOG_LOG, "start");
325         zebra_admin_start(zh);
326         break;
327     default:
328         yaz_log(LOG_LOG, "unknown admin");
329         zh->errCode = 1001;
330     }
331     if (r->toKeep->databaseName)
332     {
333         yaz_log(LOG_LOG, "database %s", r->toKeep->databaseName);
334     }
335     return 0;
336 }
337
338 static int es_admin (ZebraHandle zh, Z_Admin *r)
339 {
340     switch (r->which)
341     {
342     case Z_Admin_esRequest:
343         es_admin_request (zh, r->u.esRequest);
344         break;
345     case Z_Admin_taskPackage:
346         yaz_log (LOG_LOG, "adm taskpackage (unhandled)");
347         break;
348     default:
349         zh->errCode = 1001;
350         break;
351     }
352
353     return 0;
354 }
355
356 int bend_segment (void *handle, bend_segment_rr *rr)
357 {
358     ZebraHandle zh = (ZebraHandle) handle;
359     Z_Segment *segment = rr->segment;
360
361     if (segment->num_segmentRecords)
362         zebra_admin_import_segment (zh, rr->segment);
363     else
364         zebra_admin_import_end (zh);
365     return 0;
366 }
367
368 int bend_esrequest (void *handle, bend_esrequest_rr *rr)
369 {
370     ZebraHandle zh = (ZebraHandle) handle;
371     
372     yaz_log(LOG_LOG, "function: %d", *rr->esr->function);
373     if (rr->esr->packageName)
374         yaz_log(LOG_LOG, "packagename: %s", rr->esr->packageName);
375     yaz_log(LOG_LOG, "Waitaction: %d", *rr->esr->waitAction);
376
377     if (!rr->esr->taskSpecificParameters)
378     {
379         yaz_log (LOG_WARN, "No task specific parameters");
380     }
381     else if (rr->esr->taskSpecificParameters->which == Z_External_ESAdmin)
382     {
383         es_admin (zh, rr->esr->taskSpecificParameters->u.adminService);
384         rr->errcode = zh->errCode;
385         rr->errstring = zh->errString;
386     }
387     else if (rr->esr->taskSpecificParameters->which == Z_External_itemOrder)
388     {
389         Z_ItemOrder *it = rr->esr->taskSpecificParameters->u.itemOrder;
390         yaz_log (LOG_LOG, "Received ItemOrder");
391         switch (it->which)
392         {
393 #ifdef ASN_COMPILED
394         case Z_IOItemOrder_esRequest:
395 #else
396         case Z_ItemOrder_esRequest:
397 #endif
398         {
399             Z_IORequest *ir = it->u.esRequest;
400             Z_IOOriginPartToKeep *k = ir->toKeep;
401             Z_IOOriginPartNotToKeep *n = ir->notToKeep;
402             
403             if (k && k->contact)
404             {
405                 if (k->contact->name)
406                     yaz_log(LOG_LOG, "contact name %s", k->contact->name);
407                 if (k->contact->phone)
408                     yaz_log(LOG_LOG, "contact phone %s", k->contact->phone);
409                 if (k->contact->email)
410                     yaz_log(LOG_LOG, "contact email %s", k->contact->email);
411             }
412             if (k->addlBilling)
413             {
414                 yaz_log(LOG_LOG, "Billing info (not shown)");
415             }
416             
417             if (n->resultSetItem)
418             {
419                 yaz_log(LOG_LOG, "resultsetItem");
420                 yaz_log(LOG_LOG, "setId: %s", n->resultSetItem->resultSetId);
421                 yaz_log(LOG_LOG, "item: %d", *n->resultSetItem->item);
422             }
423 #ifdef ASN_COMPILED
424             if (n->itemRequest)
425             {
426                 Z_External *r = (Z_External*) n->itemRequest;
427                 ILL_ItemRequest *item_req = 0;
428                 ILL_Request *ill_req = 0;
429                 if (r->direct_reference)
430                 {
431                     oident *ent = oid_getentbyoid(r->direct_reference);
432                     if (ent)
433                         yaz_log(LOG_LOG, "OID %s", ent->desc);
434                     if (ent && ent->value == VAL_ISO_ILL_1)
435                     {
436                         yaz_log (LOG_LOG, "ItemRequest");
437                         if (r->which == ODR_EXTERNAL_single)
438                         {
439                             odr_setbuf(rr->decode,
440                                        r->u.single_ASN1_type->buf,
441                                        r->u.single_ASN1_type->len, 0);
442                             
443                             if (!ill_ItemRequest (rr->decode, &item_req, 0, 0))
444                             {
445                                 yaz_log (LOG_LOG,
446                                     "Couldn't decode ItemRequest %s near %d",
447                                        odr_errmsg(odr_geterror(rr->decode)),
448                                        odr_offset(rr->decode));
449                                 yaz_log(LOG_LOG, "PDU dump:");
450                                 odr_dumpBER(yaz_log_file(),
451                                      r->u.single_ASN1_type->buf,
452                                      r->u.single_ASN1_type->len);
453                             }
454                             if (rr->print)
455                             {
456                                 ill_ItemRequest (rr->print, &item_req, 0,
457                                     "ItemRequest");
458                                 odr_reset (rr->print);
459                             }
460                         }
461                         if (!item_req && r->which == ODR_EXTERNAL_single)
462                         {
463                             yaz_log (LOG_LOG, "ILLRequest");
464                             odr_setbuf(rr->decode,
465                                        r->u.single_ASN1_type->buf,
466                                        r->u.single_ASN1_type->len, 0);
467                             
468                             if (!ill_Request (rr->decode, &ill_req, 0, 0))
469                             {
470                                 yaz_log (LOG_LOG,
471                                     "Couldn't decode ILLRequest %s near %d",
472                                        odr_errmsg(odr_geterror(rr->decode)),
473                                        odr_offset(rr->decode));
474                                 yaz_log(LOG_LOG, "PDU dump:");
475                                 odr_dumpBER(yaz_log_file(),
476                                      r->u.single_ASN1_type->buf,
477                                      r->u.single_ASN1_type->len);
478                             }
479                             if (rr->print)
480                             {
481                                 ill_Request (rr->print, &ill_req, 0,
482                                     "ILLRequest");
483                                 odr_reset (rr->print);
484                             }
485                         }
486                     }
487                 }
488                 if (item_req)
489                 {
490                     yaz_log (LOG_LOG, "ILL protocol version = %d",
491                              *item_req->protocol_version_num);
492                 }
493             }
494 #endif
495         }
496         break;
497         }
498     }
499     else if (rr->esr->taskSpecificParameters->which == Z_External_update)
500     {
501         Z_IUUpdate *up = rr->esr->taskSpecificParameters->u.update;
502         yaz_log (LOG_LOG, "Received DB Update");
503         if (up->which == Z_IUUpdate_esRequest)
504         {
505             Z_IUUpdateEsRequest *esRequest = up->u.esRequest;
506             Z_IUOriginPartToKeep *toKeep = esRequest->toKeep;
507             Z_IUSuppliedRecords *notToKeep = esRequest->notToKeep;
508             
509             yaz_log (LOG_LOG, "action");
510             if (toKeep->action)
511             {
512                 switch (*toKeep->action)
513                 {
514                 case Z_IUOriginPartToKeep_recordInsert:
515                     yaz_log (LOG_LOG, "recordInsert");
516                     break;
517                 case Z_IUOriginPartToKeep_recordReplace:
518                     yaz_log (LOG_LOG, "recordUpdate");
519                     break;
520                 case Z_IUOriginPartToKeep_recordDelete:
521                     yaz_log (LOG_LOG, "recordDelete");
522                     break;
523                 case Z_IUOriginPartToKeep_elementUpdate:
524                     yaz_log (LOG_LOG, "elementUpdate");
525                     break;
526                 case Z_IUOriginPartToKeep_specialUpdate:
527                     yaz_log (LOG_LOG, "specialUpdate");
528                     break;
529                 case Z_ESAdminOriginPartToKeep_shutdown:
530                     yaz_log (LOG_LOG, "shutDown");
531                     break;
532                 case Z_ESAdminOriginPartToKeep_start:
533                     yaz_log (LOG_LOG, "start");
534                     break;
535                 default:
536                     yaz_log (LOG_LOG, " unknown (%d)", *toKeep->action);
537                 }
538             }
539             if (toKeep->databaseName)
540             {
541                 yaz_log (LOG_LOG, "database: %s", toKeep->databaseName);
542                 if (!strcmp(toKeep->databaseName, "fault"))
543                 {
544                     rr->errcode = 109;
545                     rr->errstring = toKeep->databaseName;
546                 }
547                 if (!strcmp(toKeep->databaseName, "accept"))
548                     rr->errcode = -1;
549             }
550             if (notToKeep)
551             {
552                 int i;
553                 for (i = 0; i < notToKeep->num; i++)
554                 {
555                     Z_External *rec = notToKeep->elements[i]->record;
556
557                     if (rec->direct_reference)
558                     {
559                         struct oident *oident;
560                         oident = oid_getentbyoid(rec->direct_reference);
561                         if (oident)
562                             yaz_log (LOG_LOG, "record %d type %s", i,
563                                      oident->desc);
564                     }
565                     switch (rec->which)
566                     {
567                     case Z_External_sutrs:
568                         if (rec->u.octet_aligned->len > 170)
569                             yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
570                                      rec->u.sutrs->len,
571                                      rec->u.sutrs->buf);
572                         else
573                             yaz_log (LOG_LOG, "%d bytes:\n%s",
574                                      rec->u.sutrs->len,
575                                      rec->u.sutrs->buf);
576                         break;
577                     case Z_External_octet:
578                         if (rec->u.octet_aligned->len > 170)
579                             yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
580                                      rec->u.octet_aligned->len,
581                                      rec->u.octet_aligned->buf);
582                         else
583                             yaz_log (LOG_LOG, "%d bytes\n%s",
584                                      rec->u.octet_aligned->len,
585                                      rec->u.octet_aligned->buf);
586                     }
587                 }
588             }
589         }
590     }
591     else
592     {
593         yaz_log (LOG_WARN, "Unknown Extended Service(%d)",
594                  rr->esr->taskSpecificParameters->which);
595         
596     }
597     return 0;
598 }
599
600 static void bend_start (struct statserv_options_block *sob)
601 {
602 #ifdef WIN32
603     
604 #else
605     if (!sob->inetd) 
606     {
607         char *pidfile = "zebrasrv.pid";
608         int fd = creat (pidfile, 0666);
609         if (fd == -1)
610             logf (LOG_WARN|LOG_ERRNO, "creat %s", pidfile);
611         else
612         {
613             char pidstr[30];
614         
615             sprintf (pidstr, "%ld", (long) getpid ());
616             write (fd, pidstr, strlen(pidstr));
617             close (fd);
618         }
619     }
620 #endif
621     if (sob->handle)
622         zebra_stop((ZebraService) sob->handle);
623     sob->handle = zebra_start(sob->configname);
624 }
625
626 static void bend_stop(struct statserv_options_block *sob)
627 {
628     if (sob->handle)
629     {
630         ZebraService service = sob->handle;
631         zebra_stop(service);
632     }
633 }
634
635 int main (int argc, char **argv)
636 {
637     struct statserv_options_block *sob;
638
639     sob = statserv_getcontrol ();
640     strcpy (sob->configname, FNAME_CONFIG);
641     sob->bend_start = bend_start;
642     sob->bend_stop = bend_stop;
643
644     statserv_setcontrol (sob);
645
646     return statserv_main (argc, argv, bend_init, bend_close);
647 }