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