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