Fix the symbols reading problem on Linux/X86 platform
[dyninst.git] / visi / src / visualization.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 #include <stream.h> 
43 #include "visi/src/visualizationP.h"
44 #include "visi/src/datagridP.h"
45 #include "visi/src/visiTypesP.h"
46 #include "util/h/makenan.h"
47 #include "visi/h/visualization.h"
48
49 #define MAXSTRINGSIZE  16*1024
50 #define EVENTSIZE      FOLD+1
51
52 static visi_DataGrid  visi_dataGrid;
53 // trace data streams
54 static visi_TraceData visi_traceData;
55 static int            visi_LastBucketSent = -1;
56 static int visi_fileDesc;
57 static int (*visi_fileDescCallbacks)();
58 static int (*visi_eventCallbacks[EVENTSIZE])(int);
59 static int visi_initDone = 0;
60 static visualization *visi_vp;
61
62 // TODO -- better error checking here?
63 int visi_callback(){
64   return(visi_vp->waitLoop());
65 }
66
67 ///////////////////////////////////////////////////////////
68 // paradyn initialization routine connects to parent socket,
69 // and registers the visualization::mainLoop routine as 
70 // callback on events on fileDesc[0]
71 ///////////////////////////////////////////////////////////
72 int visi_Init(){
73
74 int i;
75
76   visi_fileDescCallbacks = NULL;
77   visi_fileDesc = -1;
78   for(i=0;i<EVENTSIZE;i++){
79     visi_eventCallbacks[i] = NULL;
80   }
81
82   visi_vp = new visi_visualization(0);
83   visi_fileDesc = 0;
84   visi_fileDescCallbacks = visi_callback;
85   visi_initDone = 1;
86  
87   // make request for info. about all phases defined so far 
88   visi_vp->GetPhaseInfo();
89
90   return(visi_fileDesc);
91 }
92
93 ///////////////////////////////////////////////////////////
94 // makes initial call to get Metrics and Resources 
95 // for visualizations that do not provide an event that 
96 // invokes the GetMetsRes upcall, this routine should be
97 // called by the visiualizaiton before entering the mainloop
98 ///////////////////////////////////////////////////////////
99 int visi_StartVisi(int argc,
100               char *argv[]){
101
102   if(!visi_initDone)
103     visi_Init();
104
105   // call GetMetricResources with initial metric resource lists
106   if(argc == 3)
107    visi_vp->GetMetricResource(argv[1],(int)argv[2],0);
108   else
109    visi_vp->GetMetricResource("",0,0);
110   return(OK);
111
112 }
113
114 ///////////////////////////////////////////////////////////
115 // cleans up visi interface data structs 
116 // Visualizations should call this routine before exiting 
117 ///////////////////////////////////////////////////////////
118 void visi_QuitVisi(){
119
120     delete visi_vp;
121 }
122
123 //
124 // call back to Paradyn to display error message
125 //
126 void visi_showErrorVisiCallback(const char *msg)
127 {
128   int string_size;
129   string new_msg = msg; 
130   string_size = (new_msg.length())*sizeof(char);
131   if (string_size < MAXSTRINGSIZE)
132     visi_vp->showError(87,new_msg);
133   else {
134     string errmsg;
135     errmsg = string("Internal Error: error message has exceeded maximum length of ") + string(MAXSTRINGSIZE) + string(" bytes. Please, make your error message shorter.");
136     visi_vp->showError(87,errmsg);
137   }
138 }  
139
140 ///////////////////////////////////////////////////////////
141 // registration callback routine for paradyn events
142 // sets eventCallbacks[event] to callback routine provided by user
143 ///////////////////////////////////////////////////////////
144 int visi_RegistrationCallback(visi_msgTag event,
145                          int (*callBack)(int)){
146
147   if((event < EVENTSIZE)){
148     visi_eventCallbacks[event] = callBack;
149     return(OK);
150   }
151   return(ERROR_INT);
152 }
153
154 ///////////////////////////////////////////////////////////
155 // invokes upcall to paradyn VISIthread associated with the visualization
156 // takes list of current metrics, list of foci, and type of data
157 // (0 for histogram, 1 for scalar). 
158 // currently, only the NULL string, type 0 case is supported 
159 ///////////////////////////////////////////////////////////
160 void visi_GetMetsRes(char *, int){
161
162   if(!visi_initDone)
163     visi_Init();
164   visi_vp->GetMetricResource(0,0,0);
165 }
166
167
168 ///////////////////////////////////////////////////////////
169 // invokes upcall to paradyn.  Request to stop data for the 
170 // metric associated with metricIndex and resource associated with
171 // resourceIndex
172 ///////////////////////////////////////////////////////////
173 void visi_StopMetRes(int metricIndex,
174                      int resourceIndex){
175
176   if(!visi_initDone)
177     visi_Init();
178   if((metricIndex < visi_dataGrid.NumMetrics()) 
179       && (metricIndex >= 0)
180       && (resourceIndex >= 0)
181       && (resourceIndex <visi_dataGrid.NumResources())){
182     visi_dataGrid[metricIndex][resourceIndex].ClearEnabled();
183     visi_dataGrid[metricIndex][resourceIndex].Invalidate();
184     bool met_error = false;
185     bool res_error = false;
186     u_int m = visi_dataGrid.MetricId(metricIndex,met_error);
187     u_int r = visi_dataGrid.ResourceId(resourceIndex,res_error);
188     if((!met_error) && (!res_error)){
189         visi_vp->StopMetricResource(m,r);
190     }
191   }
192 }
193
194 ///////////////////////////////////////////////////////////
195 // invokes upcall to paradyn.  Visualization sends phase
196 // definition to paradyn.  
197 ///////////////////////////////////////////////////////////
198 void visi_DefinePhase(char *name, unsigned withPerfConsult,
199                       unsigned withVisis) {
200   if(!visi_initDone)
201     visi_Init();
202   if(withPerfConsult){
203       if(withVisis){
204           visi_vp->StartPhase((double)-1.0,name,true,true);
205       }
206       else {
207           visi_vp->StartPhase((double)-1.0,name,true,false);
208       }
209   }
210   else if(withVisis) {
211       visi_vp->StartPhase((double)-1.0,name,false,true);
212   }
213   else {
214       visi_vp->StartPhase((double)-1.0,name,false,false);
215   }
216 }
217
218 ///////////////////////////////////////////////////////////
219 //  Visi interface routine.  Receives an array of data 
220 //  values from paradyn, adds them to the datagrid, and
221 //  invokes the callback routine associated with the
222 //  DATAVALUES event.
223 ///////////////////////////////////////////////////////////
224 void visualization::Data(vector<T_visi::dataValue> data){
225
226   if(!visi_initDone)
227     visi_Init();
228
229   int noMetrics = visi_dataGrid.NumMetrics();
230   int noResources = visi_dataGrid.NumResources();
231
232   // get metric and resource index into visi_dataGrid and add value if found
233   for(unsigned i=0; i < data.size(); i++){
234       int metric = visi_dataGrid.MetricIndex(data[i].metricId);
235       int j = visi_dataGrid.ResourceIndex(data[i].resourceId);
236       if((j >= 0) && (metric >= 0)){
237          visi_dataGrid.AddValue(metric,j,
238                          data[i].bucketNum,
239                          data[i].data);
240   }} 
241
242   int min;
243   int max = visi_dataGrid.NumBins()+1;
244   min = max;
245   for(int i2=0; i2 < noMetrics; i2++){
246       for(int k=0; k < noResources; k++){
247           if(visi_dataGrid.Valid(i2,k)){
248               int temp = visi_dataGrid.LastBucketFilled(i2,k);  
249               if((temp > -1) && (temp < min))
250               min = temp; 
251   }}}
252
253   //call user registered callback routine assoc. w/event DATAVALUES
254   if((min > visi_LastBucketSent) //if new datagrid cross-section has been filled
255      && (min != max)
256      && (visi_eventCallbacks[DATAVALUES]!=NULL)){ //theres a callback routine 
257        visi_LastBucketSent = min;
258        visi_eventCallbacks[DATAVALUES](visi_LastBucketSent);
259   }
260 }
261
262 ///////////////////////////////////////////////////////////
263 //  Visi interface routine.  Receives trace data values from paradyn and
264 //  invokes the callback routine associated with the
265 //  TRACEDATAVALUES event.
266 ///////////////////////////////////////////////////////////
267 void visualization::TraceData(vector<T_visi::traceDataValue> traceData){
268
269   if(!visi_initDone)
270     visi_Init();
271
272   int noMetrics = visi_dataGrid.NumMetrics();
273   int noResources = visi_dataGrid.NumResources();
274
275   // get metric and resource index into visi_dataGrid and add value if found
276   for(unsigned i=0; i < traceData.size(); i++){
277     if (traceData[i].traceDataRecord.length()) {
278       int metric = visi_dataGrid.MetricIndex(traceData[i].metricId);
279       int j = visi_dataGrid.ResourceIndex(traceData[i].resourceId);
280       if((j >= 0) && (metric >= 0)){
281          visi_traceData.metricIndex = metric;
282          visi_traceData.resourceIndex = j;
283          visi_traceData.dataRecord =
284               new byteArray(traceData[i].traceDataRecord.getArray(),
285               traceData[i].traceDataRecord.length());
286       }
287
288
289   //call user registered callback routine assoc. w/event TRACEDATAVALUES
290   if ((visi_eventCallbacks[TRACEDATAVALUES]!=NULL)){ //theres a callback routine
291        visi_eventCallbacks[TRACEDATAVALUES](visi_traceData.dataRecord->length());
292   }
293   delete visi_traceData.dataRecord;
294     }
295   }
296 }
297
298 ///////////////////////////////////////////////////////////
299 //  Visi interface routine.  Receives notification of a
300 //  fold event, and the new bucket width.  Invokes
301 //  a fold operation on the datagrid
302 ///////////////////////////////////////////////////////////
303 void visualization::Fold(double newBucketWidth){
304   
305   int ok;
306
307   if(!visi_initDone)
308     visi_Init();
309
310   visi_dataGrid.Fold(newBucketWidth);
311   // assume a fold can only occur when datagrid histogram buckets are full
312   visi_LastBucketSent = (visi_dataGrid.NumBins()/2) - 1;
313
314   //call user registered callback routine assoc. w/event FOLD
315   if(visi_eventCallbacks[FOLD] !=  NULL){
316      ok = visi_eventCallbacks[FOLD](0);
317   }
318 }
319
320 ///////////////////////////////////////////////////////////
321 // Visi interface routine.  Receives notification of an
322 // invalid metric/resource pair.  Invalidataes the datagrid
323 // cell associated with the metricId m and resourceId r.
324 ///////////////////////////////////////////////////////////
325 void visualization::InvalidMR(u_int m, u_int r){
326
327 int i,j;
328 int ok;
329
330   if(!visi_initDone)
331     visi_Init();
332
333   // search for indices associated with metricId m and
334   // resourceId r
335   bool error = false;
336   for(i=0; (i<visi_dataGrid.NumMetrics()) &&(m != visi_dataGrid.MetricId(i,error)); i++){
337       if(error) return;
338   } 
339
340   for(j=0;(j<visi_dataGrid.NumResources())&&(r!= visi_dataGrid.ResourceId(j,error));j++){
341       if(error) return;
342   }
343
344   visi_dataGrid[i][j].ClearEnabled();
345   ok  = visi_dataGrid.Invalidate(i,j);
346
347   //call callback routine assoc. w/event INVALIDMETRICSRESOURCES 
348   if(visi_eventCallbacks[INVALIDMETRICSRESOURCES] != NULL){
349      ok = visi_eventCallbacks[INVALIDMETRICSRESOURCES](0);
350   }
351 }
352
353 ///////////////////////////////////////////////////////////
354 // Visi interface routine.  Receives a list of metrics and
355 // resources to add to the datagrid.
356 ///////////////////////////////////////////////////////////
357 void visualization::AddMetricsResources(vector<T_visi::visi_matrix> newElements,
358                                         double bucketWidth,
359                                         int nobuckets,
360                                         double start_time,
361                                         int phase_handle){
362
363
364   int ok;
365   visi_metricType *mets = 0;
366   visi_resourceType *res = 0;
367   int numRes, numMet;
368
369   if(!visi_initDone)
370     visi_Init();
371
372   // this is first set of metrics/resources, construct new visi_dataGrid
373   if(!visi_dataGrid.NumMetrics()){
374     // create list of all unique metric and resource entries
375     // in newElements
376     numRes = 0;
377     numMet = 0;
378     if((res= new visi_resourceType [newElements.size()]) == NULL){ 
379         return;
380     }                              
381     if((mets= new visi_metricType [newElements.size()]) == NULL){
382         return;
383     }                              
384     for(unsigned i = 0; i < newElements.size(); i++){
385         ok = 0;
386         for(int j=0; (j < numMet) && (!ok);j++){
387            if(newElements[i].met.Id == mets[j].Id)
388              ok = 1;
389         }
390         if(!ok){
391             if(!newElements[i].met.name.length())
392                 mets[numMet].name = NULL;
393             else
394                 mets[numMet].name = newElements[i].met.name.string_of();
395             if(!newElements[i].met.units.length())
396                 mets[numMet].units = NULL;
397             else
398                 mets[numMet].units = newElements[i].met.units.string_of();
399             mets[numMet].Id = newElements[i].met.Id;
400             if(newElements[i].met.unitstype == 0){
401                 mets[numMet].unitstype = UnNormalized;
402             }
403             else if(newElements[i].met.unitstype == 1){
404                 mets[numMet].unitstype = Normalized;
405             }
406             else {
407                 mets[numMet].unitstype = Sampled;
408             }
409             mets[numMet++].aggregate = newElements[i].met.aggregate;
410         }
411           ok = 0;
412         for(int j2=0; (j2 < numRes) && (!ok);j2++){
413            if(newElements[i].res.Id == res[j2].Id)
414              ok = 1;
415         }
416         if(!ok){
417             if(!newElements[i].res.name.length())
418                 res[numRes].name = NULL;
419             else
420                 res[numRes].name = newElements[i].res.name.string_of();
421             res[numRes++].Id = newElements[i].res.Id;
422         }
423     }
424
425     // construct new visi_dataGrid 
426     visi_dataGrid.visi_DataGrid(numMet,
427                            numRes,
428                            mets,
429                            res,
430                            nobuckets,
431                            (visi_timeType)bucketWidth,
432                            (visi_timeType)start_time,
433                            phase_handle);
434     // trace data streams
435     // construct new visi_traceData
436     visi_traceData.visi_TraceData();
437   }
438   else{ // add elements to existing data grid
439
440     // create list of new resources and add them to resource list
441     res= new visi_resourceType [newElements.size()];
442     numRes = 0;
443     for(unsigned i=0; i < newElements.size(); i++){
444       if(!visi_dataGrid.ResourceInGrid(newElements[i].res.Id)){
445           ok = 0;
446           for(int k=0; (k < numRes) && !ok; k++){
447              if(newElements[i].res.Id == res[k].Id)
448                ok = 1;
449           }
450           if(!ok){
451               if(!newElements[i].res.name.length())
452                 res[numRes].name = NULL;
453               else
454                 res[numRes].name = newElements[i].res.name.string_of();
455               res[numRes++].Id = newElements[i].res.Id;
456           }
457     }}
458
459     // add new resources to visi_dataGrid
460     if(numRes > 0)
461       visi_dataGrid.AddNewResource(numRes,res);
462
463     // create list of new metrics and add them to metricsList
464     mets = new visi_metricType [newElements.size()];
465     numMet = 0;
466     for(unsigned i2=0; i2 < newElements.size(); i2++){
467       if(!visi_dataGrid.MetricInGrid(newElements[i2].met.Id)){
468
469           ok = 0;
470           for(int k2=0; (k2 < numMet) && !ok; k2++){
471              if(newElements[i2].met.Id == mets[k2].Id)
472                ok = 1;
473           }
474           if(!ok){
475               if(!newElements[i2].met.name.length())
476                   mets[numMet].name = NULL;
477               else
478                   mets[numMet].name = newElements[i2].met.name.string_of();
479               if(!newElements[i2].met.units.length())
480                   mets[numMet].units = NULL;
481               else
482                   mets[numMet].units = newElements[i2].met.units.string_of();
483             mets[numMet].Id = newElements[i2].met.Id;
484             if(newElements[i2].met.unitstype == 0){
485                 mets[numMet].unitstype = UnNormalized;
486             }
487             else if(newElements[i2].met.unitstype == 1){
488                 mets[numMet].unitstype = Normalized;
489             }
490             else {
491                 mets[numMet].unitstype = Sampled;
492             }
493             mets[numMet++].aggregate = newElements[i2].met.aggregate;
494         }
495     }}
496
497     // add new metrics to visi_dataGrid
498     if(numMet > 0)
499       visi_dataGrid.AddNewMetrics(numMet,mets);
500   }
501
502   // set enabled for every element of newElements list 
503   for(unsigned r = 0; r < newElements.size(); r++){
504      visi_dataGrid[visi_dataGrid.MetricIndex(newElements[r].met.Id)][visi_dataGrid.ResourceIndex(newElements[r].res.Id)].SetEnabled();
505   }
506  
507   delete [] mets;
508   delete [] res;
509   //call callback routine assoc. w/event ADDMETRICSRESOURCES 
510   if(visi_eventCallbacks[ADDMETRICSRESOURCES] !=  NULL){
511      ok = visi_eventCallbacks[ADDMETRICSRESOURCES](0);
512   }
513 }
514
515 ///////////////////////////////////////////////////////////
516 // Visi interface routine.   Receives an array of histogram 
517 // values for the datagrid cell indicated by metricId and 
518 // resourceId 
519 ///////////////////////////////////////////////////////////
520 void visualization::BulkDataTransfer(vector<float> values,
521                                      u_int metricId,
522                                      u_int resourceId){
523 int lastBucket, temp, j;
524 int noMetrics, noResources;
525 int met,res;
526
527
528     // find datagrid indicies associated with metricId, resourceId 
529     noMetrics = visi_dataGrid.NumMetrics();
530     noResources = visi_dataGrid.NumResources();
531     bool found = false;
532     bool error = false;
533     for(int i = 0; i < noMetrics; i++){
534         u_int m_id = visi_dataGrid.MetricId(i,error);
535         if(!error){
536             if(m_id == metricId){
537                 met = i;
538                 found = true;
539             }
540         }
541     }
542
543     if(!found) return;
544     found = false;
545     error = false;
546     for(int i1 = 0; i1 < noResources; i1++){
547         u_int r_id = visi_dataGrid.ResourceId(i1,error);  
548         if(!error){
549             if(r_id == resourceId){
550                 res = i1;
551                 found = true;
552             }
553         }
554     }
555     if(!found) return;
556
557     // add new data values to datagrid
558     for(unsigned i2 = 0; i2 < values.size(); i2++){
559        if(!isnan(values[i2])){
560            visi_dataGrid.AddValue(met, res, i2, values[i2]);
561        }
562     }
563    
564     // find last full cross section for new visi_dataGrid 
565     lastBucket = visi_dataGrid.NumBins()+1;
566     for(int i3=0; i3 < noMetrics; i3++){
567         for(j=0; j < noResources; j++){
568             if(visi_dataGrid.Valid(i3,j)){
569                 temp = visi_dataGrid.LastBucketFilled(i3,j);  
570                 if((temp > -1) && (temp < lastBucket))
571                 lastBucket = temp; 
572             }
573         }
574     }
575
576     // call DATAVALUES callback routine
577     if(visi_eventCallbacks[DATAVALUES] !=  NULL){
578        visi_eventCallbacks[DATAVALUES](lastBucket);
579     }
580
581 }
582
583
584 ///////////////////////////////////////////////////////////
585 // Visi interface routine.  Visualization recieves Phase
586 // start information from Paradyn.
587 ///////////////////////////////////////////////////////////
588 void visualization::PhaseStart(double begin,
589                           double end,
590                           double bucketWidth,
591                           string name,
592                           u_int handle){
593
594   if(!visi_initDone)
595     visi_Init();
596    
597    // add new phase to phase vector
598    visi_dataGrid.AddNewPhase(handle,(visi_timeType)begin,(visi_timeType)end,
599                         (visi_timeType)bucketWidth,name);
600
601   //call callback routine assoc. w/event PHASESTART
602   if(visi_eventCallbacks[PHASESTART] !=  NULL){
603      visi_eventCallbacks[PHASESTART](visi_dataGrid.NumPhases()-1);
604   }
605 }
606
607 ///////////////////////////////////////////////////////////
608 // Visi interface routine.  Visualization recieves Phase
609 // end information from Paradyn.
610 ///////////////////////////////////////////////////////////
611 void visualization::PhaseEnd(double end, u_int handle){
612
613
614   if(!visi_initDone)
615     visi_Init();
616
617    // update phase end time for phase assoc w/handle
618    int ok;
619    if(!(ok = visi_dataGrid.AddEndTime(end,handle))){
620        // fprintf(stderr,"in visualization::PhaseEnd: phase end not added\n");
621    }
622    
623   //call callback routine assoc. w/event PHASEEND
624   if(visi_eventCallbacks[PHASEEND] !=  NULL){
625      visi_eventCallbacks[PHASEEND](visi_dataGrid.NumPhases()-1);
626   }
627 }
628
629 ///////////////////////////////////////////////////////////
630 // Visi interface routine.  Visualization recieves list  
631 // of all Phase info from Paradyn.
632 ///////////////////////////////////////////////////////////
633 void visualization::PhaseData(vector<T_visi::phase_info> phases){
634
635   if(!visi_initDone)
636     visi_Init();
637
638   // add an new phase object to the visi_dataGrid's vector of phases
639    for (unsigned i=0; i < phases.size(); i++){ 
640      visi_dataGrid.AddNewPhase(phases[i].handle,
641                 (visi_timeType)phases[i].start,
642                 (visi_timeType)phases[i].end,
643                 (visi_timeType)phases[i].bucketWidth,
644                 phases[i].name.string_of());
645    }
646
647   //call callback routine assoc. w/event PHASEDATA
648   if(visi_eventCallbacks[PHASEDATA] !=  NULL){
649      visi_eventCallbacks[PHASEDATA](0);
650   }
651 }
652
653 void visi_visualization::handle_error(){
654    // call user registered callback routine assoc. w/event PARADYNEXITED
655    if(visi_eventCallbacks[PARADYNEXITED] !=  NULL){
656       visi_eventCallbacks[PARADYNEXITED](0);
657    }
658    // otherwise, exit
659    else {
660       exit(-1);
661    }
662 }
663
664 //***************************** Data Grid Routines ************
665
666 //
667 // returns the ith metric name or 0 on error
668 //
669 const char *visi_MetricName(int metric_num){ 
670     return visi_dataGrid.MetricName(metric_num);
671 }
672
673 //
674 // returns the ith metric units name or 0 on error
675 //
676 const char *visi_MetricUnits(int metric_num){
677     return visi_dataGrid.MetricUnits(metric_num);
678 }
679
680 //
681 // returns the ith metric units label for data values or 0 on error
682 //
683 const char *visi_MetricLabel(int metric_num){
684     return visi_dataGrid.MetricLabel(metric_num);
685 }
686
687 //
688 // returns the ith metric units label for average aggregate data values,
689 // or 0 on error
690 //
691 const char *visi_MetricAveLabel(int metric_num){
692     return visi_dataGrid.MetricAveLabel(metric_num);
693 }
694
695 //
696 // returns the ith metric units label for sum aggregate data values,
697 // or 0 on error
698 //
699 const char *visi_MetricSumLabel(int metric_num){
700     return visi_dataGrid.MetricSumLabel(metric_num);
701 }
702
703 //
704 // returns the ith resource's name,  or 0 on error
705 //
706 const char *visi_ResourceName(int resource_num){
707     return visi_dataGrid.ResourceName(resource_num);
708 }
709
710 //
711 //  returns the number of metrics in the data grid
712 //
713 int visi_NumMetrics(){
714     return visi_dataGrid.NumMetrics();
715 }
716
717 //
718 //  returns the number of resources in the data grid
719 //
720 int visi_NumResources(){
721     return visi_dataGrid.NumResources();
722 }
723
724 //
725 //  returns the number of phases currently defined in the system
726 //
727 unsigned visi_NumPhases(){
728     return visi_dataGrid.NumPhases();
729 }
730
731 //
732 // returns the start time of the phase for which this visi is defined
733 //
734 visi_timeType visi_GetStartTime(){
735     return visi_dataGrid.GetStartTime();
736 }
737
738 //
739 // returns the name of the phase for which this visi is defined
740 //
741 const char *visi_GetMyPhaseName(){
742     return visi_dataGrid.GetMyPhaseName();
743 }
744
745 //
746 // returns the handle of the phase for which this visi is defined or
747 // -1 on error
748 //
749 int visi_GetMyPhaseHandle(){
750
751     return (visi_dataGrid.GetPhaseHandle());
752 }
753
754 //
755 // returns the handle of the phase for which this visi is defined or
756 // -1 on error
757 //
758 int visi_GetPhaseHandle(unsigned phase_num){
759
760     const PhaseInfo *p = visi_dataGrid.GetPhaseInfo(phase_num);
761     if(p){
762         return (p->getPhaseHandle());
763     }
764     return (-1);
765 }
766
767 //
768 // returns phase name for the ith phase, or returns 0 on error
769 //
770 const char *visi_GetPhaseName(unsigned phase_num){
771
772     const PhaseInfo *p = visi_dataGrid.GetPhaseInfo(phase_num);
773     if(p){
774         return (p->getName());
775     }
776     return (0);
777 }
778
779 //
780 // returns phase start time for the ith phase, or returns -1.0 on error
781 //
782 visi_timeType visi_GetPhaseStartTime(unsigned phase_num){
783
784     const PhaseInfo *p = visi_dataGrid.GetPhaseInfo(phase_num);
785     if(p){
786         return (p->getStartTime());
787     }
788     return (-1.0);
789 }
790
791 //
792 // returns phase end time for the ith phase, or returns -1.0 on error
793 //
794 visi_timeType visi_GetPhaseEndTime(unsigned phase_num){
795
796     const PhaseInfo *p = visi_dataGrid.GetPhaseInfo(phase_num);
797     if(p){
798         return (p->getEndTime());
799     }
800     return (-1.0);
801 }
802
803 //
804 // returns phase bucket width for the ith phase, or returns -1.0 on error
805 //
806 visi_timeType visi_GetPhaseBucketWidth(unsigned phase_num){
807
808     const PhaseInfo *p = visi_dataGrid.GetPhaseInfo(phase_num);
809     if(p){
810         return (p->getBucketWidth());
811     }
812     return (-1.0);
813 }
814
815 //
816 // returns the average of all the data bucket values for the metric/resource
817 // pair "metric_num" and "resource_num", returns NaN value on error
818 //
819 visi_sampleType visi_AverageValue(int metric_num, int resource_num){
820     return visi_dataGrid.AggregateValue(metric_num,resource_num);
821 }
822
823 //
824 // returns the sum of all the data bucket values for the metric/resource
825 // pair "metric_num" and "resource_num", returns NaN value on error
826 //
827 visi_sampleType visi_SumValue(int metric_num, int resource_num){
828     return visi_dataGrid.SumValue(metric_num,resource_num);
829 }
830
831 //
832 // returns the data value in bucket "bucket_num" for the metric/resource pair
833 // "metric_num" and "resource_num", returns NaN value on error
834 //
835 visi_sampleType visi_DataValue(int metric_num, int resource_num, int bucket_num){
836     return visi_dataGrid[metric_num][resource_num][bucket_num];
837 }
838
839 //
840 // returns the data values for the metric/resource pair "metric_num" 
841 // and "resource_num", returns NaN value on error
842 //
843 const visi_sampleType *visi_DataValues(int metric_num, int resource_num){
844
845     if((metric_num >= 0) && (metric_num < visi_dataGrid.NumMetrics())
846        && (resource_num >= 0) && (resource_num < visi_dataGrid.NumResources())){
847         return visi_dataGrid[metric_num][resource_num].Value();
848     }
849     return 0;
850 }
851
852 // trace data streams
853 //
854 // returns the pointer to the trace data record 
855 //
856
857 const visi_TraceData *visi_TraceDataValues(){
858
859     return &visi_traceData;
860 }
861
862 //
863 //  returns true if the data grid cell corresponding to metric_num
864 //  and resource_num contains data
865 //
866 int visi_Valid(int metric_num, int resource_num){
867     if (visi_dataGrid.Valid(metric_num,resource_num))
868         return 1;
869     else
870         return 0;
871 }
872
873 //
874 //  returns true if the data collection has been enabled for metric_num
875 //  and resource_num
876 //
877 int visi_Enabled(int metric_num, int resource_num){
878     if (visi_dataGrid[metric_num][resource_num].Enabled())
879         return 1;
880     else
881         return 0;
882 }
883
884
885 //
886 //  returns the number of buckets in each data grid cell's histogram
887 //
888 int visi_NumBuckets(){
889     return visi_dataGrid.NumBins();
890 }
891
892 //
893 //  returns the buckets width (in seconds) of each data grid cell's histogram
894 //
895 visi_timeType visi_BucketWidth(){
896     return visi_dataGrid.BinWidth();
897 }
898
899 //
900 // returns the first data bucket with valid data values
901 //
902 int visi_FirstValidBucket(int metric_num, int resource_num){
903     return visi_dataGrid[metric_num][resource_num].FirstValidBucket();
904 }
905
906 //
907 // returns the last data bucket with valid data values
908 //
909 int visi_LastBucketFilled(int metric_num,int resource_num){
910     return visi_dataGrid.LastBucketFilled(metric_num, resource_num);
911 }
912
913 //
914 // returns true if there are invalid spans of data between the first
915 // valid bucket and the last bucket filled
916 //
917 int visi_InvalidSpans(int metric_num,int resource_num){
918     if(visi_dataGrid.InvalidSpans(metric_num, resource_num)) return 1;
919     else return 0;
920 }
921
922 //
923 // returns the user data associated with metric_num and resource_num
924 // returns 0 on error
925 //
926 void *visi_GetUserData(int metric_num, int resource_num){
927
928     if((metric_num >= 0) && (metric_num < visi_dataGrid.NumMetrics())
929        && (resource_num >= 0) && (resource_num < visi_dataGrid.NumResources())){
930         return visi_dataGrid[metric_num][resource_num].userdata;
931     }
932     return 0;
933 }
934
935 //
936 // sets the user data associated with metric_num and resource_num
937 //
938 int visi_SetUserData(int metric_num, int resource_num, void *data){
939
940     if((metric_num >= 0) && (metric_num < visi_dataGrid.NumMetrics())
941        && (resource_num >= 0) && (resource_num < visi_dataGrid.NumResources())){
942         visi_dataGrid[metric_num][resource_num].userdata = data;
943         return 1;
944     }
945     return 0;
946 }
947
948 //
949 // sets the trace data associated with metric_num and resource_num
950 //
951 int visi_SetTraceData(int metric_num, int resource_num, visi_sampleType data){
952       if((resource_num >= 0) && (metric_num >= 0)){
953          visi_dataGrid.AddValue(metric_num,resource_num,
954                 visi_dataGrid.LastBucketFilled(metric_num, resource_num) + 1,
955                 data);
956          return 1;
957       }
958       return 0;
959 }
960
961 void visi_PrintDataBuckets(int step){
962
963     int noMetrics = visi_dataGrid.NumMetrics();
964     int noResources = visi_dataGrid.NumResources();
965     int noBuckets = visi_dataGrid.NumBins();
966     for(int i = 0; i < noMetrics; i++){
967         for(int j=0; j < noResources; j++){
968             if (visi_dataGrid[i][j].Valid()){
969                 cerr << visi_dataGrid.MetricName(i) << "/" 
970                      << visi_dataGrid.ResourceName(j) << endl;
971                 for(int k=0; k < noBuckets; k+=step){
972                     cerr << "value(" << k << ") = " << visi_dataGrid[i][j][k]
973                          << endl;
974                 }
975             }
976         }
977     }
978
979 }
980