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