2 // customized (for barchart) version of DGclient.C in tclVisi directory
5 /* Revision 1.2 1994/09/29 20:05:39 tamches
8 * Revision 1.1 1994/09/29 19:52:25 tamches
9 * initial implementation.
10 * This is a modified version of DGclient.C (tclVisi/src), specially
11 * tuned for the barchart program.
15 // An updated version of DGClient.C for barchart2.C
16 // Contains several **deletions** to remove blt_barchart influences
18 #include <stdlib.h> // exit()
23 #include "visi/h/visualization.h"
24 #include "barChartTcl.h"
27 void my_visi_callback(void* arg0, int* arg1, long unsigned int* arg2) {
28 if (visi_callback() == -1)
32 int Dg2AddMetricsCallback(int dummy) {
33 int retval = Tcl_Eval(MainInterp, "DgConfigCallback");
34 if (retval == TCL_ERROR)
35 fprintf(stderr, "%s\n", MainInterp->result);
37 // if necessary, the tcl program will call xAxisHasChanged and/or yAxisHasChanged, which
38 // are commands we implement in barChart.C.
39 // We take action then.
44 //int Dg2NewDataCallbackGeneral(int dummy) {
45 // // A fairly general new-data handler; is smart enough to
46 // // know when and if a **range** of values needs to be redrawn
47 // // (perhaps because we've fallen behind?) as opposed to just
48 // // the latest value --- the histogram would need this, for
49 // // example (to avoid gaps), but the barchart can always just use
50 // // the most recent value and not care if it's fallen behind...
52 // // A more specific one is actually in use at the moment; it
53 // // is Dg2NewDataCallback(). I haven't deleted the source code for
54 // // this guy since it's potentially useful for visis other than
57 // // I have, however, removed the "DgValidCallback" from the original
60 // static LastBucket = 0; // this very important STATIC variable keeps
61 // // track of the last bucket number we've processed.
62 // // We'll be sending a data-callback on range
63 // // LastBucket+1 thru what we see as the latest bucket
64 // // which has been filled with data. Presumably, if
65 // // we keep up, this'll always be the range
66 // // (LastBucket+1, LastBucket+1).
68 // // set "thislast" to dataGrid[m][r].LastBucketFilled() for the first
69 // // datagrid element we find with the Valid bit set to true...
70 // int thislast = findMostRecentBucket();
72 // // There are no more "DgValidCallback" calls, since barchart never
73 // // seemed to use them in the first place...
75 // if (thislast < LastBucket)
76 // LastBucket = thislast-1; // will rarely if ever happen; just to avoid sending
77 // // an empty range...
79 // if (thislast >= 0) {
80 // // send a data-callback on range (LastBucket+1, thislast)
81 // // This is where the previous version of Dg would invoke
82 // // the tcl script DgDataCallback. Now that we're C++, we don't
85 // UsersNewDataCallbackRoutine(LastBucket+1, thislast);
87 // LastBucket = thislast;
93 int Dg2Fold(int dummy) {
94 int retval = Tcl_Eval(MainInterp, "DgFoldCallback");
95 if (retval == TCL_ERROR)
96 fprintf(stderr, "%s\n", MainInterp->result);
101 int Dg2InvalidMetricsOrResources(int dummy) {
102 int retval = Tcl_Eval(MainInterp, "DgInvalidCallback");
103 if (retval == TCL_ERROR)
104 fprintf(stderr, "%s\n", MainInterp->result);
109 int Dg2PhaseNameCallback(int dummy) {
110 int retval = Tcl_Eval(MainInterp, "DgPhaseCallback");
111 if (retval == TCL_ERROR)
112 fprintf(stderr, "%s\n", MainInterp->result);
121 #define METRICUNITS 4
124 #define NUMRESOURCES 7
125 #define DEFINEPHASE 8
126 #define RESOURCENAME 9
127 #define STARTSTREAM 10
128 #define STOPSTREAM 11
133 #define LASTBUCKET 16
134 #define FIRSTBUCKET 18
143 static struct cmdTabEntry Dg_Cmds[] = {
144 {"aggregate", AGGREGATE, 2},
145 {"binwidth", BINWIDTH, 0},
146 {"firstbucket", FIRSTBUCKET, 2},
147 {"foldmethod", FOLDMETHOD, 2},
148 {"lastbucket", LASTBUCKET, 2},
149 {"metricname", METRICNAME, 1},
150 {"metricunits", METRICUNITS, 1},
151 {"numbins", NUMBINS, 0},
152 {"nummetrics", NUMMETRICS, 0},
153 {"numresources", NUMRESOURCES, 0},
154 {"phase", DEFINEPHASE, 3},
155 {"resourcename", RESOURCENAME, 1},
156 {"start", STARTSTREAM, 2},
157 {"stop", STOPSTREAM, 2},
159 {"valid", DGVALID, 2},
164 int findCommand(Tcl_Interp *interp,
169 sprintf(interp->result, "USAGE: Dg <option> [args...]\n");
173 for (cmdTabEntry *C = Dg_Cmds; C->cmdname!=NULL; C++) {
174 if (strcmp(argv[0], C->cmdname) == 0) {
175 if (argc-1 == C->numargs)
176 return C->index; // successful parsing
178 sprintf(interp->result,
179 "%s: wrong number of args (%d). Should be %d\n",
180 argv[0], argc-1, C->numargs);
185 sprintf(interp->result, "unknown option (%s)\n", argv[0]);
189 int Dg_TclCommand(ClientData clientData,
193 // entrypoint to the tcl "Dg" command we've installed
194 // all the sprintf()'s are rather slow...
196 // parse the arguments, using the global variable Dg_Cmds[] to tell what's what.
197 int cmdDex = findCommand(interp, argc-1, argv+1);
198 if (cmdDex == CMDERROR)
201 int m, r, buck; // metric number, resource number, bucket number
207 sprintf(interp->result,"%g", dataGrid.AggregateValue(m,r));
211 sprintf(interp->result, "%g", dataGrid.BinWidth());
217 sprintf(interp->result,"%d", dataGrid[m][r].FirstValidBucket());
222 sprintf(interp->result,"%d", dataGrid.FoldMethod(m));
228 sprintf(interp->result,"%d", dataGrid[m][r].LastBucketFilled());
233 sprintf(interp->result, "%s", dataGrid.MetricName(m));
238 sprintf(interp->result, "%s", dataGrid.MetricUnits(m));
242 sprintf(interp->result, "%d", dataGrid.NumBins());
246 sprintf(interp->result, "%d", dataGrid.NumMetrics());
250 sprintf(interp->result, "%d", dataGrid.NumResources());
254 NamePhase(atof(argv[2]), atof(argv[3]), argv[4]);
259 sprintf(interp->result, "%s", dataGrid.ResourceName(r));
263 GetMetsRes(argv[2], argv[3], 0);
275 sprintf(interp->result,"%g", dataGrid.SumValue(m,r));
281 sprintf(interp->result, "%d", dataGrid.Valid(m,r));
287 buck = atoi(argv[4]);
288 sprintf(interp->result,"%g", dataGrid[m][r].Value(buck));
292 sprintf(interp->result, "Internal error (func findCommand)\n");
296 void (*UsersNewDataCallbackRoutine)(int firstBucket, int lastBucket);
297 // we will call this routine for you when we get a new-data callback
298 // from the visi lib (first, we do a bit of processing for you, such
299 // as determining what the range is buckets you haven't seen yet is).
301 //int Dg2_Init(Tcl_Interp *interp, void (*userDataCallbackRoutine)(int, int)) {
302 int Dg2_Init(Tcl_Interp *interp) {
303 // initialize with the visi lib
306 cerr << "Dg2_Init() -- could not initialize with the visi lib" << endl;
310 // Arrange for my_visi_callback() to be called whenever there is data waiting
311 // to be read off of descriptor "fd". Extremely important! [tcl book page 357]
312 Tk_CreateFileHandler(fd, TK_READABLE, (Tk_FileProc *) my_visi_callback, 0);
314 // Register C++ Callback routines with the visi lib when
315 // certain events happen. The most important (performance-wise)
316 // is the DATAVALUES callback, which signals the arrival of
317 // new barchart data. We must process this callback very quickly,
318 // in order to perturb the system as little as possible.
320 if (RegistrationCallback(ADDMETRICSRESOURCES, Dg2AddMetricsCallback) != 0) {
321 cerr << "Dg2_Init() -- couldn't install ADDMETRICSRESOURCES callback with visilib" << endl;
325 if (RegistrationCallback(FOLD, Dg2Fold) != 0) {
326 cerr << "Dg2_Init() -- couldn't install FOLD callback with visilib" << endl;
330 if (RegistrationCallback(INVALIDMETRICSRESOURCES, Dg2InvalidMetricsOrResources) != 0) {
331 cerr << "Dg2_Init() -- couldn't install INVALID callback with visilib" << endl;
335 if (RegistrationCallback(PHASENAME, Dg2PhaseNameCallback) != 0) {
336 cerr << "Dg2_Init() -- couldn't install PHASENAME callback with visilib" << endl;
340 if (RegistrationCallback(DATAVALUES, Dg2NewDataCallback) != 0) {
341 cerr << "Dg2_Init() -- couldn't install DATAVALUES callback with visilib" << endl;
345 (void) StartVisi(0, NULL); // presently, the return value is undefined
347 // install "Dg" as a new tcl command; Dg_TclCommand() will be invoked when a script
349 Tcl_CreateCommand(interp, "Dg", Dg_TclCommand,
350 (ClientData *) NULL,(Tcl_CmdDeleteProc *) NULL);