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