Fix crash in record conv rule select YAZ-812
[yaz-moved-to-github.git] / zoom / zoom-benchmark.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 #if HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/time.h>
13
14 #include <yaz/xmalloc.h>
15 #include <yaz/options.h>
16 #include <yaz/zoom.h>
17
18 /* naming events */
19 static char* zoom_events[ZOOM_EVENT_MAX+1];
20
21 /* re-sorting event numbers to progress numbers */
22 static int zoom_progress[ZOOM_EVENT_MAX+1];
23
24 /* commando line parameters */
25 static struct parameters_t {
26     char host[1024];
27     char query[1024];
28     int progress[4096];
29     int concurrent;
30     int repeat;
31     int timeout;
32     char proxy[1024];
33     int piggypack;
34     int gnuplot;
35 } parameters;
36
37 struct  event_line_t
38 {
39     int connection;
40     long time_sec;
41     long time_usec;
42     int progress;
43     int event;
44     char zoom_event[128];
45     int error;
46     char errmsg[128];
47 };
48
49
50 void print_event_line(struct event_line_t *pel)
51 {
52     printf ("%d\t%ld.%06ld\t%d\t%d\t%s\t%d\t%s\n",
53             pel->connection, pel->time_sec, pel->time_usec,
54             pel->progress,
55             pel->event, pel->zoom_event,
56             pel->error, pel->errmsg);
57 }
58
59 void  update_events(int *elc, struct event_line_t *els,
60                     int repeat,
61                     int conn,
62                     long sec,
63                     long usec,
64                     int prog,
65                     int event,
66                     const char * eventmsg,
67                     int error,
68                     const char * errmsg){
69
70     int ielc = repeat*parameters.concurrent + conn;
71     int iels = repeat*parameters.concurrent*10 + conn*10 + elc[ielc];
72
73     els[iels].connection = conn;
74     els[iels].time_sec = sec;
75     els[iels].time_usec = usec;
76     els[iels].progress = prog;
77     els[iels].event = event;
78
79     if (eventmsg)
80         strcpy(els[iels].zoom_event, eventmsg);
81     else
82         strcpy(els[iels].zoom_event, "---");
83
84     els[iels].error = error;
85     strcpy(els[iels].errmsg, errmsg);
86     /* print_event_line(&els[iels]); */
87     elc[ielc] += 1;
88 }
89
90 void  print_events(int *elc,  struct event_line_t *els,
91                    int connections){
92     int i;
93     int j;
94     int k;
95     int ielc;
96     int iels;
97
98     for (k=0; k < parameters.repeat; k++){
99         for (i=0; i < connections; i++){
100             ielc = k * parameters.concurrent + i;
101             for (j=0; j < elc[ielc]; j++){
102                 iels = k * parameters.concurrent * 10 + i * 10 + j;
103                 print_event_line(&els[iels]);
104             }
105             printf("\n");
106         }
107         printf("\n");
108     }
109 }
110
111
112
113 void init_statics(void)
114 {
115     int i;
116     char nullstring[1] = "";
117
118     /* naming events */
119     zoom_events[ZOOM_EVENT_NONE] = "ZOOM_EVENT_NONE";
120     zoom_events[ZOOM_EVENT_CONNECT] = "ZOOM_EVENT_CONNECT";
121     zoom_events[ZOOM_EVENT_SEND_DATA] = "ZOOM_EVENT_SEND_DATA";
122     zoom_events[ZOOM_EVENT_RECV_DATA] = "ZOOM_EVENT_RECV_DATA";
123     zoom_events[ZOOM_EVENT_TIMEOUT] = "ZOOM_EVENT_TIMEOUT";
124     zoom_events[ZOOM_EVENT_UNKNOWN] = "ZOOM_EVENT_UNKNOWN";
125     zoom_events[ZOOM_EVENT_SEND_APDU] = "ZOOM_EVENT_SEND_APDU";
126     zoom_events[ZOOM_EVENT_RECV_APDU] = "ZOOM_EVENT_RECV_APDU";
127     zoom_events[ZOOM_EVENT_RECV_RECORD] = "ZOOM_EVENT_RECV_RECORD";
128     zoom_events[ZOOM_EVENT_RECV_SEARCH] = "ZOOM_EVENT_RECV_SEARCH";
129     zoom_events[ZOOM_EVENT_END] = "ZOOM_EVENT_END";
130
131     /* re-sorting event numbers to progress numbers */
132     zoom_progress[ZOOM_EVENT_NONE] = 0;
133     zoom_progress[ZOOM_EVENT_CONNECT] = 1;
134     zoom_progress[ZOOM_EVENT_SEND_DATA] = 3;
135     zoom_progress[ZOOM_EVENT_RECV_DATA] = 4;
136     zoom_progress[ZOOM_EVENT_TIMEOUT] = 9;
137     zoom_progress[ZOOM_EVENT_UNKNOWN] = 10;
138     zoom_progress[ZOOM_EVENT_SEND_APDU] = 2;
139     zoom_progress[ZOOM_EVENT_RECV_APDU] = 5;
140     zoom_progress[ZOOM_EVENT_RECV_RECORD] = 7;
141     zoom_progress[ZOOM_EVENT_RECV_SEARCH] = 6;
142     zoom_progress[ZOOM_EVENT_END] = 8;
143
144     /* parameters */
145     parameters.concurrent = 1;
146     parameters.timeout = 0;
147     parameters.repeat = 1;
148     strcpy(parameters.proxy, nullstring);
149     parameters.gnuplot = 0;
150     parameters.piggypack = 0;
151
152     /* progress initializing */
153     for (i = 0; i < 4096; i++){
154         parameters.progress[i] = 0;
155     }
156
157 }
158
159 struct time_type
160 {
161     struct timeval now;
162     struct timeval then;
163     long sec;
164     long usec;
165 };
166
167 void time_init(struct time_type *ptime)
168 {
169     gettimeofday(&(ptime->now), 0);
170     gettimeofday(&(ptime->then), 0);
171     ptime->sec = 0;
172     ptime->usec = 0;
173 }
174
175 void time_stamp(struct time_type *ptime)
176 {
177     gettimeofday(&(ptime->now), 0);
178     ptime->sec = ptime->now.tv_sec - ptime->then.tv_sec;
179     ptime->usec = ptime->now.tv_usec - ptime->then.tv_usec;
180     if (ptime->usec < 0){
181         ptime->sec--;
182         ptime->usec += 1000000;
183     }
184 }
185
186 long time_sec(struct time_type *ptime)
187 {
188     return ptime->sec;
189 }
190
191 long time_usec(struct time_type *ptime)
192 {
193     return ptime->usec;
194 }
195
196 void print_option_error(void)
197 {
198     fprintf(stderr, "zoom-benchmark:  Call error\n");
199     fprintf(stderr, "zoom-benchmark -h host:port -q pqf-query "
200             "[-c no_concurrent (max 4096)] "
201             "[-n no_repeat] "
202             "[-b (piggypack)] "
203             "[-g (gnuplot outfile)] "
204             "[-p proxy] \n");
205     /* "[-t timeout] \n"); */
206     exit(1);
207 }
208
209
210 void read_params(int argc, char **argv, struct parameters_t *p_parameters){
211     char *arg;
212     int ret;
213     while ((ret = options("h:q:c:t:p:bgn:", argv, argc, &arg)) != -2)
214     {
215         switch (ret)
216         {
217         case 'h':
218             strcpy(p_parameters->host, arg);
219             break;
220         case 'q':
221             strcpy(p_parameters->query, arg);
222             break;
223         case 'p':
224             strcpy(p_parameters->proxy, arg);
225             break;
226         case 'c':
227             p_parameters->concurrent = atoi(arg);
228             break;
229 #if 0
230             case 't':
231             p_parameters->timeout = atoi(arg);
232             break;
233 #endif
234         case 'b':
235             p_parameters->piggypack = 1;
236                     break;
237         case 'g':
238             p_parameters->gnuplot = 1;
239                     break;
240         case 'n':
241             p_parameters->repeat = atoi(arg);
242                     break;
243         case 0:
244             print_option_error();
245             break;
246         default:
247             print_option_error();
248         }
249     }
250
251     if(0){
252         printf("zoom-benchmark\n");
253         printf("   host:       %s \n", p_parameters->host);
254         printf("   query:      %s \n", p_parameters->query);
255         printf("   concurrent: %d \n", p_parameters->concurrent);
256         printf("   repeat:     %d \n", p_parameters->repeat);
257 #if 0
258         printf("   timeout:    %d \n", p_parameters->timeout);
259 #endif
260         printf("   proxy:      %s \n", p_parameters->proxy);
261         printf("   piggypack:  %d \n\n", p_parameters->piggypack);
262         printf("   gnuplot:    %d \n\n", p_parameters->gnuplot);
263     }
264
265     if (! strlen(p_parameters->host))
266         print_option_error();
267     if (! strlen(p_parameters->query))
268         print_option_error();
269     if (! (p_parameters->concurrent > 0))
270         print_option_error();
271     if (! (p_parameters->repeat > 0))
272         print_option_error();
273     if (! (p_parameters->timeout >= 0))
274         print_option_error();
275     if (! ( p_parameters->concurrent <= 4096))
276         print_option_error();
277 }
278
279 void print_table_header(void)
280 {
281     if (parameters.gnuplot)
282         printf("#");
283     printf ("target\tsecond.usec\tprogress\tevent\teventname\t");
284     printf("error\terrorname\n");
285 }
286
287
288 int main(int argc, char **argv)
289 {
290     struct time_type time;
291     ZOOM_connection *z;
292     ZOOM_resultset *r;
293     int *elc;
294     struct event_line_t *els;
295     ZOOM_options o;
296     int i;
297     int k;
298
299     init_statics();
300
301     read_params(argc, argv, &parameters);
302
303     z = (ZOOM_connection *) xmalloc(sizeof(*z) * parameters.concurrent);
304     r = (ZOOM_resultset *) xmalloc(sizeof(*r) * parameters.concurrent);
305     elc = (int *) xmalloc(sizeof(*elc) * parameters.concurrent * parameters.repeat);
306     els = (struct event_line_t *) xmalloc(
307         sizeof(*els) * parameters.concurrent * parameters.repeat * 10);
308     o = ZOOM_options_create();
309
310     /* async mode */
311     ZOOM_options_set (o, "async", "1");
312
313     /* get first record of result set (using piggypack) */
314     if (parameters.piggypack)
315         ZOOM_options_set (o, "count", "1");
316
317     /* set proxy */
318     if (strlen(parameters.proxy))
319         ZOOM_options_set (o, "proxy", parameters.proxy);
320
321
322     /* preferred record syntax */
323     if (0){
324         ZOOM_options_set (o, "preferredRecordSyntax", "usmarc");
325         ZOOM_options_set (o, "elementSetName", "F");
326     }
327
328     time_init(&time);
329     /* repeat loop */
330     for (k = 0; k < parameters.repeat; k++){
331
332         /* progress zeroing */
333         for (i = 0; i < 4096; i++){
334             parameters.progress[i] = k * 5 -1;
335         }
336
337         /* connect to all concurrent connections*/
338         for ( i = 0; i < parameters.concurrent; i++){
339             /* set event count to zero */
340             elc[k * parameters.concurrent + i] = 0;
341
342             /* create connection - pass options (they are the same for all) */
343             z[i] = ZOOM_connection_create(o);
344
345             /* connect and init */
346             ZOOM_connection_connect(z[i], parameters.host, 0);
347         }
348         /* search all */
349         for (i = 0; i < parameters.concurrent; i++)
350             r[i] = ZOOM_connection_search_pqf (z[i], parameters.query);
351
352         /* network I/O. pass number of connections and array of connections */
353         while ((i = ZOOM_event (parameters.concurrent, z))){
354             int event = ZOOM_connection_last_event(z[i-1]);
355             const char *errmsg;
356             const char *addinfo;
357             int error = 0;
358             //int progress = zoom_progress[event];
359
360             if (event == ZOOM_EVENT_SEND_DATA || event == ZOOM_EVENT_RECV_DATA)
361                 continue;
362
363             time_stamp(&time);
364
365             /* updating events and event list */
366             error = ZOOM_connection_error(z[i-1] , &errmsg, &addinfo);
367             if (error)
368                 parameters.progress[i] = zoom_progress[ZOOM_EVENT_UNKNOWN];
369             //parameters.progress[i] = zoom_progress[ZOOM_EVENT_NONE];
370             else if (event == ZOOM_EVENT_CONNECT)
371                 parameters.progress[i] = zoom_progress[event];
372             else
373                 //parameters.progress[i] = zoom_progress[event];
374                 parameters.progress[i] += 1;
375
376             update_events(elc, els,
377                           k, i-1,
378                           time_sec(&time), time_usec(&time),
379                           parameters.progress[i],
380                           event, zoom_events[event],
381                           error, errmsg);
382         }
383
384         /* destroy connections */
385         for (i = 0; i<parameters.concurrent; i++)
386             {
387                 ZOOM_resultset_destroy (r[i]);
388                 ZOOM_connection_destroy (z[i]);
389             }
390
391
392
393     } /* for (k = 0; k < parameters.repeat; k++) repeat loop */
394
395     /* output */
396
397     if (parameters.gnuplot){
398         printf("# gnuplot data and instruction file \n");
399         printf("# gnuplot thisfile \n");
400         printf("\n");
401         printf("set title \"Z39.50 connection plot\"\n");
402         printf("set xlabel \"Connection\"\n");
403         printf("set ylabel \"Time Seconds\"\n");
404         printf("set zlabel \"Progress\"\n");
405         printf("set ticslevel 0\n");
406         printf("set grid\n");
407         printf("set pm3d\n");
408         printf("splot '-' using ($1):($2):($3) t '' with points\n");
409         printf("\n");
410         printf("\n");
411     }
412
413     print_table_header();
414     print_events(elc,  els, parameters.concurrent);
415
416     if (parameters.gnuplot){
417         printf("end\n");
418         printf("pause -1 \"Hit ENTER to return\"\n");
419     }
420
421     /* destroy data structures and exit */
422     xfree(z);
423     xfree(r);
424     xfree(elc);
425     xfree(els);
426     ZOOM_options_destroy(o);
427     exit (0);
428 }
429 /*
430  * Local variables:
431  * c-basic-offset: 4
432  * c-file-style: "Stroustrup"
433  * indent-tabs-mode: nil
434  * End:
435  * vim: shiftwidth=4 tabstop=8 expandtab
436  */
437