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