Reports Database unavailable unless "Default" is specified.
[yaz-moved-to-github.git] / ztest / ztest.c
1 /*
2  * Copyright (c) 1995-2002, Index Data.
3  * See the file LICENSE for details.
4  *
5  * $Id: ztest.c,v 1.47 2002-01-17 21:04:24 adam Exp $
6  */
7
8 /*
9  * Demonstration of simple server
10  */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <ctype.h>
15
16 #include <yaz/backend.h>
17 #include <yaz/log.h>
18
19 #if YAZ_MODULE_ill
20 #include <yaz/ill.h>
21 #endif
22
23 Z_GenericRecord *read_grs1(FILE *f, ODR o);
24
25 int ztest_search (void *handle, bend_search_rr *rr);
26 int ztest_sort (void *handle, bend_sort_rr *rr);
27 int ztest_present (void *handle, bend_present_rr *rr);
28 int ztest_esrequest (void *handle, bend_esrequest_rr *rr);
29 int ztest_delete (void *handle, bend_delete_rr *rr);
30
31 int ztest_search (void *handle, bend_search_rr *rr)
32 {
33     if (rr->num_bases != 1)
34     {
35         rr->errcode = 23;
36         return 0;
37     }
38     if (strcmp (rr->basenames[0], "Default"))
39     {
40         rr->errcode = 109;
41         rr->errstring = rr->basenames[0];
42         return 0;
43     }
44     rr->hits = rand() % 22;
45     return 0;
46 }
47
48 int ztest_present (void *handle, bend_present_rr *rr)
49 {
50     return 0;
51 }
52
53 int ztest_esrequest (void *handle, bend_esrequest_rr *rr)
54 {
55     /* user-defined handle - created in bend_init */
56     int *counter = (int*) handle;  
57
58     yaz_log(LOG_LOG, "ESRequest no %d", *counter);
59
60     (*counter)++;
61
62     if (rr->esr->packageName)
63         yaz_log(LOG_LOG, "packagename: %s", rr->esr->packageName);
64     yaz_log(LOG_LOG, "Waitaction: %d", *rr->esr->waitAction);
65
66
67     yaz_log(LOG_LOG, "function: %d", *rr->esr->function);
68
69     if (!rr->esr->taskSpecificParameters)
70     {
71         yaz_log (LOG_WARN, "No task specific parameters");
72     }
73     else if (rr->esr->taskSpecificParameters->which == Z_External_itemOrder)
74     {
75         Z_ItemOrder *it = rr->esr->taskSpecificParameters->u.itemOrder;
76         yaz_log (LOG_LOG, "Received ItemOrder");
77         switch (it->which)
78         {
79         case Z_IOItemOrder_esRequest:
80         {
81             Z_IORequest *ir = it->u.esRequest;
82             Z_IOOriginPartToKeep *k = ir->toKeep;
83             Z_IOOriginPartNotToKeep *n = ir->notToKeep;
84             
85             if (k && k->contact)
86             {
87                 if (k->contact->name)
88                     yaz_log(LOG_LOG, "contact name %s", k->contact->name);
89                 if (k->contact->phone)
90                     yaz_log(LOG_LOG, "contact phone %s", k->contact->phone);
91                 if (k->contact->email)
92                     yaz_log(LOG_LOG, "contact email %s", k->contact->email);
93             }
94             if (k->addlBilling)
95             {
96                 yaz_log(LOG_LOG, "Billing info (not shown)");
97             }
98             
99             if (n->resultSetItem)
100             {
101                 yaz_log(LOG_LOG, "resultsetItem");
102                 yaz_log(LOG_LOG, "setId: %s", n->resultSetItem->resultSetId);
103                 yaz_log(LOG_LOG, "item: %d", *n->resultSetItem->item);
104             }
105 #if YAZ_MODULE_ill
106             if (n->itemRequest)
107             {
108                 Z_External *r = (Z_External*) n->itemRequest;
109                 ILL_ItemRequest *item_req = 0;
110                 ILL_APDU *ill_apdu = 0;
111                 if (r->direct_reference)
112                 {
113                     oident *ent = oid_getentbyoid(r->direct_reference);
114                     if (ent)
115                         yaz_log(LOG_LOG, "OID %s", ent->desc);
116                     if (ent && ent->value == VAL_TEXT_XML)
117                     {
118                         yaz_log (LOG_LOG, "ILL XML request");
119                         if (r->which == Z_External_octet)
120                             yaz_log (LOG_LOG, "%.*s", r->u.octet_aligned->len,
121                                      r->u.octet_aligned->buf); 
122                     }
123                     if (ent && ent->value == VAL_ISO_ILL_1)
124                     {
125                         yaz_log (LOG_LOG, "Decode ItemRequest begin");
126                         if (r->which == ODR_EXTERNAL_single)
127                         {
128                             odr_setbuf(rr->decode,
129                                        (char *) r->u.single_ASN1_type->buf,
130                                        r->u.single_ASN1_type->len, 0);
131                             
132                             if (!ill_ItemRequest (rr->decode, &item_req, 0, 0))
133                             {
134                                 yaz_log (LOG_LOG,
135                                     "Couldn't decode ItemRequest %s near %d",
136                                        odr_errmsg(odr_geterror(rr->decode)),
137                                        odr_offset(rr->decode));
138 #if 0
139                                 yaz_log(LOG_LOG, "PDU dump:");
140                                 odr_dumpBER(yaz_log_file(),
141                                      r->u.single_ASN1_type->buf,
142                                      r->u.single_ASN1_type->len);
143 #endif
144                             }
145                             else
146                                 yaz_log(LOG_LOG, "Decode ItemRequest OK");
147                             if (rr->print)
148                             {
149                                 ill_ItemRequest (rr->print, &item_req, 0,
150                                     "ItemRequest");
151                                 odr_reset (rr->print);
152                             }
153                         }
154                         if (!item_req && r->which == ODR_EXTERNAL_single)
155                         {
156                             yaz_log (LOG_LOG, "Decode ILL APDU begin");
157                             odr_setbuf(rr->decode,
158                                        (char*) r->u.single_ASN1_type->buf,
159                                        r->u.single_ASN1_type->len, 0);
160                             
161                             if (!ill_APDU (rr->decode, &ill_apdu, 0, 0))
162                             {
163                                 yaz_log (LOG_LOG,
164                                     "Couldn't decode ILL APDU %s near %d",
165                                        odr_errmsg(odr_geterror(rr->decode)),
166                                        odr_offset(rr->decode));
167                                 yaz_log(LOG_LOG, "PDU dump:");
168                                 odr_dumpBER(yaz_log_file(),
169                                      (char *) r->u.single_ASN1_type->buf,
170                                      r->u.single_ASN1_type->len);
171                             }
172                             else
173                                 yaz_log(LOG_LOG, "Decode ILL APDU OK");
174                             if (rr->print)
175                             {
176                                 ill_APDU (rr->print, &ill_apdu, 0,
177                                     "ILL APDU");
178                                 odr_reset (rr->print);
179                             }
180                         }
181                     }
182                 }
183                 if (item_req)
184                 {
185                     yaz_log (LOG_LOG, "ILL protocol version = %d",
186                              *item_req->protocol_version_num);
187                 }
188             }
189 #endif
190         }
191         break;
192         }
193     }
194     else if (rr->esr->taskSpecificParameters->which == Z_External_update)
195     {
196         Z_IUUpdate *up = rr->esr->taskSpecificParameters->u.update;
197         yaz_log (LOG_LOG, "Received DB Update");
198         if (up->which == Z_IUUpdate_esRequest)
199         {
200             Z_IUUpdateEsRequest *esRequest = up->u.esRequest;
201             Z_IUOriginPartToKeep *toKeep = esRequest->toKeep;
202             Z_IUSuppliedRecords *notToKeep = esRequest->notToKeep;
203             
204             yaz_log (LOG_LOG, "action");
205             if (toKeep->action)
206             {
207                 switch (*toKeep->action)
208                 {
209                 case Z_IUOriginPartToKeep_recordInsert:
210                     yaz_log (LOG_LOG, " recordInsert");
211                     break;
212                 case Z_IUOriginPartToKeep_recordReplace:
213                     yaz_log (LOG_LOG, " recordReplace");
214                     break;
215                 case Z_IUOriginPartToKeep_recordDelete:
216                     yaz_log (LOG_LOG, " recordDelete");
217                     break;
218                 case Z_IUOriginPartToKeep_elementUpdate:
219                     yaz_log (LOG_LOG, " elementUpdate");
220                     break;
221                 case Z_IUOriginPartToKeep_specialUpdate:
222                     yaz_log (LOG_LOG, " specialUpdate");
223                     break;
224                 default:
225                     yaz_log (LOG_LOG, " unknown (%d)", *toKeep->action);
226                 }
227             }
228             if (toKeep->databaseName)
229             {
230                 yaz_log (LOG_LOG, "database: %s", toKeep->databaseName);
231                 if (!strcmp(toKeep->databaseName, "fault"))
232                 {
233                     rr->errcode = 109;
234                     rr->errstring = toKeep->databaseName;
235                 }
236                 if (!strcmp(toKeep->databaseName, "accept"))
237                     rr->errcode = -1;
238             }
239             if (toKeep)
240             {
241                 Z_External *ext = (Z_External *)
242                     odr_malloc (rr->stream, sizeof(*ext));
243                 Z_IUOriginPartToKeep *keep = (Z_IUOriginPartToKeep *)
244                     odr_malloc (rr->stream, sizeof(*keep));
245                 Z_IUTargetPart *targetPart = (Z_IUTargetPart *)
246                     odr_malloc (rr->stream, sizeof(*targetPart));
247                 rr->taskPackage = (Z_TaskPackage *)
248                     odr_malloc (rr->stream, sizeof(*rr->taskPackage));
249                 rr->taskPackage->packageType =
250                     odr_oiddup (rr->stream, rr->esr->packageType);
251                 rr->taskPackage->packageName = 0;
252                 rr->taskPackage->userId = 0;
253                 rr->taskPackage->retentionTime = 0;
254                 rr->taskPackage->permissions = 0;
255                 rr->taskPackage->description = 0;
256                 rr->taskPackage->targetReference = (Odr_oct *)
257                     odr_malloc (rr->stream, sizeof(Odr_oct));
258                 rr->taskPackage->targetReference->buf =
259                     (unsigned char *) odr_strdup (rr->stream, "123");
260                 rr->taskPackage->targetReference->len =
261                     rr->taskPackage->targetReference->size =
262                     strlen((char *) (rr->taskPackage->targetReference->buf));
263                 rr->taskPackage->creationDateTime = 0;
264                 rr->taskPackage->taskStatus = odr_intdup(rr->stream, 0);
265                 rr->taskPackage->packageDiagnostics = 0;
266                 rr->taskPackage->taskSpecificParameters = ext;
267
268                 ext->direct_reference =
269                     odr_oiddup (rr->stream, rr->esr->packageType);
270                 ext->indirect_reference = 0;
271                 ext->descriptor = 0;
272                 ext->which = Z_External_update;
273                 ext->u.update = (Z_IUUpdate *)
274                     odr_malloc (rr->stream, sizeof(*ext->u.update));
275                 ext->u.update->which = Z_IUUpdate_taskPackage;
276                 ext->u.update->u.taskPackage =  (Z_IUUpdateTaskPackage *)
277                     odr_malloc (rr->stream, sizeof(Z_IUUpdateTaskPackage));
278                 ext->u.update->u.taskPackage->originPart = keep;
279                 ext->u.update->u.taskPackage->targetPart = targetPart;
280
281                 keep->action = (int *) odr_malloc (rr->stream, sizeof(int));
282                 *keep->action = *toKeep->action;
283                 keep->databaseName =
284                     odr_strdup (rr->stream, toKeep->databaseName);
285                 keep->schema = 0;
286                 keep->elementSetName = 0;
287                 keep->actionQualifier = 0;
288
289                 targetPart->updateStatus = odr_intdup (rr->stream, 1);
290                 targetPart->num_globalDiagnostics = 0;
291                 targetPart->globalDiagnostics = (Z_DiagRec **) odr_nullval();
292                 targetPart->num_taskPackageRecords = 0;
293                 targetPart->taskPackageRecords =
294                     (Z_IUTaskPackageRecordStructure **) odr_nullval();
295             }
296             if (notToKeep)
297             {
298                 int i;
299                 for (i = 0; i < notToKeep->num; i++)
300                 {
301                     Z_External *rec = notToKeep->elements[i]->record;
302
303                     if (rec->direct_reference)
304                     {
305                         struct oident *oident;
306                         oident = oid_getentbyoid(rec->direct_reference);
307                         if (oident)
308                             yaz_log (LOG_LOG, "record %d type %s", i,
309                                      oident->desc);
310                     }
311                     switch (rec->which)
312                     {
313                     case Z_External_sutrs:
314                         if (rec->u.octet_aligned->len > 170)
315                             yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
316                                      rec->u.sutrs->len,
317                                      rec->u.sutrs->buf);
318                         else
319                             yaz_log (LOG_LOG, "%d bytes:\n%s",
320                                      rec->u.sutrs->len,
321                                      rec->u.sutrs->buf);
322                         break;
323                     case Z_External_octet        :
324                         if (rec->u.octet_aligned->len > 170)
325                             yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
326                                      rec->u.octet_aligned->len,
327                                      rec->u.octet_aligned->buf);
328                         else
329                             yaz_log (LOG_LOG, "%d bytes\n%s",
330                                      rec->u.octet_aligned->len,
331                                      rec->u.octet_aligned->buf);
332                     }
333                 }
334             }
335         }
336     }
337     else
338     {
339         yaz_log (LOG_WARN, "Unknown Extended Service(%d)",
340                  rr->esr->taskSpecificParameters->which);
341         
342     }
343     return 0;
344 }
345
346 int ztest_delete (void *handle, bend_delete_rr *rr)
347 {
348     if (rr->num_setnames == 1 && !strcmp (rr->setnames[0], "1"))
349         rr->delete_status = Z_DeleteStatus_success;
350     else
351         rr->delete_status = Z_DeleteStatus_resultSetDidNotExist;
352     return 0;
353 }
354
355 /* Our sort handler really doesn't sort... */
356 int ztest_sort (void *handle, bend_sort_rr *rr)
357 {
358     rr->errcode = 0;
359     rr->sort_status = Z_SortStatus_success;
360     return 0;
361 }
362
363 static int atoin (const char *buf, int n)
364 {
365     int val = 0;
366     while (--n >= 0)
367     {
368         if (isdigit(*buf))
369             val = val*10 + (*buf - '0');
370         buf++;
371     }
372     return val;
373 }
374
375 char *marc_read(FILE *inf, ODR odr)
376 {
377     char length_str[5];
378     size_t size;
379     char *buf;
380
381     if (fread (length_str, 1, 5, inf) != 5)
382         return NULL;
383     size = atoin (length_str, 5);
384     if (size <= 6)
385         return NULL;
386     if (!(buf = (char*) odr_malloc (odr, size+1)))
387         return NULL;
388     if (fread (buf+5, 1, size-5, inf) != (size-5))
389     {
390         xfree (buf);
391         return NULL;
392     }
393     memcpy (buf, length_str, 5);
394     buf[size] = '\0';
395     return buf;
396 }
397
398 static char *dummy_database_record (int num, ODR odr)
399 {
400     FILE *inf = fopen ("dummy-records", "r");
401     char *buf = 0;
402
403     if (!inf)
404         return NULL;
405     if (num == 98) 
406     {   /* this will generate a very bad MARC record (testing only) */
407         buf = (char*) odr_malloc(odr, 2101);
408         memset(buf, '7', 2100);
409         buf[2100] = '\0';
410     }
411     else
412     {
413         /* OK, try to get proper MARC records from the file */
414         while (--num >= 0)
415         {
416             buf = marc_read (inf, odr);
417             if (!buf)
418                 break;
419         }
420     }
421     fclose(inf);
422     return buf;
423 }
424
425 static Z_GenericRecord *dummy_grs_record (int num, ODR o)
426 {
427     FILE *f = fopen("dummy-grs", "r");
428     char line[512];
429     Z_GenericRecord *r = 0;
430     int n;
431
432     if (!f)
433         return 0;
434     while (fgets(line, 512, f))
435         if (*line == '#' && sscanf(line, "#%d", &n) == 1 && n == num)
436         {
437             r = read_grs1(f, o);
438             break;
439         }
440     fclose(f);
441     return r;
442 }
443
444 int ztest_fetch(void *handle, bend_fetch_rr *r)
445 {
446     char *cp;
447     r->errstring = 0;
448     r->last_in_set = 0;
449     r->basename = "DUMMY";
450     r->output_format = r->request_format;  
451     if (r->request_format == VAL_SUTRS)
452     {
453 #if 0
454 /* this section returns a huge record (for testing non-blocking write, etc) */
455         r->len = 980000;
456         r->record = odr_malloc (r->stream, r->len);
457         memset (r->record, 'x', r->len);
458 #else
459 /* this section returns a small record */
460         char buf[100];
461
462         sprintf(buf, "This is dummy SUTRS record number %d\n", r->number);
463
464         r->len = strlen(buf);
465         r->record = (char *) odr_malloc (r->stream, r->len+1);
466         strcpy(r->record, buf);
467 #endif
468     }
469     else if (r->request_format == VAL_GRS1)
470     {
471         r->len = -1;
472         r->record = (char*) dummy_grs_record(r->number, r->stream);
473         if (!r->record)
474         {
475             r->errcode = 13;
476             return 0;
477         }
478     }
479     else if ((cp = dummy_database_record(r->number, r->stream)))
480     {
481         r->len = strlen(cp);
482         r->record = cp;
483         r->output_format = VAL_USMARC;
484     }
485     else
486     {
487         r->errcode = 13;
488         return 0;
489     }
490     r->errcode = 0;
491     return 0;
492 }
493
494 /*
495  * silly dummy-scan what reads words from a file.
496  */
497 int ztest_scan(void *handle, bend_scan_rr *q)
498 {
499     static FILE *f = 0;
500     static struct scan_entry list[200];
501     static char entries[200][80];
502     int hits[200];
503     char term[80], *p;
504     int i, pos;
505     int term_position_req = q->term_position;
506     int num_entries_req = q->num_entries;
507
508     q->errcode = 0;
509     q->errstring = 0;
510     q->entries = list;
511     q->status = BEND_SCAN_SUCCESS;
512     if (!f && !(f = fopen("dummy-words", "r")))
513     {
514         perror("dummy-words");
515         exit(1);
516     }
517     if (q->term->term->which != Z_Term_general)
518     {
519         q->errcode = 229; /* unsupported term type */
520         return 0;
521     }
522     if (*q->step_size != 0)
523     {
524         q->errcode = 205; /*Only zero step size supported for Scan */
525         return 0;
526     }
527     if (q->term->term->u.general->len >= 80)
528     {
529         q->errcode = 11; /* term too long */
530         return 0;
531     }
532     if (q->num_entries > 200)
533     {
534         q->errcode = 31;
535         return 0;
536     }
537     memcpy(term, q->term->term->u.general->buf, q->term->term->u.general->len);
538     term[q->term->term->u.general->len] = '\0';
539     for (p = term; *p; p++)
540         if (islower(*p))
541             *p = toupper(*p);
542
543     fseek(f, 0, SEEK_SET);
544     q->num_entries = 0;
545
546     for (i = 0, pos = 0; fscanf(f, " %79[^:]:%d", entries[pos], &hits[pos]) == 2;
547         i++, pos < 199 ? pos++ : (pos = 0))
548     {
549         if (!q->num_entries && strcmp(entries[pos], term) >= 0) /* s-point fnd */
550         {
551             if ((q->term_position = term_position_req) > i + 1)
552             {
553                 q->term_position = i + 1;
554                 q->status = BEND_SCAN_PARTIAL;
555             }
556             for (; q->num_entries < q->term_position; q->num_entries++)
557             {
558                 int po;
559
560                 po = pos - q->term_position + q->num_entries+1; /* find pos */
561                 if (po < 0)
562                     po += 200;
563
564                 if (!strcmp (term, "SD") && q->num_entries == 2)
565                 {
566                     list[q->num_entries].term = entries[pos];
567                     list[q->num_entries].occurrences = -1;
568                     list[q->num_entries].errcode = 233;
569                     list[q->num_entries].errstring = "SD for Scan Term";
570                 }
571                 else
572                 {
573                     list[q->num_entries].term = entries[po];
574                     list[q->num_entries].occurrences = hits[po];
575                 }
576             }
577         }
578         else if (q->num_entries)
579         {
580             list[q->num_entries].term = entries[pos];
581             list[q->num_entries].occurrences = hits[pos];
582             q->num_entries++;
583         }
584         if (q->num_entries >= num_entries_req)
585             break;
586     }
587     if (feof(f))
588         q->status = BEND_SCAN_PARTIAL;
589     return 0;
590 }
591
592 bend_initresult *bend_init(bend_initrequest *q)
593 {
594     bend_initresult *r = (bend_initresult *) odr_malloc (q->stream, sizeof(*r));
595     int *counter = (int *) xmalloc (sizeof(int));
596
597     *counter = 0;
598     r->errcode = 0;
599     r->errstring = 0;
600     r->handle = counter;         /* user handle, in this case a simple int */
601     q->bend_sort = ztest_sort;              /* register sort handler */
602     q->bend_search = ztest_search;          /* register search handler */
603     q->bend_present = ztest_present;        /* register present handle */
604     q->bend_esrequest = ztest_esrequest;
605     q->bend_delete = ztest_delete;
606     q->bend_fetch = ztest_fetch;
607     q->bend_scan = ztest_scan;
608     return r;
609 }
610
611 void bend_close(void *handle)
612 {
613     xfree (handle);              /* release our user-defined handle */
614     return;
615 }
616
617 int main(int argc, char **argv)
618 {
619     return statserv_main(argc, argv, bend_init, bend_close);
620 }