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