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