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