added a -g switch for gnuplot instructions in output. This way, the outpit stream...
[yaz-moved-to-github.git] / zoom / zoom-benchmark.c
1 /*
2  * $Id: zoom-benchmark.c,v 1.12 2005-09-20 12:07:29 marc 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             //case 't':
223             //p_parameters->timeout = atoi(arg);
224             //        break;
225         case 'b':
226             p_parameters->piggypack = 1;
227                     break;
228         case 'g':
229             p_parameters->gnuplot = 1;
230                     break;
231         case 'n':
232             p_parameters->repeat = atoi(arg);
233                     break;
234         case 0:
235             print_option_error();
236             break;
237         default:
238             print_option_error();
239         }
240     }
241     
242     if(0){
243         printf("zoom-benchmark\n");
244         printf("   host:       %s \n", p_parameters->host);
245         printf("   query:      %s \n", p_parameters->query);
246         printf("   concurrent: %d \n", p_parameters->concurrent);
247         printf("   repeat:     %d \n", p_parameters->repeat);
248         //printf("   timeout:    %d \n", p_parameters->timeout);
249         printf("   proxy:      %s \n", p_parameters->proxy);
250         printf("   piggypack:  %d \n\n", p_parameters->piggypack);
251         printf("   gnuplot:    %d \n\n", p_parameters->gnuplot);
252     }
253
254     if (! strlen(p_parameters->host))
255         print_option_error();
256     if (! strlen(p_parameters->query))
257         print_option_error();
258     if (! (p_parameters->concurrent > 0))
259         print_option_error();
260     if (! (p_parameters->repeat > 0))
261         print_option_error();
262     if (! (p_parameters->timeout >= 0))
263         print_option_error();
264     if (! ( p_parameters->concurrent <= 4096))
265         print_option_error();
266 }
267
268 void print_table_header()
269 {
270     if (parameters.gnuplot)
271         printf("#");
272     printf ("target\tsecond.usec\tprogress\tevent\teventname\t");
273     printf("error\terrorname\n");
274 }
275
276
277 int main(int argc, char **argv)
278 {
279     struct time_type time;
280     ZOOM_connection *z;
281     ZOOM_resultset *r;
282     int *elc;
283     struct event_line_t *els;
284     ZOOM_options o;
285     int i;
286     int k;
287
288     init_statics();
289
290     read_params(argc, argv, &parameters);
291
292     z = xmalloc(sizeof(*z) * parameters.concurrent);
293     r = xmalloc(sizeof(*r) * parameters.concurrent);
294     elc = xmalloc(sizeof(*elc) * parameters.concurrent * parameters.repeat);
295     els = xmalloc(sizeof(*els) 
296                   * parameters.concurrent * parameters.repeat * 10);
297     o = ZOOM_options_create();
298
299     /* async mode */
300     ZOOM_options_set (o, "async", "1");
301
302     /* get first record of result set (using piggypack) */
303     if (parameters.piggypack)
304         ZOOM_options_set (o, "count", "1");
305
306     /* set proxy */
307     if (strlen(parameters.proxy))
308         ZOOM_options_set (o, "proxy", parameters.proxy);
309
310
311     /* preferred record syntax */
312     if (0){
313         ZOOM_options_set (o, "preferredRecordSyntax", "usmarc");
314         ZOOM_options_set (o, "elementSetName", "F");
315     }
316     
317     time_init(&time);
318     /* repeat loop */
319     for (k = 0; k < parameters.repeat; k++){
320
321         /* progress zeroing */
322         for (i = 0; i < 4096; i++){
323             parameters.progress[i] = k * 5 -1;
324         }
325
326         /* connect to all concurrent connections*/
327         for ( i = 0; i < parameters.concurrent; i++){
328             /* set event count to zero */
329             elc[k * parameters.concurrent + i] = 0;
330
331             /* create connection - pass options (they are the same for all) */
332             z[i] = ZOOM_connection_create(o);
333             
334             /* connect and init */
335             ZOOM_connection_connect(z[i], parameters.host, 0);
336         }
337         /* search all */
338         for (i = 0; i < parameters.concurrent; i++)
339             r[i] = ZOOM_connection_search_pqf (z[i], parameters.query);
340
341         /* network I/O. pass number of connections and array of connections */
342         while ((i = ZOOM_event (parameters.concurrent, z))){ 
343             int event = ZOOM_connection_last_event(z[i-1]);
344             const char *errmsg;
345             const char *addinfo;
346             int error = 0;
347             int progress = zoom_progress[event];
348             
349             if (event == ZOOM_EVENT_SEND_DATA || event == ZOOM_EVENT_RECV_DATA)
350                 continue;
351
352             time_stamp(&time);
353
354             /* updating events and event list */
355             error = ZOOM_connection_error(z[i-1] , &errmsg, &addinfo);
356             if (error)
357                 parameters.progress[i] = -progress;
358             else
359                 parameters.progress[i] += 1;
360             
361             update_events(elc, els,
362                           k, i-1, 
363                           time_sec(&time), time_usec(&time), 
364                           parameters.progress[i],
365                           event, zoom_events[event], 
366                           error, errmsg);
367         }
368
369         /* destroy connections */
370         for (i = 0; i<parameters.concurrent; i++)
371             {
372                 ZOOM_resultset_destroy (r[i]);
373                 ZOOM_connection_destroy (z[i]);
374             }
375
376
377
378     } // for (k = 0; k < parameters.repeat; k++) repeat loop
379
380     /* output */
381
382     if (parameters.gnuplot){
383         printf("# gnuplot data and instruction file \n");
384         printf("# gnuplot thisfile \n");
385         printf("\n");
386         printf("set title \"Z39.50 connection plot\"\n");
387         printf("set xlabel \"Connection\"\n");
388         printf("set ylabel \"Time Seconds\"\n");
389         printf("set zlabel \"Progress\"\n");
390         printf("set ticslevel 0\n");
391         printf("set grid\n");
392         printf("set pm3d\n");
393         printf("splot '-' using ($1):($2):($3) t '' with points\n");
394         printf("\n");
395         printf("\n");
396     }
397     
398     print_table_header();    
399     print_events(elc,  els, parameters.concurrent);
400     
401     if (parameters.gnuplot){
402         printf("end\n");
403         printf("pause -1 \"Hit ENTER to return\"\n");
404     }
405
406     /* destroy data structures and exit */
407     xfree(z);
408     xfree(r);
409     xfree(elc);
410     xfree(els);
411     ZOOM_options_destroy(o);
412     exit (0);
413 }
414 /*
415  * Local variables:
416  * c-basic-offset: 4
417  * indent-tabs-mode: nil
418  * End:
419  * vim: shiftwidth=4 tabstop=8 expandtab
420  */
421