Added support for extended handlers in backend server interface.
[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.7  1998-02-10 11:03:57  adam
11  * Added support for extended handlers in backend server interface.
12  *
13  * Revision 1.6  1998/01/29 13:16:02  adam
14  * Added dummy sort in test server.
15  *
16  * Revision 1.5  1997/11/07 13:31:58  adam
17  * Added NT Service name part of statserv_options_block. Moved NT
18  * service utility to server library.
19  *
20  * Revision 1.4  1997/09/17 12:10:43  adam
21  * YAZ version 1.4.
22  *
23  * Revision 1.3  1997/09/09 10:10:20  adam
24  * Another MSV5.0 port. Changed projects to include proper
25  * library/include paths.
26  * Server starts server in test-mode when no options are given.
27  *
28  * Revision 1.2  1997/09/04 13:50:31  adam
29  * Bug fix in ztest.
30  *
31  */
32
33 /*
34  * Demonstration of simple server
35  */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <ctype.h>
40 #include <assert.h>
41
42 #include <backend.h>
43 #include <xmalloc.h>
44 #include <proto.h>
45 #include <log.h>
46
47 Z_GenericRecord *read_grs1(FILE *f, ODR o);
48
49 int ztest_search (void *handle, bend_search_rr *rr);
50 int ztest_sort (void *handle, bend_sort_rr *rr);
51 int ztest_present (void *handle, bend_present_rr *rr);
52
53 bend_initresult *bend_init(bend_initrequest *q)
54 {
55     bend_initresult *r = odr_malloc (q->stream, sizeof(*r));
56     static char *dummy = "Hej fister";
57
58     r->errcode = 0;
59     r->errstring = 0;
60     r->handle = dummy;
61     q->bend_sort = ztest_sort;       /* register sort handler */
62     q->bend_search = ztest_search;   /* register search handler */
63     q->bend_present = ztest_present; /* register present handle */
64     return r;
65 }
66
67 int ztest_search (void *handle, bend_search_rr *rr)
68 {
69     rr->hits = rand() % 22;
70     return 0;
71 }
72
73 int ztest_present (void *handle, bend_present_rr *rr)
74 {
75     return 0;
76 }
77
78 /* Obsolete bend_search, never called because handler is registered */
79 bend_searchresult *bend_search(void *handle, bend_searchrequest *q, int *fd)
80 {
81     return 0;
82 }
83
84 /* Our sort handler really doesn't sort... */
85 int ztest_sort (void *handle, bend_sort_rr *rr)
86 {
87     rr->errcode = 0;
88     rr->sort_status = Z_SortStatus_success;
89     return 0;
90 }
91
92 static int atoin (const char *buf, int n)
93 {
94     int val = 0;
95     while (--n >= 0)
96     {
97         if (isdigit(*buf))
98             val = val*10 + (*buf - '0');
99         buf++;
100     }
101     return val;
102 }
103
104 char *marc_read(FILE *inf)
105 {
106     char length_str[5];
107     size_t size;
108     char *buf;
109
110     if (fread (length_str, 1, 5, inf) != 5)
111         return NULL;
112     size = atoin (length_str, 5);
113     if (size <= 6)
114         return NULL;
115     if (!(buf = xmalloc (size+1)))
116         return NULL;
117     if (fread (buf+5, 1, size-5, inf) != (size-5))
118     {
119         xfree (buf);
120         return NULL;
121     }
122     memcpy (buf, length_str, 5);
123     buf[size] = '\0';
124     return buf;
125 }
126
127 static char *dummy_database_record (int num)
128 {
129     FILE *inf = fopen ("dummy-records", "r");
130     char *buf = 0;
131
132     if (!inf)
133         return NULL;
134     while (--num >= 0)
135     {
136         if (buf)
137            xfree(buf);
138         if (num == 98)
139         {
140             assert(buf = xmalloc(2101));
141             memset(buf, 'A', 2100);
142             buf[2100] = '\0';
143             break;
144         }
145         else
146             buf = marc_read (inf);
147         if (!num || !buf)
148             break;
149     }
150     fclose(inf);
151     if (num < 0)
152         return 0;
153     return buf;
154 }
155
156 static Z_GenericRecord *dummy_grs_record (int num, ODR o)
157 {
158     FILE *f = fopen("dummy-grs", "r");
159     char line[512];
160     Z_GenericRecord *r = 0;
161     int n;
162
163     if (!f)
164         return 0;
165     while (fgets(line, 512, f))
166         if (*line == '#' && sscanf(line, "#%d", &n) == 1 && n == num)
167         {
168             r = read_grs1(f, o);
169             break;
170         }
171     fclose(f);
172     return r;
173 }
174
175 bend_fetchresult *bend_fetch(void *handle, bend_fetchrequest *q, int *num)
176 {
177     bend_fetchresult *r = odr_malloc (q->stream, sizeof(*r));
178     static char *bbb = 0;
179
180     r->errstring = 0;
181     r->last_in_set = 0;
182     r->basename = "DUMMY";
183     if (bbb)
184     {
185         xfree(bbb);
186         bbb = 0;
187     }
188     r->format = q->format;  
189     if (q->format == VAL_SUTRS)
190     {
191         char buf[100];
192
193         sprintf(buf, "This is dummy SUTRS record number %d\n", q->number);
194         assert(r->record = bbb = xmalloc(strlen(buf)+1));
195         strcpy(bbb, buf);
196         r->len = strlen(buf);
197     }
198     else if (q->format == VAL_GRS1)
199     {
200         r->len = -1;
201         r->record = (char*) dummy_grs_record(q->number, q->stream);
202         if (!r->record)
203         {
204             r->errcode = 13;
205             return r;
206         }
207     }
208     else if (!(r->record = bbb = dummy_database_record(q->number)))
209     {
210         r->errcode = 13;
211         r->format = VAL_USMARC;
212         return r;
213     }
214     else
215         r->len = strlen(r->record);
216     r->errcode = 0;
217     return r;
218 }
219
220 bend_deleteresult *bend_delete(void *handle, bend_deleterequest *q, int *num)
221 {
222     return 0;
223 }
224
225 #if 0
226 bend_scanresult *bend_scan(void *handle, bend_scanrequest *q, int *num)
227 {
228     static struct scan_entry list[200];
229     static char buf[200][200];
230     static bend_scanresult r;
231     int i;
232
233     r.term_position = q->term_position;
234     r.num_entries = q->num_entries;
235     r.entries = list;
236     for (i = 0; i < r.num_entries; i++)
237     {
238         list[i].term = buf[i];
239         sprintf(list[i].term, "term-%d", i+1);
240         list[i].occurrences = rand() % 100000;
241     }
242     r.errcode = 0;
243     r.errstring = 0;
244     return &r;
245 }
246 #else
247 /*
248  * silly dummy-scan what reads words from a file.
249  */
250 bend_scanresult *bend_scan(void *handle, bend_scanrequest *q, int *num)
251 {
252     bend_scanresult *r = odr_malloc (q->stream, sizeof(*r));
253     static FILE *f = 0;
254     static struct scan_entry list[200];
255     static char entries[200][80];
256     int hits[200];
257     char term[80], *p;
258     int i, pos;
259
260     r->errcode = 0;
261     r->errstring = 0;
262     r->entries = list;
263     r->status = BEND_SCAN_SUCCESS;
264     if (!f && !(f = fopen("dummy-words", "r")))
265     {
266         perror("dummy-words");
267         exit(1);
268     }
269     if (q->term->term->which != Z_Term_general)
270     {
271         r->errcode = 229; /* unsupported term type */
272         return r;
273     }
274     if (q->term->term->u.general->len >= 80)
275     {
276         r->errcode = 11; /* term too long */
277         return r;
278     }
279     if (q->num_entries > 200)
280     {
281         r->errcode = 31;
282         return r;
283     }
284     memcpy(term, q->term->term->u.general->buf, q->term->term->u.general->len);
285     term[q->term->term->u.general->len] = '\0';
286     for (p = term; *p; p++)
287         if (islower(*p))
288             *p = toupper(*p);
289
290     fseek(f, 0, SEEK_SET);
291     r->num_entries = 0;
292     for (i = 0, pos = 0; fscanf(f, " %79[^:]:%d", entries[pos], &hits[pos]) == 2;
293         i++, pos < 199 ? pos++ : (pos = 0))
294     {
295         if (!r->num_entries && strcmp(entries[pos], term) >= 0) /* s-point fnd */
296         {
297             if ((r->term_position = q->term_position) > i + 1)
298             {
299                 r->term_position = i + 1;
300                 r->status = BEND_SCAN_PARTIAL;
301             }
302             for (; r->num_entries < r->term_position; r->num_entries++)
303             {
304                 int po;
305
306                 po = pos - r->term_position + r->num_entries + 1; /* find pos */
307                 if (po < 0)
308                     po += 200;
309                 list[r->num_entries].term = entries[po];
310                 list[r->num_entries].occurrences = hits[po];
311             }
312         }
313         else if (r->num_entries)
314         {
315             list[r->num_entries].term = entries[pos];
316             list[r->num_entries].occurrences = hits[pos];
317             r->num_entries++;
318         }
319         if (r->num_entries >= q->num_entries)
320             break;
321     }
322     if (feof(f))
323         r->status = BEND_SCAN_PARTIAL;
324     return r;
325 }
326
327 #endif
328
329 void bend_close(void *handle)
330 {
331     return;
332 }
333
334 int main(int argc, char **argv)
335 {
336     return statserv_main(argc, argv);
337 }