Changeset: db6e9ac5e2c6 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=db6e9ac5e2c6
Added Files:
        clients/mapiclient/tachograph.c
Modified Files:
        clients/mapiclient/Makefile.ag
        clients/mapiclient/tomograph.c
Branch: default
Log Message:

Add tachograph progress monitor
The infrastructure for producing web-based progress monitoring
and MAL execution trace analysis. The trace can be fed to tomograph.


diffs (truncated from 1112 to 300 lines):

diff --git a/clients/mapiclient/Makefile.ag b/clients/mapiclient/Makefile.ag
--- a/clients/mapiclient/Makefile.ag
+++ b/clients/mapiclient/Makefile.ag
@@ -39,14 +39,21 @@ bin_msqldump = {
 }
 
 bin_stethoscope = {
-       SOURCES = stethoscope.c
+       SOURCES = eventparser.c stethoscope.c
+       LIBS = libmcutil ../mapilib/libmapi \
+               ../../common/stream/libstream \
+               $(curl_LIBS) $(MALLOC_LIBS) $(PTHREAD_LIBS) $(SOCKET_LIBS)
+}
+
+bin_tachograph = {
+       SOURCES = eventparser.c tachograph.c
        LIBS = libmcutil ../mapilib/libmapi \
                ../../common/stream/libstream \
                $(curl_LIBS) $(MALLOC_LIBS) $(PTHREAD_LIBS) $(SOCKET_LIBS)
 }
 
 bin_tomograph = {
-       SOURCES = tomograph.c
+       SOURCES = eventparser.c tomograph.c
        LIBS = libmcutil ../mapilib/libmapi \
                ../../common/stream/libstream \
                $(curl_LIBS) $(MALLOC_LIBS) $(PTHREAD_LIBS) $(SOCKET_LIBS)
diff --git a/clients/mapiclient/tachograph.c b/clients/mapiclient/tachograph.c
new file mode 100644
--- /dev/null
+++ b/clients/mapiclient/tachograph.c
@@ -0,0 +1,492 @@
+/*
+ * The contents of this file are subject to the MonetDB Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.monetdb.org/Legal/MonetDBLicense
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is the MonetDB Database System.
+ *
+ * The Initial Developer of the Original Code is CWI.
+ * Portions created by CWI are Copyright (C) 1997-July 2008 CWI.
+ * Copyright August 2008-2015 MonetDB B.V.
+ * All Rights Reserved.
+ */
+
+/* (c) M Kersten
+ * Progress indicator
+ * tachograph -d demo 
+ * which connects to the demo database server and
+ * will present a progress bar for each query.
+*/
+
+#include "monetdb_config.h"
+#include "monet_options.h"
+#include <mapi.h>
+#include <stream.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+#include "mprompt.h"
+#include "dotmonetdb.h"
+#include "eventparser.h"
+
+#ifndef HAVE_GETOPT_LONG
+# include "monet_getopt.h"
+#else
+# ifdef HAVE_GETOPT_H
+#  include "getopt.h"
+# endif
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#define die(dbh, hdl)                                          \
+       do {                                                    \
+               (hdl ? mapi_explain_query(hdl, stderr) :        \
+                dbh ? mapi_explain(dbh, stderr) :              \
+                fprintf(stderr, "!! command failed\n"));       \
+               goto stop_disconnect;                           \
+       } while (0)
+
+#define doQ(X)                                                         \
+       do {                                                            \
+               if ((hdl = mapi_query(dbh, X)) == NULL ||       \
+                   mapi_error(dbh) != MOK)                     \
+                       die(dbh, hdl);                  \
+       } while (0)
+
+static stream *conn = NULL;
+static char hostname[128];
+static char *basefilename = "tacho";
+static char *dbname;
+static Mapi dbh;
+static MapiHdl hdl = NULL;
+static int capturing=0;
+
+/*
+ * Parsing the argument list of a MAL call to obtain un-quoted string values
+ */
+
+static void
+usageTachograph(void)
+{
+    fprintf(stderr, "tachograph [options] \n");
+    fprintf(stderr, "  -d | --dbname=<database_name>\n");
+    fprintf(stderr, "  -u | --user=<user>\n");
+    fprintf(stderr, "  -p | --port=<portnr>\n");
+    fprintf(stderr, "  -h | --host=<hostname>\n");
+    fprintf(stderr, "  -o | --output=<webfile>\n");
+    fprintf(stderr, "  -? | --help\n");
+       exit(-1);
+}
+
+/* Any signal should be captured and turned into a graceful
+ * termination of the profiling session. */
+
+static void
+stopListening(int i)
+{
+       fprintf(stderr,"signal %d received\n",i);
+       if( dbh)
+               doQ("profiler.stop();");
+stop_disconnect:
+       // show follow up action only once
+       if(dbh)
+               mapi_disconnect(dbh);
+       exit(0);
+}
+
+char *currentfunction= 0;
+char *currentquery= 0;
+lng starttime = 0;
+lng finishtime = 0;
+lng duration =0;
+int malsize = 0;
+
+static FILE *tachofd;
+
+static void resetTachograph(void){
+       if (debug)
+               fprintf(stderr, "RESET tachograph\n");
+       malsize= 0;
+       malargtop =0;
+       currentfunction = 0;
+       currentquery = 0;
+       starttime = 0;
+       finishtime = 0;
+       duration =0;
+       fclose(tachofd);
+       tachofd = 0;
+}
+
+/*
+static char stamp[BUFSIZ];
+static void
+rendertime(lng ticks)
+{
+       int t, hr,min,sec;
+       t = (int) (ticks/1000000);
+       sec = t % 60;
+       min = (t /60) %60;
+       hr = (t /3600);
+       snprintf(stamp,BUFSIZ,"%02d:%02d:%02d.%06d", hr,min,sec, (int) ticks 
%1000000); 
+}
+*/
+/* create the progressbar JSON file for pickup */
+static void
+progressBarInit(void)
+{
+       char buf[BUFSIZ];
+
+       snprintf(buf,BUFSIZ,"%s_%s.json",basefilename,dbname);
+       tachofd= fopen(buf,"w");
+       if( tachofd == NULL){
+               fprintf(stderr,"Could not create %s\n",buf);
+               exit(0);
+       }
+       fprintf(tachofd,"{ \"tachograph\":0.1,\n");
+       fprintf(tachofd," 
\"qid\":\"%s\",\n",currentfunction?currentfunction:"");
+       fprintf(tachofd," \"query\":\"%s\",\n",currentquery?currentquery:"");
+       fprintf(tachofd," \"started\": "LLFMT",\n",starttime);
+       fprintf(tachofd," \"duration\":"LLFMT"\n",duration);
+       fprintf(tachofd," \"instructions\":%d\n",malsize);
+       fprintf(tachofd,"},\n");
+       fflush(tachofd);
+}
+
+static void
+update(EventRecord *ev)
+{
+       int i;
+       char *qry, *q = 0, *c;
+       int uid = 0,qid = 0;
+ 
+       /* handle a ping event, keep the current instruction in focus */
+       if (ev->state >= PING ) {
+               // All state events are ignored
+               return;
+       }
+
+       if (debug)
+               fprintf(stderr, "Update %s input %s stmt %s time " 
LLFMT"\n",(ev->state>=0?statenames[ev->state]:"unknown"),(ev->fcn?ev->fcn:"(null)"),(currentfunction?currentfunction:""),ev->clkticks
 -starttime);
+
+       if (starttime == 0) {
+               if (ev->fcn == 0 ) {
+                       if (debug)
+                               fprintf(stderr, "Skip %s input 
%s\n",(ev->state>=0?statenames[ev->state]:"unknown"),ev->fcn);
+                       return;
+               }
+               if (debug)
+                       fprintf(stderr, "Start capturing updates %s\n",ev->fcn);
+       }
+       if (ev->clkticks < 0) {
+               /* HACK: *TRY TO* compensate for the fact that the MAL
+                * profiler chops-off day information, and assume that
+                * clkticks is < starttime because the tomograph run
+                * crossed a day boundary (midnight);
+                * we simply add 1 day (24 hours) worth of microseconds.
+                * NOTE: this surely does NOT work correctly if the
+                * tomograph run takes 24 hours or more ...
+                */
+               ev->clkticks += US_DD;
+       }
+
+       /* monitor top level function brackets, we restrict ourselves to SQL 
queries */
+       if (!capturing && ev->state == START && ev->fcn && strncmp(ev->fcn, 
"function", 8) == 0) {
+               if( (i = sscanf(ev->fcn + 9,"user.s%d_%d",&uid,&qid)) != 2){
+                       if( debug)
+                               fprintf(stderr,"Start phase parsing %d, uid %d 
qid %d\n",i,uid,qid);
+                       return;
+               }
+               if (capturing++ == 0){
+                       starttime = ev->clkticks;
+                       finishtime = ev->clkticks + ev->ticks;
+                       duration = ev->ticks;
+               }
+               if (currentfunction == 0)
+                       currentfunction = strdup(ev->fcn+9);
+               if (debug)
+                       fprintf(stderr, "Enter function %s capture %d\n", 
currentfunction, capturing);
+               return;
+       }
+       ev->clkticks -= starttime;
+
+       if ( !capturing || ev->thread >= MAXTHREADS)
+               return;
+
+       /* start of instruction box */
+       if (ev->state == START ) {
+               if(ev->fcn && strstr(ev->fcn,"querylog.define") ){
+                       // extract a string argument
+                       currentquery = malarguments[0];
+                       malsize = atoi(malarguments[3]);
+                       // use the truncated query text, beware the the \ is 
already escaped in the call argument.
+                       q = qry = (char *) malloc(strlen(currentquery) * 2);
+                       for (c= currentquery; *c; )
+                               switch(*c){
+                               case '\\':
+                                       c++;
+                                       switch(*c){
+                                       case 'n': *q++=' '; c++; break;
+                                       case 't': *q++=' '; c++; break;
+                                       case '\\': break;
+                                       default:
+                                               *q++ = *c++;
+                                       }
+                                       break;
+                               default:
+                                       *q++ = *c++;
+                               }
+                       *q =0;
+                       currentquery = qry;
+                       progressBarInit();
+               }
+               fprintf(tachofd,"{\n");
+               
fprintf(tachofd,"\"qid\":\"%s\",\n",currentfunction?currentfunction:"");
+               fprintf(tachofd,"\"time\": "LLFMT",\n",ev->clkticks);
+               fprintf(tachofd,"\"status\": \"start\",\n");
+               fprintf(tachofd,"\"estimate\": "LLFMT",\n",ev->ticks);
+               fprintf(tachofd,"\"stmt\": \"%s\"\n",ev->stmt);
+               fprintf(tachofd,"},\n");
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to