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