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