minor cvs fixes
[dyninst.git] / visiClients / barchart / dg2.C
1 // dg2.C
2 // customized (for barchart) version of DGclient.C in tclVisi directory
3
4 /* $Log: dg2.C,v $
5 /* Revision 1.2  1994/09/29 20:05:39  tamches
6 /* minor cvs fixes
7 /*
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.
12  *
13 */
14
15 // An updated version of DGClient.C for barchart2.C
16 // Contains several **deletions** to remove blt_barchart influences
17
18 #include <stdlib.h> // exit()
19 #include <iostream.h>
20 #include <tcl.h>
21 #include <tk.h>
22 #include "dg2.h"
23 #include "visi/h/visualization.h"
24 #include "barChartTcl.h"
25 #include "barChart.h"
26
27 void my_visi_callback(void* arg0, int* arg1, long unsigned int* arg2) {
28     if (visi_callback() == -1)
29        exit(0);
30 }
31
32 int Dg2AddMetricsCallback(int dummy) {
33   int retval = Tcl_Eval(MainInterp, "DgConfigCallback");
34   if (retval == TCL_ERROR)
35      fprintf(stderr, "%s\n", MainInterp->result);
36
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.
40
41   return(retval);
42 }
43
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...
51 //
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
55 //   // the barchart.
56 //
57 //   // I have, however, removed the "DgValidCallback" from the original
58 //   // DGclient.C
59 //
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).
67 //
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();
71 //
72 //   // There are no more "DgValidCallback" calls, since barchart never
73 //   // seemed to use them in the first place...
74 //
75 //   if (thislast < LastBucket)
76 //      LastBucket = thislast-1; // will rarely if ever happen; just to avoid sending
77 //                               // an empty range...
78 //
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
83 //      // do that.
84 //
85 //      UsersNewDataCallbackRoutine(LastBucket+1, thislast);
86 //
87 //      LastBucket = thislast;
88 //   }
89 //
90 //   return TCL_OK;
91 //}
92
93 int Dg2Fold(int dummy) {
94   int retval = Tcl_Eval(MainInterp, "DgFoldCallback");
95   if (retval == TCL_ERROR)
96     fprintf(stderr, "%s\n", MainInterp->result);
97
98   return(retval);
99 }
100
101 int Dg2InvalidMetricsOrResources(int dummy) {
102   int retval = Tcl_Eval(MainInterp, "DgInvalidCallback");
103   if (retval == TCL_ERROR)
104     fprintf(stderr, "%s\n", MainInterp->result);
105
106   return(retval);
107 }
108
109 int Dg2PhaseNameCallback(int dummy) {
110   int retval = Tcl_Eval(MainInterp, "DgPhaseCallback");
111   if (retval == TCL_ERROR)
112     fprintf(stderr, "%s\n", MainInterp->result);
113
114   return(retval);
115 }
116
117 #define   AGGREGATE        0
118 #define   BINWIDTH         1
119 #define   FOLDMETHOD       2
120 #define   METRICNAME       3
121 #define   METRICUNITS      4
122 #define   NUMBINS          5
123 #define   NUMMETRICS       6
124 #define   NUMRESOURCES     7
125 #define   DEFINEPHASE      8
126 #define   RESOURCENAME     9
127 #define   STARTSTREAM      10
128 #define   STOPSTREAM       11
129 #define   DGSUM            12
130 #define   DGVALID          13
131 #define   VALUE            14
132 #define   CMDERROR         15
133 #define   LASTBUCKET       16
134 #define   FIRSTBUCKET      18
135
136 struct cmdTabEntry 
137 {
138   char *cmdname;
139   int index;
140   int numargs;
141 };
142
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},
158   {"sum",          DGSUM,           2},
159   {"valid",        DGVALID,         2},
160   {"value",        VALUE,           3},
161   {NULL,           CMDERROR,        0}
162 };
163
164 int findCommand(Tcl_Interp *interp, 
165                        int argc, 
166                        char *argv[]) {
167
168   if (argc == 0) {
169      sprintf(interp->result, "USAGE: Dg <option> [args...]\n");
170      return CMDERROR;
171   }
172
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
177
178         sprintf(interp->result, 
179               "%s: wrong number of args (%d). Should be %d\n",
180               argv[0], argc-1, C->numargs);
181         return CMDERROR;
182      }
183   }
184
185   sprintf(interp->result, "unknown option (%s)\n", argv[0]);
186   return CMDERROR;
187 }
188
189 int Dg_TclCommand(ClientData clientData,
190                Tcl_Interp *interp, 
191                int argc, 
192                char *argv[]) {
193   // entrypoint to the tcl "Dg" command we've installed
194   // all the sprintf()'s are rather slow...
195
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)
199     return TCL_ERROR;
200
201   int m, r, buck; // metric number, resource number, bucket number
202
203   switch(cmdDex) {
204   case AGGREGATE:   
205     m = atoi(argv[2]);
206     r = atoi(argv[3]);
207     sprintf(interp->result,"%g", dataGrid.AggregateValue(m,r));
208     return TCL_OK;
209
210   case BINWIDTH:     
211     sprintf(interp->result, "%g", dataGrid.BinWidth());
212     return TCL_OK;
213
214   case FIRSTBUCKET:
215     m = atoi(argv[2]);
216     r = atoi(argv[3]);
217     sprintf(interp->result,"%d", dataGrid[m][r].FirstValidBucket()); 
218     return TCL_OK;
219
220   case FOLDMETHOD:
221     m = atoi(argv[2]);
222     sprintf(interp->result,"%d", dataGrid.FoldMethod(m));
223     return TCL_OK;
224
225   case LASTBUCKET:
226     m = atoi(argv[2]);
227     r = atoi(argv[3]);
228     sprintf(interp->result,"%d", dataGrid[m][r].LastBucketFilled());
229     return TCL_OK;
230
231   case METRICNAME:  
232     m = atoi(argv[2]);
233     sprintf(interp->result, "%s", dataGrid.MetricName(m));
234     return TCL_OK;
235
236   case METRICUNITS:  
237     m = atoi(argv[2]);
238     sprintf(interp->result, "%s", dataGrid.MetricUnits(m));
239     return TCL_OK;
240
241   case NUMBINS:     
242     sprintf(interp->result, "%d", dataGrid.NumBins());
243     return TCL_OK;
244
245   case NUMMETRICS:  
246     sprintf(interp->result, "%d", dataGrid.NumMetrics());
247     return TCL_OK;
248
249   case NUMRESOURCES:
250     sprintf(interp->result, "%d", dataGrid.NumResources());
251     return TCL_OK;
252
253   case DEFINEPHASE:       
254     NamePhase(atof(argv[2]), atof(argv[3]), argv[4]);
255     return TCL_OK;
256
257   case RESOURCENAME:
258     r = atoi(argv[2]);
259     sprintf(interp->result, "%s", dataGrid.ResourceName(r));
260     return TCL_OK;
261
262   case STARTSTREAM:       
263     GetMetsRes(argv[2], argv[3], 0);
264     return TCL_OK;
265
266   case STOPSTREAM:
267     m = atoi(argv[2]);
268     r = atoi(argv[3]);
269     StopMetRes(m, r);
270     return TCL_OK;
271
272   case DGSUM:         
273     m = atoi(argv[2]);
274     r = atoi(argv[3]);
275     sprintf(interp->result,"%g", dataGrid.SumValue(m,r));
276     return TCL_OK;
277
278   case DGVALID:
279     m = atoi(argv[2]);
280     r = atoi(argv[3]);
281     sprintf(interp->result, "%d", dataGrid.Valid(m,r));
282     return TCL_OK;
283
284   case VALUE:       
285     m = atoi(argv[2]);
286     r = atoi(argv[3]);
287     buck = atoi(argv[4]);
288     sprintf(interp->result,"%g", dataGrid[m][r].Value(buck));
289     return TCL_OK;
290   }
291
292   sprintf(interp->result, "Internal error (func findCommand)\n");
293   return TCL_ERROR;
294 }
295
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).
300
301 //int Dg2_Init(Tcl_Interp *interp, void (*userDataCallbackRoutine)(int, int)) {
302 int Dg2_Init(Tcl_Interp *interp) {
303    // initialize with the visi lib
304    int fd = VisiInit();
305    if (fd < 0) {
306       cerr << "Dg2_Init() -- could not initialize with the visi lib" << endl;
307       exit(5);
308    }
309
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);
313
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.
319
320    if (RegistrationCallback(ADDMETRICSRESOURCES, Dg2AddMetricsCallback) != 0) {
321       cerr << "Dg2_Init() -- couldn't install ADDMETRICSRESOURCES callback with visilib" << endl;
322       exit(5);
323    }
324
325    if (RegistrationCallback(FOLD, Dg2Fold) != 0) {
326       cerr << "Dg2_Init() -- couldn't install FOLD callback with visilib" << endl;
327       exit(5);
328    }
329
330    if (RegistrationCallback(INVALIDMETRICSRESOURCES, Dg2InvalidMetricsOrResources) != 0) {
331       cerr << "Dg2_Init() -- couldn't install INVALID callback with visilib" << endl;
332       exit(5);
333    }
334
335    if (RegistrationCallback(PHASENAME, Dg2PhaseNameCallback) != 0) {
336       cerr << "Dg2_Init() -- couldn't install PHASENAME callback with visilib" << endl;
337       exit(5);
338    }
339
340    if (RegistrationCallback(DATAVALUES, Dg2NewDataCallback) != 0) {
341       cerr << "Dg2_Init() -- couldn't install DATAVALUES callback with visilib" << endl;
342       exit(5);
343    }
344
345    (void) StartVisi(0, NULL); // presently, the return value is undefined
346
347    // install "Dg" as a new tcl command; Dg_TclCommand() will be invoked when a script
348    // calls Dg.
349    Tcl_CreateCommand(interp, "Dg", Dg_TclCommand, 
350                     (ClientData *) NULL,(Tcl_CmdDeleteProc *) NULL);
351  
352    return TCL_OK;
353 }