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