memory leak fixes
[dyninst.git] / visi / src / visualization.C
1 /*
2  * Copyright (c) 1993, 1994 Barton P. Miller, Jeff Hollingsworth,
3  *     Bruce Irvin, Jon Cargille, Krishna Kunchithapadam, Karen
4  *     Karavanic, Tia Newhall, Mark Callaghan.  All rights reserved.
5  * 
6  * This software is furnished under the condition that it may not be
7  * provided or otherwise made available to, or used by, any other
8  * person, except as provided for by the terms of applicable license
9  * agreements.  No title to or ownership of the software is hereby
10  * transferred.  The name of the principals may not be used in any
11  * advertising or publicity related to this software without specific,
12  * written prior authorization.  Any use of this software must include
13  * the above copyright notice.
14  *
15  */
16 /* $Log: visualization.C,v $
17 /* Revision 1.20  1994/11/02 04:15:00  newhall
18 /* memory leak fixes
19 /*
20  * Revision 1.19  1994/10/13  15:39:17  newhall
21  * QuitVisi added
22  *
23  * Revision 1.18  1994/09/30  21:00:51  newhall
24  * use datagrid method functions MetricId and ResourceId
25  *
26  * Revision 1.17  1994/09/25  02:00:29  newhall
27  * changes to visi interface routines that take list of met/focus pairs:
28  * AddMetricsResources, GetMetRes
29  * and changes to support the new version of igen
30  *
31  * Revision 1.16  1994/09/22  03:14:41  markc
32  * declared arrays at start
33  * incremented version number
34  *
35  * Added stronger compiler warnings
36  * removed compiler warnings
37  *
38  * Revision 1.15  1994/08/13  20:34:50  newhall
39  * removed all code associated with class visi_MRList
40  * removed mrlist src and obj
41  * removed
42  *
43  * Revision 1.14  1994/08/11  02:52:11  newhall
44  * removed calls to grid cell Deleted member functions
45  *
46  * Revision 1.13  1994/08/03  20:49:12  newhall
47  * removed code for interface routines NewMetricsResources and Enabled
48  * changed AddMetricsResources to set grid cell's enabled flag
49  *
50  * Revision 1.12  1994/07/30  03:27:27  newhall
51  * added visi interface functions Enabled and BulkDataTransfer
52  *
53  * Revision 1.11  1994/07/20  22:41:11  rbi
54  * Small arguments fix to make identification of wildcards easier.
55  *
56  * Revision 1.10  1994/07/07  22:40:31  newhall
57  * fixed compile warnings
58  *
59  * Revision 1.9  1994/06/16  18:24:53  newhall
60  * fix to visualization::Data
61  *
62  * Revision 1.8  1994/06/07  17:48:49  newhall
63  * support for adding metrics and resources to existing visualization
64  *
65  * Revision 1.7  1994/05/23  20:56:48  newhall
66  * To visi_GridCellHisto class: added deleted flag, SumValue
67  * method function, and fixed AggregateValue method function
68  *
69  * Revision 1.6  1994/05/11  17:13:14  newhall
70  * changed data type from double to float
71  *
72  * Revision 1.5  1994/04/13  21:34:54  newhall
73  * added routines: GetMetsRes StopMetRes NamePhase
74  *
75  * Revision 1.4  1994/03/26  04:19:49  newhall
76  * changed all floats to double
77  * fix problem with null string returned for first resource name
78  *
79  * Revision 1.3  1994/03/17  05:23:09  newhall
80  * changed eventCallbacks type, and the constraints on triggering the
81  * callback routine associated with the DATAVALUES event
82  *
83  * Revision 1.2  1994/03/14  20:28:55  newhall
84  * changed visi subdirectory structure
85  *  */ 
86 #include "visi/h/visualization.h"
87 #include "visi.SRVR.h"
88
89 visi_DataGrid  dataGrid;
90 int            LastBucketSent = -1;
91 int fileDesc[FILETABLESIZE];
92 int (*fileDescCallbacks[FILETABLESIZE])();
93 int (*eventCallbacks[EVENTSIZE])(int);
94 int initDone = 0;
95
96 visualization *vp;
97 int visi_callback(){
98   return(vp->mainLoop());
99 }
100
101 ///////////////////////////////////////////////////////////
102 // paradyn initialization routine connects to parent socket,
103 // and registers the visualization::mainLoop routine as 
104 // callback on events on fileDesc[0]
105 ///////////////////////////////////////////////////////////
106 int VisiInit(){
107
108 int i;
109
110   for(i=0;i<FILETABLESIZE;i++){
111     fileDescCallbacks[i] = NULL;
112     fileDesc[i] = -1;
113   }
114   for(i=0;i<EVENTSIZE;i++){
115     eventCallbacks[i] = NULL;
116   }
117
118   vp = new visualization(0, NULL, NULL);
119   fileDesc[0] = 0;
120   fileDescCallbacks[0] = visi_callback;
121   initDone = 1;
122
123   return(fileDesc[0]);
124 }
125
126 ///////////////////////////////////////////////////////////
127 // makes initial call to get Metrics and Resources 
128 // for visualizations that do not provide an event that 
129 // invokes the GetMetsRes upcall, this routine should be
130 // called by the visiualizaiton before entering the mainloop
131 ///////////////////////////////////////////////////////////
132 int StartVisi(int argc,
133               char *argv[]){
134
135   if(!initDone)
136     VisiInit();
137
138   // call GetMetricResources with initial metric resource lists
139   if(argc == 3)
140    vp->GetMetricResource(argv[1],(int)argv[2],0);
141   else
142    vp->GetMetricResource(NULL,0,0);
143   return(OK);
144
145 }
146
147 ///////////////////////////////////////////////////////////
148 // cleans up visi interface data structs 
149 // Visualizations should call this routine before exiting 
150 ///////////////////////////////////////////////////////////
151 void QuitVisi(){
152
153     delete vp;
154
155 }
156
157
158
159
160 ///////////////////////////////////////////////////////////
161 // registration callback routine for paradyn events
162 // sets eventCallbacks[event] to callback routine provided by user
163 ///////////////////////////////////////////////////////////
164 int RegistrationCallback(msgTag event,
165                          int (*callBack)(int)){
166
167   if((event < EVENTSIZE)){
168     eventCallbacks[event] = callBack;
169     return(OK);
170   }
171   else{
172     visi_ErrorHandler(ERROR_SUBSCRIPT,"error in RegistrationCallback");
173     return(ERROR_SUBSCRIPT);
174   }
175 }
176
177 ///////////////////////////////////////////////////////////
178 // fd registration and callback routine registration for user
179 // to register callback routines when they use the provided main routine
180 ///////////////////////////////////////////////////////////
181 int RegFileDescriptors(int *fd, int (*callBack)()){
182   return(OK);
183 }
184
185 ///////////////////////////////////////////////////////////
186 // invokes upcall to paradyn VISIthread associated with the visualization
187 // takes list of current metrics, list of foci, and type of data
188 // (0 for histogram, 1 for scalar). 
189 // currently, only the NULL string, type 0 case is supported 
190 ///////////////////////////////////////////////////////////
191 void GetMetsRes(char *metres,
192                 int numElements,
193                 int type){
194
195   if(!initDone)
196     VisiInit();
197   vp->GetMetricResource(metres,numElements,0);
198 }
199
200 ///////////////////////////////////////////////////////////
201 // invokes upcall to paradyn.  Request to stop data for the 
202 // metric associated with metricIndex and resource associated with
203 // resourceIndex
204 ///////////////////////////////////////////////////////////
205 void StopMetRes(int metricIndex,
206                 int resourceIndex){
207
208   if(!initDone)
209     VisiInit();
210   if((metricIndex < dataGrid.NumMetrics()) 
211       && (metricIndex >= 0)
212       && (resourceIndex >= 0)
213       && (resourceIndex <dataGrid.NumResources())){
214     dataGrid[metricIndex][resourceIndex].ClearEnabled();
215     dataGrid[metricIndex][resourceIndex].Invalidate();
216     vp->StopMetricResource(dataGrid.MetricId(metricIndex),
217                            dataGrid.ResourceId(resourceIndex));
218   }
219 }
220
221 ///////////////////////////////////////////////////////////
222 // invokes upcall to paradyn.  Visualization sends phase
223 // definition to paradyn.  
224 ///////////////////////////////////////////////////////////
225 void NamePhase(timeType begin,
226                timeType end,
227                char *name){
228
229   if(!initDone)
230     VisiInit();
231   vp->PhaseName((double)begin,(double)end,name);
232 }
233
234 ///////////////////////////////////////////////////////////
235 //  Visi interface routine.  Receives an array of data 
236 //  values from paradyn, adds them to the datagrid, and
237 //  invokes the callback routine associated with the
238 //  DATAVALUES event.
239 ///////////////////////////////////////////////////////////
240 void visualization::Data(dataValue_Array data){
241
242 int noMetrics, noResources;
243 int i,j,metric,ok;
244 int temp,min,max;
245
246
247   if(!initDone)
248     VisiInit();
249
250   noMetrics = dataGrid.NumMetrics();
251   noResources = dataGrid.NumResources();
252
253
254   for(i=0; i < data.count; i++){
255
256       // get metric and resource index into dataGrid and add value if found
257       metric = dataGrid.MetricIndex(data.data[i].metricId);
258       j = dataGrid.ResourceIndex(data.data[i].resourceId);
259
260       if((j >= 0) && (metric >= 0)){
261
262          dataGrid.AddValue(metric,j,
263                          data.data[i].bucketNum,
264                          (float)data.data[i].data);
265       }
266   } 
267
268   min = max = dataGrid.NumBins()+1;
269   for(i=0; i < noMetrics; i++){
270       for(j=0; j < noResources; j++){
271           if(dataGrid.Valid(i,j)){
272               temp = dataGrid.LastBucketFilled(i,j);  
273               if((temp > -1) && (temp < min))
274               min = temp; 
275           }
276       }
277   }
278
279   //call user registered callback routine assoc. w/event DATAVALUES
280   if((min > LastBucketSent) // if a new datagrid cross-section has been filled
281      && (min != max)
282      && (eventCallbacks[DATAVALUES] !=  NULL)){ // there is a callback routine 
283
284        LastBucketSent = min;
285        ok = eventCallbacks[DATAVALUES](LastBucketSent);
286   }
287 }
288
289
290 ///////////////////////////////////////////////////////////
291 //  Visi interface routine.  Receives notification of a
292 //  fold event, and the new bucket width.  Invokes
293 //  a fold operation on the datagrid
294 ///////////////////////////////////////////////////////////
295 void visualization::Fold(double newBucketWidth){
296   
297   int ok;
298
299   if(!initDone)
300     VisiInit();
301
302   dataGrid.Fold(newBucketWidth);
303   // assume a fold can only occur when datagrid histogram buckets are full
304   LastBucketSent = (dataGrid.NumBins()/2) - 1;
305
306   //call user registered callback routine assoc. w/event FOLD
307   if(eventCallbacks[FOLD] !=  NULL){
308      ok = eventCallbacks[FOLD](0);
309   }
310 }
311
312 ///////////////////////////////////////////////////////////
313 // Visi interface routine.  Receives notification of an
314 // invalid metric/resource pair.  Invalidataes the datagrid
315 // cell associated with the metricId m and resourceId r.
316 ///////////////////////////////////////////////////////////
317 void visualization::InvalidMR(int m, int r){
318
319 int i,j;
320 int ok;
321
322   if(!initDone)
323     VisiInit();
324
325   // search for indices associated with metricId m and
326   // resourceId r
327   for(i=0;
328      (i<dataGrid.NumMetrics())
329      &&(m!=dataGrid.MetricId(i)); i++) ;
330   for(j=0;
331       (j<dataGrid.NumResources())
332       &&(r!=dataGrid.ResourceId(j)); j++) ;
333
334   dataGrid[i][j].ClearEnabled();
335   ok = dataGrid.Invalidate(i,j);
336
337   //call callback routine assoc. w/event INVALIDMETRICSRESOURCES 
338   if(eventCallbacks[INVALIDMETRICSRESOURCES] != NULL){
339      ok = eventCallbacks[INVALIDMETRICSRESOURCES](0);
340   }
341 }
342
343 ///////////////////////////////////////////////////////////
344 // Visi interface routine.  Receives a list of metrics and
345 // resources to add to the datagrid.
346 ///////////////////////////////////////////////////////////
347 void visualization::AddMetricsResources(visi_matrix_Array newElements,
348                                         double bucketWidth,
349                                         int nobuckets){
350
351   int ok,i,j,k;
352   visi_metricType *mets = 0;
353   visi_resourceType *res = 0;
354   int numRes, numMet;
355
356   if(!initDone)
357     VisiInit();
358
359   // this is first set of metrics/resources, construct new dataGrid
360   if(!dataGrid.NumMetrics()){
361     // create list of all unique metric and resource entries
362     // in newElements
363     numRes = 0;
364     numMet = 0;
365     if((res=(visi_resourceType *)malloc(sizeof(visi_resourceType)*
366                                     newElements.count)) == NULL){
367         return;
368     }                              
369     if((mets=(visi_metricType *)malloc(sizeof(visi_metricType)*
370                                     newElements.count)) == NULL){
371         return;
372     }                              
373     for(i = 0; i < newElements.count; i++){
374         ok = 0;
375         for(j=0; (j < numMet) && (!ok);j++){
376            if(newElements.data[i].met.Id == mets[j].Id)
377              ok = 1;
378         }
379         if(!ok){
380             if(!newElements.data[i].met.name)
381                 mets[numMet].name = NULL;
382             else
383                 mets[numMet].name = strdup(newElements.data[i].met.name);
384             if(!newElements.data[i].met.units)
385                 mets[numMet].units = NULL;
386             else
387                 mets[numMet].units = strdup(newElements.data[i].met.units);
388             mets[numMet].Id = newElements.data[i].met.Id;
389             mets[numMet++].aggregate = newElements.data[i].met.aggregate;
390         }
391           ok = 0;
392         for(j=0; (j < numRes) && (!ok);j++){
393            if(newElements.data[i].res.Id == res[j].Id)
394              ok = 1;
395         }
396         if(!ok){
397             if(!newElements.data[i].res.name)
398                 res[numRes].name = NULL;
399             else
400                 res[numRes].name = strdup(newElements.data[i].res.name);
401             res[numRes++].Id = newElements.data[i].res.Id;
402         }
403     }
404
405     // construct new dataGrid 
406     dataGrid.visi_DataGrid(numMet,
407                            numRes,
408                            mets,
409                            res,
410                            nobuckets,
411                            (timeType)bucketWidth);
412   }
413   else{ // add elements to existing data grid
414
415     // create list of new resources and add them to resource list
416     res=(visi_resourceType *)malloc(sizeof(visi_resourceType)
417                                     *newElements.count);
418     numRes = 0;
419     for(i=0; i < newElements.count; i++){
420       if(!dataGrid.ResourceInGrid(newElements.data[i].res.Id)){
421           ok = 0;
422           for(k=0; (k < numRes) && !ok; k++){
423              if(newElements.data[i].res.Id == res[k].Id)
424                ok = 1;
425           }
426           if(!ok){
427               if(!newElements.data[i].res.name)
428                 res[numRes].name = NULL;
429               else
430                 res[numRes].name = strdup(newElements.data[i].res.name);
431               res[numRes++].Id = newElements.data[i].res.Id;
432           }
433       }
434     }
435
436     // add new resources to dataGrid
437     if(numRes > 0)
438       dataGrid.AddNewResource(numRes,res);
439
440     // create list of new metrics and add them to metricsList
441     mets = (visi_metricType *)malloc(sizeof(visi_metricType)*
442             newElements.count);
443     numMet = 0;
444     for(i=0; i < newElements.count; i++){
445       if(!dataGrid.MetricInGrid(newElements.data[i].met.Id)){
446
447           ok = 0;
448           for(k=0; (k < numMet) && !ok; k++){
449              if(newElements.data[i].met.Id == mets[k].Id)
450                ok = 1;
451           }
452           if(!ok){
453               if(!newElements.data[i].met.name)
454                   mets[numMet].name = NULL;
455               else
456                   mets[numMet].name = strdup(newElements.data[i].met.name);
457               if(!newElements.data[i].met.units)
458                   mets[numMet].units = NULL;
459               else
460                   mets[numMet].units = strdup(newElements.data[i].met.units);
461             mets[numMet].Id = newElements.data[i].met.Id;
462             mets[numMet++].aggregate = newElements.data[i].met.aggregate;
463         }
464       }
465     }
466
467
468     // add new metrics to dataGrid
469     if(numMet > 0)
470       dataGrid.AddNewMetrics(numMet,mets);
471   }
472
473   // set enabled for every element of newElements list 
474   for(k = 0; k < newElements.count; k++){
475      dataGrid[dataGrid.MetricIndex(newElements.data[k].met.Id)][dataGrid.ResourceIndex(newElements.data[k].res.Id)].SetEnabled();
476   }
477  
478   for(i=0; i < numRes; i++){
479      if(res[i].name) free(res[i].name);
480   }
481   for(i=0; i < numMet; i++){
482      if(mets[i].units) free(mets[i].units);
483      if(mets[i].name) free(mets[i].name);
484   }
485   free(mets);
486   free(res);
487   //call callback routine assoc. w/event ADDMETRICSRESOURCES 
488   if(eventCallbacks[ADDMETRICSRESOURCES] !=  NULL){
489      ok = eventCallbacks[ADDMETRICSRESOURCES](0);
490   }
491 }
492
493 ///////////////////////////////////////////////////////////
494 // Visi interface routine.   Receives an array of histogram 
495 // values for the datagrid cell indicated by metricId and 
496 // resourceId 
497 ///////////////////////////////////////////////////////////
498 void visualization::BulkDataTransfer(float_Array values,
499                                      int metricId,
500                                      int resourceId){
501 int i, lastBucket, temp, j;
502 int noMetrics, noResources;
503 int met = -1, res = -1;
504
505
506     // find datagrid indicies associated with metricId, resourceId 
507     noMetrics = dataGrid.NumMetrics();
508     noResources = dataGrid.NumResources();
509     for(i = 0; i < noMetrics; i++){
510         if(dataGrid.MetricId(i) == metricId)
511             met = i;
512     }
513     for(i = 0; i < noResources; i++){
514         if(dataGrid.ResourceId(i) == resourceId)
515             res = i;
516     }
517     if((met == -1) || (res == -1))  return; 
518
519     // add new data values to datagrid
520     for(i = 0; i < values.count; i++){
521        if(!isnan(values.data[i])){
522            dataGrid.AddValue(met, res, i, (float)values.data[i]);
523        }
524     }
525    
526     // find last full cross section for new dataGrid 
527     lastBucket = dataGrid.NumBins()+1;
528     for(i=0; i < noMetrics; i++){
529         for(j=0; j < noResources; j++){
530             if(dataGrid.Valid(i,j)){
531                 temp = dataGrid.LastBucketFilled(i,j);  
532                 if((temp > -1) && (temp < lastBucket))
533                 lastBucket = temp; 
534             }
535         }
536     }
537
538     // call DATAVALUES callback routine
539     if(eventCallbacks[DATAVALUES] !=  NULL){
540        i = eventCallbacks[DATAVALUES](lastBucket);
541     }
542
543 }
544
545
546 ///////////////////////////////////////////////////////////
547 // Visi interface routine.  Visualization recieves Phase
548 // information from Paradyn.
549 ///////////////////////////////////////////////////////////
550 void visualization::Phase(double begin,
551                           double end,
552                           char *name){
553
554 int size,ok;
555
556   if(!initDone)
557     VisiInit();
558   size = strlen(name);
559    
560   //call callback routine assoc. w/event PHASENAME
561   if(eventCallbacks[PHASENAME] !=  NULL){
562      ok = eventCallbacks[PHASENAME](0);
563   }
564 }
565