added METRICAVEUNITS, METRICSUMUNITS
[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.13  1996/01/10 21:11:15  tamches
6 /* added METRICAVEUNITS, METRICSUMUNITS
7 /*
8  * Revision 1.12  1995/11/29 00:40:07  tamches
9  * removed myTclEval
10  *
11  * Revision 1.11  1995/11/17 17:39:32  newhall
12  * changed Dg start command, and call to GetMetsRes
13  *
14  * Revision 1.10  1995/11/17  17:32:27  newhall
15  * changed Dg start command to take no arguments, replaced call to MetricUnits
16  * with call to MetricLabel
17  *
18  * Revision 1.9  1995/09/22  19:23:41  tamches
19  * removed warnings under g++ 2.7.0
20  *
21  * Revision 1.8  1995/08/06  22:11:48  tamches
22  * removed some warnings by using myTclEval
23  *
24  * Revision 1.7  1995/02/26  02:01:48  newhall
25  * added callback functions for new visiLib phase info.
26  *
27  * Revision 1.6  1994/11/06  10:24:04  tamches
28  * minor cleanups (especially commenting)
29  *
30  * Revision 1.5  1994/10/11  21:59:47  tamches
31  * Removed extra StartVisi() bug.
32  * Implemented dataGrid[][].Enabled()
33  *
34  * Revision 1.4  1994/10/10  23:08:47  tamches
35  * preliminary changes on the way to swapping the x and y axes
36  *
37  * Revision 1.3  1994/10/10  14:36:18  tamches
38  * fixed some resizing bugs
39  *
40  * Revision 1.2  1994/09/29  20:05:39  tamches
41  * minor cvs fixes
42  *
43  * Revision 1.1  1994/09/29  19:52:25  tamches
44  * initial implementation.
45  * This is a modified version of DGclient.C (tclVisi/src), specially
46  * tuned for the barchart program.
47  *
48 */
49
50 // An updated version of DGClient.C for barchart2.C
51 // Contains several **deletions** to remove blt_barchart influences
52
53 #include <stdlib.h> // exit()
54 #include <iostream.h>
55
56 #include "tcl.h"
57 #include "tk.h"
58 #include "tkTools.h" // myTclEval()
59
60 #include "dg2.h"
61 #include "visi/h/visualization.h"
62 #include "barChartTcl.h"
63 #include "barChart.h"
64
65 void my_visi_callback(void*, int*, long unsigned int*) {
66    if (visi_callback() == -1)
67       exit(0);
68 }
69
70 int Dg2AddMetricsCallback(int) {
71    myTclEval(MainInterp, "DgConfigCallback");
72
73    // if necessary, the tcl program will call xAxisHasChanged and/or
74    // yAxisHasChanged, which are commands we implement in barChart.C.
75    // We take action then.
76
77    return TCL_OK;
78 }
79
80 int Dg2Fold(int) {
81    myTclEval(MainInterp, "DgFoldCallback");
82    return TCL_OK;
83 }
84
85 int Dg2InvalidMetricsOrResources(int) {
86    myTclEval(MainInterp, "DgInvalidCallback");
87    return TCL_OK;
88 }
89
90 int Dg2PhaseNameCallback(int) {
91    myTclEval(MainInterp, "DgPhaseCallback");
92    return TCL_OK;
93 }
94
95 #define   AGGREGATE        0
96 #define   BINWIDTH         1
97 #define   FOLDMETHOD       2
98 #define   METRICNAME       3
99 #define   METRICUNITS      4
100 #define   METRICAVEUNITS   5
101 #define   METRICSUMUNITS   6
102 #define   NUMBINS          7
103 #define   NUMMETRICS       8
104 #define   NUMRESOURCES     9
105 #define   DEFINEPHASE      10
106 #define   RESOURCENAME     11
107 #define   STARTSTREAM      12
108 #define   STOPSTREAM       13
109 #define   DGSUM            14
110 #define   DGVALID          15
111 #define   DGENABLED        16
112 #define   VALUE            17
113 #define   CMDERROR         18
114 #define   LASTBUCKET       19
115 #define   FIRSTBUCKET      20
116
117 struct cmdTabEntry {
118    const char *cmdname;
119    int index;
120    int numargs;
121 };
122
123 static struct cmdTabEntry Dg_Cmds[] = {
124   {"aggregate",    AGGREGATE,       2},
125   {"binwidth",     BINWIDTH,        0},
126   {"firstbucket",  FIRSTBUCKET,     2},
127   {"foldmethod",   FOLDMETHOD,      2},
128   {"lastbucket",   LASTBUCKET,      2},
129   {"metricname",   METRICNAME,      1},
130   {"metricunits",  METRICUNITS,     1},
131   {"metricaveunits", METRICAVEUNITS,1},
132   {"metricsumunits", METRICSUMUNITS,1},
133   {"numbins",      NUMBINS,         0},
134   {"nummetrics",   NUMMETRICS,      0},
135   {"numresources", NUMRESOURCES,    0},
136   {"phase",        DEFINEPHASE,     3},
137   {"resourcename", RESOURCENAME,    1},
138   {"start",        STARTSTREAM,     0},
139   {"stop",         STOPSTREAM,      2},
140   {"sum",          DGSUM,           2},
141   {"valid",        DGVALID,         2},
142   {"enabled",      DGENABLED,       2},
143   {"value",        VALUE,           3},
144   {NULL,           CMDERROR,        0}
145 };
146
147 int findCommand(Tcl_Interp *interp, 
148                        int argc, 
149                        char *argv[]) {
150
151   if (argc == 0) {
152      sprintf(interp->result, "USAGE: Dg <option> [args...]\n");
153      return CMDERROR;
154   }
155
156   for (cmdTabEntry *C = Dg_Cmds; C->cmdname!=NULL; C++) {
157      if (strcmp(argv[0], C->cmdname) == 0) {
158         if (argc-1 == C->numargs) 
159            return C->index; // successful parsing
160
161         sprintf(interp->result, 
162               "%s: wrong number of args (%d). Should be %d\n",
163               argv[0], argc-1, C->numargs);
164         return CMDERROR;
165      }
166   }
167
168   sprintf(interp->result, "unknown option (%s)\n", argv[0]);
169   return CMDERROR;
170 }
171
172 int Dg_TclCommand(ClientData,
173                   Tcl_Interp *interp, 
174                   int argc, char *argv[]) {
175   // entrypoint to the tcl "Dg" command we've installed
176   // all the sprintf()'s are rather slow...
177
178   // parse the arguments, using global vrble Dg_Cmds[] to tell what's what.
179   int cmdDex = findCommand(interp, argc-1, argv+1);
180   if (cmdDex == CMDERROR)
181     return TCL_ERROR;
182
183   int m, r, buck; // metric number, resource number, bucket number
184
185   switch(cmdDex) {
186   case AGGREGATE:   
187     m = atoi(argv[2]);
188     r = atoi(argv[3]);
189     sprintf(interp->result,"%g", dataGrid.AggregateValue(m,r));
190     return TCL_OK;
191
192   case BINWIDTH:     
193     sprintf(interp->result, "%g", dataGrid.BinWidth());
194     return TCL_OK;
195
196   case FIRSTBUCKET:
197     m = atoi(argv[2]);
198     r = atoi(argv[3]);
199     sprintf(interp->result,"%d", dataGrid[m][r].FirstValidBucket()); 
200     return TCL_OK;
201
202   case FOLDMETHOD:
203     m = atoi(argv[2]);
204     sprintf(interp->result,"%d", dataGrid.FoldMethod(m));
205     return TCL_OK;
206
207   case LASTBUCKET:
208     m = atoi(argv[2]);
209     r = atoi(argv[3]);
210     sprintf(interp->result,"%d", dataGrid[m][r].LastBucketFilled());
211     return TCL_OK;
212
213   case METRICNAME:  
214     m = atoi(argv[2]);
215     strcpy(interp->result, dataGrid.MetricName(m));
216     return TCL_OK;
217
218   case METRICUNITS:  
219     m = atoi(argv[2]);
220     strcpy(interp->result, dataGrid.MetricLabel(m));
221     return TCL_OK;
222
223   case METRICAVEUNITS:  
224     m = atoi(argv[2]);
225     strcpy(interp->result, dataGrid.MetricAveLabel(m));
226     return TCL_OK;
227
228   case METRICSUMUNITS:  
229     m = atoi(argv[2]);
230     strcpy(interp->result, dataGrid.MetricSumLabel(m));
231     return TCL_OK;
232
233   case NUMBINS:     
234     sprintf(interp->result, "%d", dataGrid.NumBins());
235     return TCL_OK;
236
237   case NUMMETRICS:  
238     sprintf(interp->result, "%d", dataGrid.NumMetrics());
239     return TCL_OK;
240
241   case NUMRESOURCES:
242     sprintf(interp->result, "%d", dataGrid.NumResources());
243     return TCL_OK;
244
245   case DEFINEPHASE:       
246     DefinePhase(-1.0,NULL);
247     return TCL_OK;
248
249   case RESOURCENAME:
250     r = atoi(argv[2]);
251     strcpy(interp->result, dataGrid.ResourceName(r));
252     return TCL_OK;
253
254   case STARTSTREAM:       
255     GetMetsRes(); 
256     return TCL_OK;
257
258   case STOPSTREAM:
259     m = atoi(argv[2]);
260     r = atoi(argv[3]);
261     StopMetRes(m, r);
262     return TCL_OK;
263
264   case DGSUM:         
265     m = atoi(argv[2]);
266     r = atoi(argv[3]);
267     sprintf(interp->result,"%g", dataGrid.SumValue(m,r));
268     return TCL_OK;
269
270   case DGVALID:
271     m = atoi(argv[2]);
272     r = atoi(argv[3]);
273     sprintf(interp->result, "%d", dataGrid.Valid(m,r));
274     return TCL_OK;
275
276   case DGENABLED:
277     m = atoi(argv[2]);
278     r = atoi(argv[3]);
279     sprintf(interp->result, "%d", dataGrid[m][r].Enabled());
280 //    sprintf(interp->result, "%d", dataGrid.Enabled(m,r));
281     return TCL_OK;
282
283   case VALUE:       
284     m = atoi(argv[2]);
285     r = atoi(argv[3]);
286     buck = atoi(argv[4]);
287     sprintf(interp->result,"%g", dataGrid[m][r].Value(buck));
288     return TCL_OK;
289   }
290
291   sprintf(interp->result, "Internal error (func findCommand)\n");
292   return TCL_ERROR;
293 }
294
295 void (*UsersNewDataCallbackRoutine)(int firstBucket, int lastBucket);
296    // we will call this routine for you when we get a new-data callback
297    // from the visi lib (first, we do a bit of processing for you, such
298    // as determining what the range is buckets you haven't seen yet is).
299
300 int Dg2_Init(Tcl_Interp *interp) {
301    // initialize with the visi lib
302    int fd = VisiInit();
303    if (fd < 0) {
304       cerr << "Dg2_Init() -- could not initialize with the visi lib" << endl;
305       exit(5);
306    }
307
308    // Register C++ Callback routines with the visi lib when
309    // certain events happen.  The most important (performance-wise)
310    // is the DATAVALUES callback, which signals the arrival of
311    // new barchart data.  We must process this callback very quickly,
312    // in order to perturb the system as little as possible.
313
314    if (RegistrationCallback(ADDMETRICSRESOURCES, Dg2AddMetricsCallback) != 0)
315       panic("Dg2_Init() -- couldn't install ADDMETRICSRESOURCES callback");
316
317    if (RegistrationCallback(FOLD, Dg2Fold) != 0)
318       panic("Dg2_Init() -- couldn't install FOLD callback");
319
320    if (RegistrationCallback(INVALIDMETRICSRESOURCES, Dg2InvalidMetricsOrResources) != 0)
321       panic("Dg2_Init() -- couldn't install INVALID callback");
322
323    if (RegistrationCallback(PHASESTART, Dg2PhaseNameCallback) != 0)
324       panic("Dg2_Init() -- couldn't install PHASENAME callback");
325
326    if (RegistrationCallback(DATAVALUES, Dg2NewDataCallback) != 0)
327       panic("Dg2_Init() -- couldn't install DATAVALUES callback");
328
329    // install "Dg" as a new tcl command; Dg_TclCommand() will be invoked when
330    // a tcl script calls Dg
331    Tcl_CreateCommand(interp, "Dg", Dg_TclCommand, 
332                     (ClientData *) NULL,(Tcl_CmdDeleteProc *) NULL);
333  
334    // Arrange for my_visi_callback() to be called whenever data is waiting
335    // to be read off of descriptor "fd".  Extremely important! [tcl book
336    // page 357]
337    Tk_CreateFileHandler(fd, TK_READABLE, (Tk_FileProc *) my_visi_callback, 0);
338
339    return TCL_OK;
340 }