DB Update implemented in client (very basic).
[yaz-moved-to-github.git] / ztest / ztest.c
1 /*
2  * Copyright (c) 1995-1998, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * NT Service interface by
7  *    Chas Woodfield, Fretwell Downing Datasystems.
8  *
9  * $Log: ztest.c,v $
10  * Revision 1.22  1999-05-26 13:49:12  adam
11  * DB Update implemented in client (very basic).
12  *
13  * Revision 1.21  1998/12/15 12:45:42  adam
14  * Minor change.
15  *
16  * Revision 1.20  1998/12/14 14:48:05  adam
17  * Fixed memory leak - happened when fetching MARC records.
18  *
19  * Revision 1.19  1998/10/20 15:16:22  adam
20  * Minor change to prevent warning.
21  *
22  * Revision 1.18  1998/10/20 15:13:45  adam
23  * Minor fix regarding output for Item Order.
24  *
25  * Revision 1.17  1998/10/18 22:33:35  quinn
26  * Added diagnostic dump of Item Order Eservice.
27  *
28  * Revision 1.16  1998/10/15 08:26:23  adam
29  * Added type cast to make C++ happy.
30  *
31  * Revision 1.15  1998/10/13 20:05:57  adam
32  * Minor change.
33  *
34  * Revision 1.14  1998/10/13 16:12:25  adam
35  * Added support for Surrogate Diagnostics for Scan Term entries.
36  *
37  * Revision 1.13  1998/08/19 16:10:09  adam
38  * Changed som member names of DeleteResultSetRequest/Response.
39  *
40  * Revision 1.12  1998/07/20 12:38:44  adam
41  * Implemented delete result set service to server API.
42  *
43  * Revision 1.11  1998/06/09 13:55:08  adam
44  * Minor changes.
45  *
46  * Revision 1.10  1998/05/27 16:55:54  adam
47  * Minor changes.
48  *
49  * Revision 1.9  1998/03/31 11:07:45  adam
50  * Furhter work on UNIverse resource report.
51  * Added Extended Services handling in frontend server.
52  *
53  * Revision 1.8  1998/02/11 11:53:36  adam
54  * Changed code so that it compiles as C++.
55  *
56  * Revision 1.7  1998/02/10 11:03:57  adam
57  * Added support for extended handlers in backend server interface.
58  *
59  * Revision 1.6  1998/01/29 13:16:02  adam
60  * Added dummy sort in test server.
61  *
62  * Revision 1.5  1997/11/07 13:31:58  adam
63  * Added NT Service name part of statserv_options_block. Moved NT
64  * service utility to server library.
65  *
66  * Revision 1.4  1997/09/17 12:10:43  adam
67  * YAZ version 1.4.
68  *
69  * Revision 1.3  1997/09/09 10:10:20  adam
70  * Another MSV5.0 port. Changed projects to include proper
71  * library/include paths.
72  * Server starts server in test-mode when no options are given.
73  *
74  * Revision 1.2  1997/09/04 13:50:31  adam
75  * Bug fix in ztest.
76  *
77  */
78
79 /*
80  * Demonstration of simple server
81  */
82
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <ctype.h>
86 #include <assert.h>
87
88 #include <backend.h>
89 #include <proto.h>
90 #include <log.h>
91
92 Z_GenericRecord *read_grs1(FILE *f, ODR o);
93
94 int ztest_search (void *handle, bend_search_rr *rr);
95 int ztest_sort (void *handle, bend_sort_rr *rr);
96 int ztest_present (void *handle, bend_present_rr *rr);
97 int ztest_esrequest (void *handle, bend_esrequest_rr *rr);
98 int ztest_delete (void *handle, bend_delete_rr *rr);
99
100 bend_initresult *bend_init(bend_initrequest *q)
101 {
102     bend_initresult *r = (bend_initresult *) odr_malloc (q->stream, sizeof(*r));
103     static char *dummy = "Hej fister";
104
105     r->errcode = 0;
106     r->errstring = 0;
107     r->handle = dummy;
108     q->bend_sort = ztest_sort;       /* register sort handler */
109     q->bend_search = ztest_search;   /* register search handler */
110     q->bend_present = ztest_present; /* register present handle */
111     q->bend_esrequest = ztest_esrequest;
112     q->bend_delete = ztest_delete;
113     return r;
114 }
115
116 int ztest_search (void *handle, bend_search_rr *rr)
117 {
118     rr->hits = rand() % 22;
119     return 0;
120 }
121
122 int ztest_present (void *handle, bend_present_rr *rr)
123 {
124     return 0;
125 }
126
127 int ztest_esrequest (void *handle, bend_esrequest_rr *rr)
128 {
129     logf(LOG_LOG, "function: %d", *rr->esr->function);
130     if (rr->esr->packageName)
131         logf(LOG_LOG, "packagename: %s", rr->esr->packageName);
132     logf(LOG_LOG, "Waitaction: %d", *rr->esr->waitAction);
133
134     if (!rr->esr->taskSpecificParameters)
135     {
136         logf (LOG_WARN, "No task specific parameters");
137     }
138     else if (rr->esr->taskSpecificParameters->which == Z_External_itemOrder)
139     {
140         Z_ItemOrder *it = rr->esr->taskSpecificParameters->u.itemOrder;
141         switch (it->which)
142         {
143 #ifdef ASN_COMPILED
144         case Z_IOItemOrder_esRequest:
145 #else
146         case Z_ItemOrder_esRequest:
147 #endif
148         {
149             Z_IORequest *ir = it->u.esRequest;
150             Z_IOOriginPartToKeep *k = ir->toKeep;
151             Z_IOOriginPartNotToKeep *n = ir->notToKeep;
152             
153             if (k && k->contact)
154             {
155                 if (k->contact->name)
156                     logf(LOG_LOG, "contact name %s", k->contact->name);
157                 if (k->contact->phone)
158                     logf(LOG_LOG, "contact phone %s", k->contact->phone);
159                 if (k->contact->email)
160                     logf(LOG_LOG, "contact email %s", k->contact->email);
161             }
162             if (k->addlBilling)
163             {
164                 logf(LOG_LOG, "Billing info (not shown)");
165             }
166             
167             if (n->resultSetItem)
168             {
169                 logf(LOG_LOG, "resultsetItem");
170                 logf(LOG_LOG, "setId: %s", n->resultSetItem->resultSetId);
171                 logf(LOG_LOG, "item: %d", *n->resultSetItem->item);
172             }
173         }
174         break;
175         }
176     }
177     else
178     {
179         logf (LOG_WARN, "Unknown Extended Service(%d)",
180               rr->esr->taskSpecificParameters->which);
181     }
182     rr->errcode = 0;
183     return 0;
184 }
185
186 int ztest_delete (void *handle, bend_delete_rr *rr)
187 {
188     if (rr->num_setnames == 1 && !strcmp (rr->setnames[0], "1"))
189         rr->delete_status = Z_DeleteStatus_success;
190     else
191         rr->delete_status = Z_DeleteStatus_resultSetDidNotExist;
192     return 0;
193 }
194
195 /* Obsolete bend_search, never called because handler is registered */
196 bend_searchresult *bend_search(void *handle, bend_searchrequest *q, int *fd)
197 {
198     return 0;
199 }
200
201 /* Our sort handler really doesn't sort... */
202 int ztest_sort (void *handle, bend_sort_rr *rr)
203 {
204     rr->errcode = 0;
205     rr->sort_status = Z_SortStatus_success;
206     return 0;
207 }
208
209 static int atoin (const char *buf, int n)
210 {
211     int val = 0;
212     while (--n >= 0)
213     {
214         if (isdigit(*buf))
215             val = val*10 + (*buf - '0');
216         buf++;
217     }
218     return val;
219 }
220
221 char *marc_read(FILE *inf, ODR odr)
222 {
223     char length_str[5];
224     size_t size;
225     char *buf;
226
227     if (fread (length_str, 1, 5, inf) != 5)
228         return NULL;
229     size = atoin (length_str, 5);
230     if (size <= 6)
231         return NULL;
232     if (!(buf = (char*) odr_malloc (odr, size+1)))
233         return NULL;
234     if (fread (buf+5, 1, size-5, inf) != (size-5))
235     {
236         xfree (buf);
237         return NULL;
238     }
239     memcpy (buf, length_str, 5);
240     buf[size] = '\0';
241     return buf;
242 }
243
244 static char *dummy_database_record (int num, ODR odr)
245 {
246     FILE *inf = fopen ("dummy-records", "r");
247     char *buf;
248
249     if (!inf)
250         return NULL;
251     while (--num >= 0)
252     {
253         if (num == 98)
254         {
255             buf = (char*) odr_malloc(odr, 2101);
256             assert(buf);
257             memset(buf, 'A', 2100);
258             buf[2100] = '\0';
259             break;
260         }
261         else
262             buf = marc_read (inf, odr);
263         if (!num || !buf)
264             break;
265     }
266     fclose(inf);
267     if (num < 0)
268         return 0;
269     return buf;
270 }
271
272 static Z_GenericRecord *dummy_grs_record (int num, ODR o)
273 {
274     FILE *f = fopen("dummy-grs", "r");
275     char line[512];
276     Z_GenericRecord *r = 0;
277     int n;
278
279     if (!f)
280         return 0;
281     while (fgets(line, 512, f))
282         if (*line == '#' && sscanf(line, "#%d", &n) == 1 && n == num)
283         {
284             r = read_grs1(f, o);
285             break;
286         }
287     fclose(f);
288     return r;
289 }
290
291 bend_fetchresult *bend_fetch(void *handle, bend_fetchrequest *q, int *fd)
292 {
293     bend_fetchresult *r = (bend_fetchresult *)
294                         odr_malloc (q->stream, sizeof(*r));
295     char *cp;
296     r->errstring = 0;
297     r->last_in_set = 0;
298     r->basename = "DUMMY";
299     r->format = q->format;  
300     if (q->format == VAL_SUTRS)
301     {
302         char buf[100];
303
304         sprintf(buf, "This is dummy SUTRS record number %d\n", q->number);
305         r->len = strlen(buf);
306         r->record = (char *) odr_malloc (q->stream, r->len+1);
307         strcpy(r->record, buf);
308     }
309     else if (q->format == VAL_GRS1)
310     {
311         r->len = -1;
312         r->record = (char*) dummy_grs_record(q->number, q->stream);
313         if (!r->record)
314         {
315             r->errcode = 13;
316             return r;
317         }
318     }
319     else if ((cp = dummy_database_record(q->number, q->stream)))
320     {
321         r->len = strlen(cp);
322         r->record = cp;
323         r->format = VAL_USMARC;
324     }
325     else
326     {
327         r->errcode = 13;
328         return r;
329     }
330     r->errcode = 0;
331     return r;
332 }
333
334 /*
335  * silly dummy-scan what reads words from a file.
336  */
337 bend_scanresult *bend_scan(void *handle, bend_scanrequest *q, int *fd)
338 {
339     bend_scanresult *r = (bend_scanresult *)
340         odr_malloc (q->stream, sizeof(*r));
341     static FILE *f = 0;
342     static struct scan_entry list[200];
343     static char entries[200][80];
344     int hits[200];
345     char term[80], *p;
346     int i, pos;
347
348     r->errcode = 0;
349     r->errstring = 0;
350     r->entries = list;
351     r->status = BEND_SCAN_SUCCESS;
352     if (!f && !(f = fopen("dummy-words", "r")))
353     {
354         perror("dummy-words");
355         exit(1);
356     }
357     if (q->term->term->which != Z_Term_general)
358     {
359         r->errcode = 229; /* unsupported term type */
360         return r;
361     }
362     if (q->term->term->u.general->len >= 80)
363     {
364         r->errcode = 11; /* term too long */
365         return r;
366     }
367     if (q->num_entries > 200)
368     {
369         r->errcode = 31;
370         return r;
371     }
372     memcpy(term, q->term->term->u.general->buf, q->term->term->u.general->len);
373     term[q->term->term->u.general->len] = '\0';
374     for (p = term; *p; p++)
375         if (islower(*p))
376             *p = toupper(*p);
377
378     fseek(f, 0, SEEK_SET);
379     r->num_entries = 0;
380     for (i = 0, pos = 0; fscanf(f, " %79[^:]:%d", entries[pos], &hits[pos]) == 2;
381         i++, pos < 199 ? pos++ : (pos = 0))
382     {
383         if (!r->num_entries && strcmp(entries[pos], term) >= 0) /* s-point fnd */
384         {
385             if ((r->term_position = q->term_position) > i + 1)
386             {
387                 r->term_position = i + 1;
388                 r->status = BEND_SCAN_PARTIAL;
389             }
390             for (; r->num_entries < r->term_position; r->num_entries++)
391             {
392                 int po;
393
394                 po = pos - r->term_position + r->num_entries + 1; /* find pos */
395                 if (po < 0)
396                     po += 200;
397
398                 if (!strcmp (term, "SD") && r->num_entries == 2)
399                 {
400                     list[r->num_entries].term = entries[pos];
401                     list[r->num_entries].occurrences = -1;
402                     list[r->num_entries].errcode = 233;
403                     list[r->num_entries].errstring = "SD for Scan Term";
404                 }
405                 else
406                 {
407                     list[r->num_entries].term = entries[po];
408                     list[r->num_entries].occurrences = hits[po];
409                 }
410             }
411         }
412         else if (r->num_entries)
413         {
414             list[r->num_entries].term = entries[pos];
415             list[r->num_entries].occurrences = hits[pos];
416             r->num_entries++;
417         }
418         if (r->num_entries >= q->num_entries)
419             break;
420     }
421     if (feof(f))
422         r->status = BEND_SCAN_PARTIAL;
423     return r;
424 }
425
426 void bend_close(void *handle)
427 {
428     return;
429 }
430
431 int main(int argc, char **argv)
432 {
433     return statserv_main(argc, argv);
434 }