2 // customized (for barchart) version of DGclient.C in tclVisi directory
5 // Revision 1.1 1994/09/29 19:52:25 tamches
6 // initial implementation.
7 // This is a modified version of DGclient.C (tclVisi/src), specially
8 // tuned for the barchart program.
11 // An updated version of DGClient.C for barchart2.C
12 // Contains several **deletions** to remove blt_barchart influences
14 #include <stdlib.h> // exit()
19 #include "visi/h/visualization.h"
20 #include "barChartTcl.h"
23 void my_visi_callback(void* arg0, int* arg1, long unsigned int* arg2) {
24 if (visi_callback() == -1)
28 int Dg2AddMetricsCallback(int dummy) {
29 int retval = Tcl_Eval(MainInterp, "DgConfigCallback");
30 if (retval == TCL_ERROR)
31 fprintf(stderr, "%s\n", MainInterp->result);
33 // if necessary, the tcl program will call xAxisHasChanged and/or yAxisHasChanged, which
34 // are commands we implement in barChart.C.
35 // We take action then.
40 //int Dg2NewDataCallbackGeneral(int dummy) {
41 // // A fairly general new-data handler; is smart enough to
42 // // know when and if a **range** of values needs to be redrawn
43 // // (perhaps because we've fallen behind?) as opposed to just
44 // // the latest value --- the histogram would need this, for
45 // // example (to avoid gaps), but the barchart can always just use
46 // // the most recent value and not care if it's fallen behind...
48 // // A more specific one is actually in use at the moment; it
49 // // is Dg2NewDataCallback(). I haven't deleted the source code for
50 // // this guy since it's potentially useful for visis other than
53 // // I have, however, removed the "DgValidCallback" from the original
56 // static LastBucket = 0; // this very important STATIC variable keeps
57 // // track of the last bucket number we've processed.
58 // // We'll be sending a data-callback on range
59 // // LastBucket+1 thru what we see as the latest bucket
60 // // which has been filled with data. Presumably, if
61 // // we keep up, this'll always be the range
62 // // (LastBucket+1, LastBucket+1).
64 // // set "thislast" to dataGrid[m][r].LastBucketFilled() for the first
65 // // datagrid element we find with the Valid bit set to true...
66 // int thislast = findMostRecentBucket();
68 // // There are no more "DgValidCallback" calls, since barchart never
69 // // seemed to use them in the first place...
71 // if (thislast < LastBucket)
72 // LastBucket = thislast-1; // will rarely if ever happen; just to avoid sending
73 // // an empty range...
75 // if (thislast >= 0) {
76 // // send a data-callback on range (LastBucket+1, thislast)
77 // // This is where the previous version of Dg would invoke
78 // // the tcl script DgDataCallback. Now that we're C++, we don't
81 // UsersNewDataCallbackRoutine(LastBucket+1, thislast);
83 // LastBucket = thislast;
89 int Dg2Fold(int dummy) {
90 int retval = Tcl_Eval(MainInterp, "DgFoldCallback");
91 if (retval == TCL_ERROR)
92 fprintf(stderr, "%s\n", MainInterp->result);
97 int Dg2InvalidMetricsOrResources(int dummy) {
98 int retval = Tcl_Eval(MainInterp, "DgInvalidCallback");
99 if (retval == TCL_ERROR)
100 fprintf(stderr, "%s\n", MainInterp->result);
105 int Dg2PhaseNameCallback(int dummy) {
106 int retval = Tcl_Eval(MainInterp, "DgPhaseCallback");
107 if (retval == TCL_ERROR)
108 fprintf(stderr, "%s\n", MainInterp->result);
117 #define METRICUNITS 4
120 #define NUMRESOURCES 7
121 #define DEFINEPHASE 8
122 #define RESOURCENAME 9
123 #define STARTSTREAM 10
124 #define STOPSTREAM 11
129 #define LASTBUCKET 16
130 #define FIRSTBUCKET 18
139 static struct cmdTabEntry Dg_Cmds[] = {
140 {"aggregate", AGGREGATE, 2},
141 {"binwidth", BINWIDTH, 0},
142 {"firstbucket", FIRSTBUCKET, 2},
143 {"foldmethod", FOLDMETHOD, 2},
144 {"lastbucket", LASTBUCKET, 2},
145 {"metricname", METRICNAME, 1},
146 {"metricunits", METRICUNITS, 1},
147 {"numbins", NUMBINS, 0},
148 {"nummetrics", NUMMETRICS, 0},
149 {"numresources", NUMRESOURCES, 0},
150 {"phase", DEFINEPHASE, 3},
151 {"resourcename", RESOURCENAME, 1},
152 {"start", STARTSTREAM, 2},
153 {"stop", STOPSTREAM, 2},
155 {"valid", DGVALID, 2},
160 int findCommand(Tcl_Interp *interp,
165 sprintf(interp->result, "USAGE: Dg <option> [args...]\n");
169 for (cmdTabEntry *C = Dg_Cmds; C->cmdname!=NULL; C++) {
170 if (strcmp(argv[0], C->cmdname) == 0) {
171 if (argc-1 == C->numargs)
172 return C->index; // successful parsing
174 sprintf(interp->result,
175 "%s: wrong number of args (%d). Should be %d\n",
176 argv[0], argc-1, C->numargs);
181 sprintf(interp->result, "unknown option (%s)\n", argv[0]);
185 int Dg_TclCommand(ClientData clientData,
189 // entrypoint to the tcl "Dg" command we've installed
190 // all the sprintf()'s are rather slow...
192 // parse the arguments, using the global variable Dg_Cmds[] to tell what's what.
193 int cmdDex = findCommand(interp, argc-1, argv+1);
194 if (cmdDex == CMDERROR)
197 int m, r, buck; // metric number, resource number, bucket number
203 sprintf(interp->result,"%g", dataGrid.AggregateValue(m,r));
207 sprintf(interp->result, "%g", dataGrid.BinWidth());
213 sprintf(interp->result,"%d", dataGrid[m][r].FirstValidBucket());
218 sprintf(interp->result,"%d", dataGrid.FoldMethod(m));
224 sprintf(interp->result,"%d", dataGrid[m][r].LastBucketFilled());
229 sprintf(interp->result, "%s", dataGrid.MetricName(m));
234 sprintf(interp->result, "%s", dataGrid.MetricUnits(m));
238 sprintf(interp->result, "%d", dataGrid.NumBins());
242 sprintf(interp->result, "%d", dataGrid.NumMetrics());
246 sprintf(interp->result, "%d", dataGrid.NumResources());
250 NamePhase(atof(argv[2]), atof(argv[3]), argv[4]);
255 sprintf(interp->result, "%s", dataGrid.ResourceName(r));
259 GetMetsRes(argv[2], argv[3], 0);
271 sprintf(interp->result,"%g", dataGrid.SumValue(m,r));
277 sprintf(interp->result, "%d", dataGrid.Valid(m,r));
283 buck = atoi(argv[4]);
284 sprintf(interp->result,"%g", dataGrid[m][r].Value(buck));
288 sprintf(interp->result, "Internal error (func findCommand)\n");
292 void (*UsersNewDataCallbackRoutine)(int firstBucket, int lastBucket);
293 // we will call this routine for you when we get a new-data callback
294 // from the visi lib (first, we do a bit of processing for you, such
295 // as determining what the range is buckets you haven't seen yet is).
297 //int Dg2_Init(Tcl_Interp *interp, void (*userDataCallbackRoutine)(int, int)) {
298 int Dg2_Init(Tcl_Interp *interp) {
299 // initialize with the visi lib
302 cerr << "Dg2_Init() -- could not initialize with the visi lib" << endl;
306 // Arrange for my_visi_callback() to be called whenever there is data waiting
307 // to be read off of descriptor "fd". Extremely important! [tcl book page 357]
308 Tk_CreateFileHandler(fd, TK_READABLE, (Tk_FileProc *) my_visi_callback, 0);
310 // Register C++ Callback routines with the visi lib when
311 // certain events happen. The most important (performance-wise)
312 // is the DATAVALUES callback, which signals the arrival of
313 // new barchart data. We must process this callback very quickly,
314 // in order to perturb the system as little as possible.
316 if (RegistrationCallback(ADDMETRICSRESOURCES, Dg2AddMetricsCallback) != 0) {
317 cerr << "Dg2_Init() -- couldn't install ADDMETRICSRESOURCES callback with visilib" << endl;
321 if (RegistrationCallback(FOLD, Dg2Fold) != 0) {
322 cerr << "Dg2_Init() -- couldn't install FOLD callback with visilib" << endl;
326 if (RegistrationCallback(INVALIDMETRICSRESOURCES, Dg2InvalidMetricsOrResources) != 0) {
327 cerr << "Dg2_Init() -- couldn't install INVALID callback with visilib" << endl;
331 if (RegistrationCallback(PHASENAME, Dg2PhaseNameCallback) != 0) {
332 cerr << "Dg2_Init() -- couldn't install PHASENAME callback with visilib" << endl;
336 if (RegistrationCallback(DATAVALUES, Dg2NewDataCallback) != 0) {
337 cerr << "Dg2_Init() -- couldn't install DATAVALUES callback with visilib" << endl;
341 (void) StartVisi(0, NULL); // presently, the return value is undefined
343 // install "Dg" as a new tcl command; Dg_TclCommand() will be invoked when a script
345 Tcl_CreateCommand(interp, "Dg", Dg_TclCommand,
346 (ClientData *) NULL,(Tcl_CmdDeleteProc *) NULL);