Ignore zoomst10
[yaz-moved-to-github.git] / zoom / zoom-benchmark.c
index 19e83e8..722c4f2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: zoom-benchmark.c,v 1.1 2005-09-07 13:45:15 marc Exp $
+ * $Id: zoom-benchmark.c,v 1.13 2005-10-22 13:28:03 adam Exp $
  *
  * Asynchronous multi-target client doing search and piggyback retrieval
  */
 #include <sys/time.h>
 
 #include <yaz/xmalloc.h>
+#include <yaz/options.h>
 #include <yaz/zoom.h>
 
 
+/* naming events */
+static char* zoom_events[10];
 
+/* re-sorting event numbers to progress numbers */
+static int zoom_progress[10];
 
-int main(int argc, char **argv)
+/* commando line parameters */
+static struct parameters_t { 
+    char host[1024];
+    char query[1024];
+    int progress[4096];
+    int concurrent;
+    int repeat;
+    int timeout;
+    char proxy[1024];
+    int piggypack;
+    int gnuplot;
+} parameters;
+
+struct  event_line_t 
 {
+    int connection;
+    long time_sec;
+    long time_usec;
+    int progress;
+    int event;
+    char zoom_event[128];
+    int error;
+    char errmsg[128];
+};
 
-    struct timeval now;
-    struct timeval then;
-    long sec=0, usec=0;
 
