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