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