+void print_event_line(struct event_line_t *pel)
+{
+    printf ("%d\t%ld.%06ld\t%d\t%d\t%s\t%d\t%s\n",
+            pel->connection, pel->time_sec, pel->time_usec, 
+            pel->progress,
+            pel->event, pel->zoom_event, 
+            pel->error, pel->errmsg);
+}
+
+void  update_events(int *elc, struct event_line_t *els,
+                    int repeat,
+                    int conn,
+                    long sec,
+                    long usec,
+                    int prog,
+                    int event,
+                    const char * eventmsg,
+                    int error,
+                    const char * errmsg){
+
+    int ielc = repeat*parameters.concurrent + conn;
+    int iels = repeat*parameters.concurrent*10 + conn*10 + elc[ielc];
+
+    els[iels].connection = conn;
+    els[iels].time_sec = sec;
+    els[iels].time_usec = usec;
+    els[iels].progress = prog;
+    els[iels].event = event;
+    strcpy(els[iels].zoom_event, eventmsg);
+    els[iels].error = error;
+    strcpy(els[iels].errmsg, errmsg);
+    /* print_event_line(&els[iels]); */
+    elc[ielc] += 1;
+}
+
+void  print_events(int *elc,  struct event_line_t *els, 
+                   int connections){
     int i;
-    int same_target = 0;
-    int no = argc-2;
-    ZOOM_connection z[1024]; /* allow at most 1024 connections */
-    ZOOM_resultset r[1024];  /* and result sets .. */
-    ZOOM_options o = ZOOM_options_create ();
+    int j;
+    int k;
+    int ielc;
+    int iels;
 
-    if (argc < 3)
-    {
-        fprintf (stderr, "usage:\n%s target1 target2 ... targetN query\n",
-                 *argv);
-        exit (1);
-    }
-    if (argc == 4 && isdigit(argv[1][0]) && !strchr(argv[1],'.'))
-    {
-        no = atoi(argv[1]);
-        same_target = 1;
+    for (k=0; k < parameters.repeat; k++){
+        for (i=0; i < connections; i++){
+            ielc = k * parameters.concurrent + i;
+            for (j=0; j < elc[ielc]; j++){
+                iels = k * parameters.concurrent * 10 + i * 10 + j;
+                print_event_line(&els[iels]);
+            }
+            printf("\n");
+        }
+        printf("\n");
     }
+}
+
+
 
-    if (no > 500)
-        no = 500;
+void init_statics()
+{
+    int i;
+    char nullstring[1] = "";
 
     /* naming events */
-    
-    //typedef enum {
-    //    ZOOM_EVENT_NONE = 0,
-    //    ZOOM_EVENT_CONNECT = 1,
-    //    ZOOM_EVENT_SEND_DATA  = 2,
-    //    ZOOM_EVENT_RECV_DATA = 3,
-    //    ZOOM_EVENT_TIMEOUT = 4,
-    //    ZOOM_EVENT_UNKNOWN = 5,
-    //    ZOOM_EVENT_SEND_APDU = 6,
-    //    ZOOM_EVENT_RECV_APDU = 7,
-    //    ZOOM_EVENT_RECV_RECORD = 8,
-    //    ZOOM_EVENT_RECV_SEARCH = 9
-    //} ZOOM_events;
-
-    char* zoom_events[10];
     zoom_events[ZOOM_EVENT_NONE] = "ZOOM_EVENT_NONE";
     zoom_events[ZOOM_EVENT_CONNECT] = "ZOOM_EVENT_CONNECT";
     zoom_events[ZOOM_EVENT_SEND_DATA] = "ZOOM_EVENT_SEND_DATA";
@@ -72,7 +122,7 @@ int main(int argc, char **argv)
     zoom_events[ZOOM_EVENT_RECV_RECORD] = "ZOOM_EVENT_RECV_RECORD";
     zoom_events[ZOOM_EVENT_RECV_SEARCH] = "ZOOM_EVENT_RECV_SEARCH";
 
-    int zoom_progress[10];
+    /* re-sorting event numbers to progress numbers */
     zoom_progress[ZOOM_EVENT_NONE] = 0;
     zoom_progress[ZOOM_EVENT_CONNECT] = 1;
     zoom_progress[ZOOM_EVENT_SEND_DATA] = 3;
@@ -83,108 +133,285 @@ int main(int argc, char **argv)
     zoom_progress[ZOOM_EVENT_RECV_APDU] = 5;
     zoom_progress[ZOOM_EVENT_RECV_RECORD] = 7;
     zoom_progress[ZOOM_EVENT_RECV_SEARCH] = 6;
-   
 
-    /* async mode */
-    ZOOM_options_set (o, "async", "1");
+    /* parameters */
+    parameters.concurrent = 1;
+    parameters.timeout = 0;
+    parameters.repeat = 1;
+    strcpy(parameters.proxy, nullstring);
+    parameters.gnuplot = 0;
+    parameters.piggypack = 0;
 
-    /* get first 10 records of result set (using piggyback) */
-    ZOOM_options_set (o, "count", "1");
+    /* progress initializing */
+    for (i = 0; i < 4096; i++){
+        parameters.progress[i] = 0;
+    }
+    
+}
+struct time_type 
+{
+    struct timeval now;
+    struct timeval then;
+    long sec;
+    long usec;
+};
 
-    /* preferred record syntax */
-    //ZOOM_options_set (o, "preferredRecordSyntax", "usmarc");
-    //ZOOM_options_set (o, "elementSetName", "F");
+void time_init(struct time_type *ptime)
+{
+    gettimeofday(&(ptime->now), 0);
+    gettimeofday(&(ptime->then), 0);
+    ptime->sec = 0;
+    ptime->usec = 0;
+}
 
-    /* connect to all */
-    for (i = 0; i<no; i++)
-    {
-        /* create connection - pass options (they are the same for all) */
-        z[i] = ZOOM_connection_create (o);
-
-        /* connect and init */
-        if (same_target)
-            ZOOM_connection_connect (z[i], argv[2], 0);
-        else
-            ZOOM_connection_connect (z[i], argv[1+i], 0);
+void time_stamp(struct time_type *ptime)
+{
+    gettimeofday(&(ptime->now), 0);
+    ptime->sec = ptime->now.tv_sec - ptime->then.tv_sec;
+    ptime->usec = ptime->now.tv_usec - ptime->then.tv_usec;
+    if (ptime->usec < 0){
+        ptime->sec--;
+        ptime->usec += 1000000;
     }
-    /* search all */
-    for (i = 0; i<no; i++)
-        r[i] = ZOOM_connection_search_pqf (z[i], argv[argc-1]);
-
-    printf ("second.usec target progress event eventname error errorname\n");
-
-
-    gettimeofday(&then, 0);
-    /* network I/O. pass number of connections and array of connections */
-    while ((i = ZOOM_event (no, z)))
-    { 
-
-        int event = ZOOM_connection_last_event(z[i-1]);
-        const char *errmsg;
-        const char *addinfo;
-        int error = 0;
-        int progress = zoom_progress[event];
-
-        gettimeofday(&now, 0);
-        //stamp(&now, &then);
-        sec = now.tv_sec - then.tv_sec;
-        usec = now.tv_usec - then.tv_usec;
-        if (usec < 0){
-            sec--;
-            usec += 1000000;
+}
+
+long time_sec(struct time_type *ptime)
+{
+    return ptime->sec;
+}
+
+long time_usec(struct time_type *ptime)
+{
+    return ptime->usec;
+}
+
+void print_option_error()
+{
+    fprintf(stderr, "zoom-benchmark:  Call error\n");
+    fprintf(stderr, "zoom-benchmark -h host:port -q pqf-query "
+            "[-c no_concurrent (max 4096)] "
+            "[-n no_repeat] "
+            "[-b (piggypack)] "
+            "[-g (gnuplot outfile)] "
+            "[-p proxy] \n");
+    /* "[-t timeout] \n"); */
+    exit(1);
+}
+
+
+void read_params(int argc, char **argv, struct parameters_t *p_parameters){    
+    char *arg;
+    int ret;
+    while ((ret = options("h:q:c:t:p:bgn:", argv, argc, &arg)) != -2)
+    {
+        switch (ret)
+        {
+        case 'h':
+            strcpy(p_parameters->host, arg);
+            break;
+        case 'q':
+            strcpy(p_parameters->query, arg);
+            break;
+        case 'p':
+            strcpy(p_parameters->proxy, arg);
+            break;
+        case 'c':
+            p_parameters->concurrent = atoi(arg);
+            break;
+#if 0
+            case 't':
+            p_parameters->timeout = atoi(arg);
+            break;
+#endif
+        case 'b':
+            p_parameters->piggypack = 1;
+                    break;
+        case 'g':
+            p_parameters->gnuplot = 1;
+                    break;
+        case 'n':
+            p_parameters->repeat = atoi(arg);
+                    break;
+        case 0:
+            print_option_error();
+            break;
+        default:
+            print_option_error();
         }
-        error = ZOOM_connection_error(z[i-1] , &errmsg, &addinfo);
-        if (error)
-            progress = -progress;
-        
-        printf ("%i.%06i %d %d %d %s %d '%s' \n", sec, usec, 
-                i-1, progress,
-                event, zoom_events[event], 
-                error, errmsg);
+    }
+    
+    if(0){
+        printf("zoom-benchmark\n");
+        printf("   host:       %s \n", p_parameters->host);
+        printf("   query:      %s \n", p_parameters->query);
+        printf("   concurrent: %d \n", p_parameters->concurrent);
+        printf("   repeat:     %d \n", p_parameters->repeat);
+#if 0
+        printf("   timeout:    %d \n", p_parameters->timeout);
+#endif
+        printf("   proxy:      %s \n", p_parameters->proxy);
+        printf("   piggypack:  %d \n\n", p_parameters->piggypack);
+        printf("   gnuplot:    %d \n\n", p_parameters->gnuplot);
+    }
+
+    if (! strlen(p_parameters->host))
+        print_option_error();
+    if (! strlen(p_parameters->query))
+        print_option_error();
+    if (! (p_parameters->concurrent > 0))
+        print_option_error();
+    if (! (p_parameters->repeat > 0))
+        print_option_error();
+    if (! (p_parameters->timeout >= 0))
+        print_option_error();
+    if (! ( p_parameters->concurrent <= 4096))
+        print_option_error();
+}
+
+void print_table_header()
+{
+    if (parameters.gnuplot)
+        printf("#");
+    printf ("target\tsecond.usec\tprogress\tevent\teventname\t");
+    printf("error\terrorname\n");
+}
+
+
+int main(int argc, char **argv)
+{
+    struct time_type time;
+    ZOOM_connection *z;
+    ZOOM_resultset *r;
+    int *elc;
+    struct event_line_t *els;
+    ZOOM_options o;
+    int i;
+    int k;
+
+    init_statics();
+
+    read_params(argc, argv, &parameters);
+
+    z = xmalloc(sizeof(*z) * parameters.concurrent);
+    r = xmalloc(sizeof(*r) * parameters.concurrent);
+    elc = xmalloc(sizeof(*elc) * parameters.concurrent * parameters.repeat);
+    els = xmalloc(sizeof(*els) 
+                  * parameters.concurrent * parameters.repeat * 10);
+    o = ZOOM_options_create();
+
+    /* async mode */
+    ZOOM_options_set (o, "async", "1");
+
+    /* get first record of result set (using piggypack) */
+    if (parameters.piggypack)
+        ZOOM_options_set (o, "count", "1");
+
+    /* set proxy */
+    if (strlen(parameters.proxy))
+        ZOOM_options_set (o, "proxy", parameters.proxy);
+
 
+    /* preferred record syntax */
+    if (0){
+        ZOOM_options_set (o, "preferredRecordSyntax", "usmarc");
+        ZOOM_options_set (o, "elementSetName", "F");
     }
     
-    /* no more to be done. Inspect results */
-    for (i = 0; i<no && 0; i++)
-    {
-        int error;
-        const char *errmsg, *addinfo;
-        const char *tname = (same_target ? argv[2] : argv[1+i]);
-        /* display errors if any */
-        if ((error = ZOOM_connection_error(z[i], &errmsg, &addinfo)))
-            fprintf (stderr, "%s error: %s (%d) %s\n", tname, errmsg,
-                     error, addinfo);
-        else
-        {
-            /* OK, no major errors. Look at the result count */
-            int pos;
-            printf ("%s: %d hits\n", tname, ZOOM_resultset_size(r[i]));
-            /* go through all records at target */
-            for (pos = 0; pos < 10; pos++)
+    time_init(&time);
+    /* repeat loop */
+    for (k = 0; k < parameters.repeat; k++){
+
+        /* progress zeroing */
+        for (i = 0; i < 4096; i++){
+            parameters.progress[i] = k * 5 -1;
+        }
+
+        /* connect to all concurrent connections*/
+        for ( i = 0; i < parameters.concurrent; i++){
+            /* set event count to zero */
+            elc[k * parameters.concurrent + i] = 0;
+
+            /* create connection - pass options (they are the same for all) */
+            z[i] = ZOOM_connection_create(o);
+            
+            /* connect and init */
+            ZOOM_connection_connect(z[i], parameters.host, 0);
+        }
+        /* search all */
+        for (i = 0; i < parameters.concurrent; i++)
+            r[i] = ZOOM_connection_search_pqf (z[i], parameters.query);
+
+        /* network I/O. pass number of connections and array of connections */
+        while ((i = ZOOM_event (parameters.concurrent, z))){ 
+            int event = ZOOM_connection_last_event(z[i-1]);
+            const char *errmsg;
+            const char *addinfo;
+            int error = 0;
+            int progress = zoom_progress[event];
+            
+            if (event == ZOOM_EVENT_SEND_DATA || event == ZOOM_EVENT_RECV_DATA)
+                continue;
+
+            time_stamp(&time);
+
+            /* updating events and event list */
+            error = ZOOM_connection_error(z[i-1] , &errmsg, &addinfo);
+            if (error)
+                parameters.progress[i] = -progress;
+            else
+                parameters.progress[i] += 1;
+            
+            update_events(elc, els,
+                          k, i-1, 
+                          time_sec(&time), time_usec(&time), 
+                          parameters.progress[i],
+                          event, zoom_events[event], 
+                          error, errmsg);
+        }
+
+        /* destroy connections */
+        for (i = 0; i<parameters.concurrent; i++)
             {
-                int len; /* length of buffer rec */
-                const char *rec =
-                    ZOOM_record_get (
-                        ZOOM_resultset_record (r[i], pos), "render", &len);
-                /* if rec is non-null, we got a record for display */
-                if (rec)
-                {
-                    printf ("%d\n", pos+1);
-                    if (rec)
-                        fwrite (rec, 1, len, stdout);
-                    printf ("\n");
-                }
+                ZOOM_resultset_destroy (r[i]);
+                ZOOM_connection_destroy (z[i]);
             }
-        }
-    }
 
-    /* destroy and exit */
-    for (i = 0; i<no; i++)
-    {
-        ZOOM_resultset_destroy (r[i]);
-        ZOOM_connection_destroy (z[i]);
+
+
+    } /* for (k = 0; k < parameters.repeat; k++) repeat loop */
+
+    /* output */
+
+    if (parameters.gnuplot){
+        printf("# gnuplot data and instruction file \n");
+        printf("# gnuplot thisfile \n");
+        printf("\n");
+        printf("set title \"Z39.50 connection plot\"\n");
+        printf("set xlabel \"Connection\"\n");
+        printf("set ylabel \"Time Seconds\"\n");
+        printf("set zlabel \"Progress\"\n");
+        printf("set ticslevel 0\n");
+        printf("set grid\n");
+        printf("set pm3d\n");
+        printf("splot '-' using ($1):($2):($3) t '' with points\n");
+        printf("\n");
+        printf("\n");
+    }
+    
+    print_table_header();    
+    print_events(elc,  els, parameters.concurrent);
+    
+    if (parameters.gnuplot){
+        printf("end\n");
+        printf("pause -1 \"Hit ENTER to return\"\n");
     }
+
+    /* destroy data structures and exit */
+    xfree(z);
+    xfree(r);
+    xfree(elc);
+    xfree(els);
     ZOOM_options_destroy(o);
     exit (0);
 }