made some inline functions non-inline because of size;
[dyninst.git] / visi / src / datagrid.C
1 /*
2  * Copyright (c) 1996-1999 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 // $Id: datagrid.C,v 1.27 2001/08/23 14:44:48 schendel Exp $
43
44 ///////////////////////////////////////////////
45 // Member functions for the following classes:
46 //  Metric, Resource, visi_GridCellHisto,
47 //  visi_GridHistoArray, visi_DataGrid
48 ///////////////////////////////////////////////
49 #include "visi/src/datagridP.h" 
50
51 Metric::Metric(string metricUnits,
52                string metricName,
53                u_int id,
54                int foldMethod,
55                visi_unitsType units_type){
56
57   units = metricUnits;
58   name = metricName;
59   Id    = id;
60   if(foldMethod == AVE)
61     aggregate = foldMethod;
62   else
63     aggregate = SUM;
64   unitstype = units_type;
65   if(unitstype == Normalized) {
66     label = units;
67     total_label = units;
68     total_label += P_strdup("_seconds");
69   }
70   else if (unitstype == UnNormalized) {
71     label = units;
72     label += P_strdup("/sec");
73     total_label = units; 
74   }
75   else {
76     label = units;
77     total_label = units; 
78   }
79 }
80
81 //
82 //  Metric destructor
83 //
84 Metric::~Metric(){
85   Id = 0;
86 }
87
88 ///////////////////////////////////////////
89 //
90 //  Resource constructor
91 //
92 Resource::Resource(string resourceName,
93                    u_int id){
94
95   if(resourceName.string_of() != 0){
96     name = resourceName; 
97     Id = id;
98   }
99   else {
100     name = 0;
101     Id = 0;
102   }
103 }
104
105 //
106 //  Resource destructor
107 //
108 Resource::~Resource(){
109 }
110
111 ///////////////////////////////////////////
112 //
113 //  visi_GridCellHisto constructor
114 //
115 visi_GridCellHisto::visi_GridCellHisto(int numElements){
116
117  int i;
118     
119  if(numElements > 0){  
120    value = new visi_sampleType[numElements];
121    for(i = 0; i < numElements; i++)
122      value[i] = VISI_ERROR;
123    valid      = 1;
124  }
125  enabled = 0;
126  size       = numElements;
127  lastBucketFilled = -1;
128  firstValidBucket = -1;
129 }
130
131 //
132 // destructor for class visi_GridCellHisto
133 //
134 visi_GridCellHisto::~visi_GridCellHisto(){
135
136   if(value) delete[] value;
137   value = 0;
138   valid = 0;
139   enabled = 0;
140   size = 0;
141 }
142
143 // returns a normalized value for EventCounter metrics which is (currently)
144 // what is stored in each bucket for these style of metrics returns the
145 // actual value for the SampledFunction metrics, which it does by summing
146 // across all the previous buckets and adding the initial actual value of the
147 // metric.  the implementation needs to be changed since the format of the
148 // histogram has been changed so that the change in sample value (instead of
149 // the actual value) is stored for each bucket for SampledFunction metrics
150 visi_sampleType visi_GridCellHisto::Value(int bkt, visi_unitsType unitstype) { 
151   visi_sampleType retSample = 0;
152
153   if((bkt < 0) || (bkt >= size)){
154     retSample = VISI_ERROR;
155   } else if(unitstype == Sampled) {
156     if(isnan(value[bkt]))
157       retSample = VISI_ERROR;
158     else if(initActVal == -1) {
159       retSample = VISI_ERROR;      
160     } else {
161       retSample = initActVal;
162       for(int i=0; i<=bkt; i++) {
163         if(!isnan(value[i])){
164           retSample += value[i];
165         }
166       }
167     } 
168   } else {
169     retSample = value[bkt];
170   }
171
172   return retSample;
173 }
174
175 int visi_GridCellHisto::AddNewValues(visi_sampleType *temp, int arraySize,
176                                      int lbf, void *ud, int v, int e) {
177   if(temp == NULL){
178     value = NULL;
179     size = 0;
180   }
181   else{
182     // initialize cell to temp values
183     value = new visi_sampleType[arraySize];
184     size = arraySize;
185     for(int i=0;i<size;i++){
186       if(!isnan(temp[i])){
187         value[i] = temp[i]; 
188         if(firstValidBucket == -1) {
189           firstValidBucket = i;
190         }
191       }
192       else
193         value[i] = VISI_ERROR; 
194     }
195   }
196   lastBucketFilled = lbf;
197   userdata = ud;
198   valid = v;
199   enabled = e;
200   return(VISI_OK);
201 }
202
203 int visi_GridCellHisto::AddValue(visi_sampleType x, int i, int numElements) {
204   int j;
205   
206   if (!enabled){ // if this cell has not been enabled don't add values
207     return(VISI_OK);
208   }
209   if (!valid){ // if this is the first value create a histo cell array 
210     if(value == NULL)
211       value = new visi_sampleType[numElements];
212     size = numElements;
213     valid = 1;
214     enabled = 1;
215     for(j=0;j<size;j++){
216       value[j] = VISI_ERROR;
217     }
218   }
219   if((i < 0) || (i >= size))
220     return(VISI_ERROR_INT);
221   value[i] = x;
222   if(i > lastBucketFilled) {
223     lastBucketFilled = i;
224   }
225   if(firstValidBucket == -1) {
226     firstValidBucket = i;
227   }
228   return(VISI_OK);
229 }
230
231 void visi_GridCellHisto::Fold(visi_unitsType unitstype) {
232   int i,j;
233   if(valid){
234     firstValidBucket = -1;
235     for(i=0,j=0;(i< (lastBucketFilled+1)/2) // new bucket counter
236           && (j< (lastBucketFilled+1)); // old bucket counter
237         i++,j+=2){
238       // For the sampledFunction type of metrics, the buckets hold the change
239       // in the sample value, so folding buckets with these delta sample
240       // values involves just summing the buckets together.
241       // For the eventCounter type of metrics (eg. timing style of metrics),
242       // the buckets are normalized, so we need to take the average
243       // of the buckets when folding.
244       // These two metric types will be unified when the visis are converted
245       // over.
246       if((!isnan(value[j])) && (!isnan(value[j+1]))){
247         if(unitstype == Sampled)
248           value[i] = value[j] + value[j+1];
249         else //unitstype == EventCounter
250           value[i] = (value[j] + value[j+1]) / 2.0f;
251
252         if(firstValidBucket == -1) {
253           firstValidBucket = i;
254         }
255       } else if(!isnan(value[j])) {
256         if(unitstype == Sampled)
257           value[i] = value[j];
258         else
259           value[i] = value[j] / 2.0f;
260
261         if(firstValidBucket == -1) {
262           firstValidBucket = i;
263         }
264       } else if(!isnan(value[j+1])) {
265         if(unitstype == Sampled)
266           value[i] = value[j+1];
267         else
268           value[i] = value[j+1] / 2.0f;
269
270         if(firstValidBucket == -1) {
271           firstValidBucket = i;
272         }
273       }
274       else{
275         value[i] = VISI_ERROR;
276       }
277     }
278     for(i=(lastBucketFilled+1)/2; i < size; i++){
279       value[i] = VISI_ERROR;
280     }
281
282     lastBucketFilled = ((lastBucketFilled+1)/2)-1;
283   }
284 }
285
286 void visi_GridCellHisto::Value(visi_sampleType *samples, 
287                                int firstBucket, int lastBucket,
288                                visi_unitsType unitstype) 
289
290   sampleVal_cerr << "Value2- unitstype: " 
291                  <<(unitstype==Sampled?"Sampled":"NotSampled")
292                  << ", firstBucket: " << firstBucket << ", lastBucket: "
293                  << lastBucket << "\n";
294   for(int i=firstBucket; i<=lastBucket; i++) {
295     if(unitstype == Sampled)
296       samples[i] = Value(i, unitstype);
297     else
298       samples[i] = value[i];
299   }
300 }
301
302 visi_sampleType visi_GridCellHisto::SumValue(visi_timeType width,
303                                              visi_unitsType unitstype) {
304   int i;
305   visi_sampleType sum;
306   
307   if(value != NULL){
308     for(sum=0.0,i=0; i< size; i++){
309       if(!isnan(value[i])){
310         sum += Value(i, unitstype);
311       }
312     }
313     sampleVal_cerr << "  numBuckets: " << size << "  sum: " << sum 
314                    << "  width: " << width << "  sum*width: " 
315                    << sum*width << "\n"; 
316     if(unitstype == Sampled)
317       return sum;
318     else
319       return sum*width;
320   }
321   else{
322     sampleVal_cerr << " value == NULL\n";
323     return(VISI_ERROR);
324   }
325 }
326
327 visi_sampleType visi_GridCellHisto::AggregateValue(visi_unitsType unitstype) {
328   int i,num;
329   visi_sampleType sum;
330   if(value != NULL){
331     for(sum=0.0,num=i=0; i< size; i++){
332       if(!isnan(value[i])){
333         sum += Value(i, unitstype);
334         num++;
335       }
336     }
337     
338     if(num != 0){
339       sampleVal_cerr << "  sum: " << sum << "  num: " << num 
340                      << "  sum/num: " << (sum/(1.0*num)) << "\n";
341       return(sum/(1.0f * num));
342     }
343     else{
344       return(VISI_ERROR);
345     }
346   }
347   else{
348     return(VISI_ERROR);
349   }
350 }
351
352
353 ///////////////////////////////////////////
354 //
355 // constructor for class GridHistoArray
356 //
357 visi_GridHistoArray::visi_GridHistoArray(int numElements){
358
359  if(numElements > 0){  
360    values = new visi_GridCellHisto[numElements];
361  }
362  size = numElements;
363
364 }
365
366
367 //
368 // destructor for class GridHistoArray
369 //
370 visi_GridHistoArray::~visi_GridHistoArray(){
371
372   delete[] values;
373 }
374
375 //
376 // evaluates to true if the grid cell indexed by i (foucus index)
377 // contains a histogram (is a valid metric/focus pair)
378 //
379 int visi_GridHistoArray::Valid(int i){
380
381   if ((i< 0) || (i>= size)){
382     return(VISI_ERROR_INT);  
383   }
384   return(values[i].Valid());
385
386 }
387
388
389 //
390 // invalidates the grid cell indexed by i 
391 //
392 int visi_GridHistoArray::Invalidate(int i){
393
394   if ((i< 0) || (i>= size)){
395     return(VISI_ERROR_INT);  
396   }
397   values[i].Invalidate();
398   return(VISI_OK);
399 }
400
401
402 //
403 // add new elements to the values array
404 //
405 int visi_GridHistoArray::AddNewResources(int howmany){
406
407 visi_GridCellHisto *temp = 0;
408
409   if(howmany > 0){
410     temp = values;
411     values = new visi_GridCellHisto[howmany + size];
412     for(int i = 0; i < size; i++){
413        if(values[i].AddNewValues(temp[i].GetValueRawData(),
414                                   temp[i].Size(),
415                                   temp[i].LastBucketFilled(),
416                                   temp[i].userdata,
417                                   temp[i].Valid(),
418                                   temp[i].Enabled()) != VISI_OK){
419          return(VISI_ERROR_INT);
420        }
421        temp[i].userdata = 0;
422     }
423     size += howmany;
424     
425   }
426   delete[] temp;
427   return(VISI_OK);
428
429 }
430
431
432 //
433 //  add new elements to the values array
434 //
435 int visi_GridHistoArray::AddNewValues(visi_GridCellHisto *rarray,int howmany){
436
437   values = rarray;
438   size   = howmany;
439   rarray = 0;
440   return(VISI_OK);
441
442 }
443
444 ///////////////////////////////////////////
445 //
446 // DataGrid constructor: creates metric and 
447 // resource lists and empty datagrid
448 //
449 visi_DataGrid::visi_DataGrid(int noMetrics,
450                              int noResources,
451                              Metric *metricList,
452                              Resource *resourceList,
453                              int noBins,
454                              visi_timeType width,
455                              visi_timeType startTime,
456                              int phaseHandle){
457 int i;
458
459   numMetrics   = noMetrics;
460   numResources = noResources;
461   metrics      = new Metric[noMetrics];
462   resources    = new Resource[noResources];
463
464   for(i = 0; i < noMetrics; i++){
465     metrics[i] = Metric(metricList[i].Units(),metricList[i].Name(),
466                       metricList[i].Identifier(),metricList[i].Aggregate(),
467                       metricList[i].UnitsType());
468   }
469   for(i = 0; i < noResources; i++){
470     resources[i] = Resource(resourceList[i].Name(),resourceList[i].Identifier());
471   }
472
473   data_values = new visi_GridHistoArray[noMetrics];
474   for (i = 0; i < noMetrics; i++){
475       visi_GridHistoArray *temp = new visi_GridHistoArray(noResources);
476       data_values[i] = *temp;
477       delete temp;
478   }
479   numBins  = noBins;
480   binWidth = width;
481   start_time = startTime;
482   phase_handle = phaseHandle;
483
484 }
485
486
487 //
488 // DataGrid constructor: creates metric and 
489 // resource lists and empty datagrid
490 //
491 visi_DataGrid::visi_DataGrid(int noMetrics,
492                              int noResources,
493                              visi_metricType *metricList,
494                              visi_resourceType *resourceList,
495                              int noBins,
496                              visi_timeType width,
497                              visi_timeType startTime,
498                              int phaseHandle){
499 int i;
500
501   numMetrics   = noMetrics;
502   numResources = noResources;
503   metrics      = new Metric[noMetrics];
504   resources    = new Resource[noResources];
505
506   for(i = 0; i < noMetrics; i++){
507     metrics[i] = Metric(metricList[i].units,metricList[i].name,
508                       metricList[i].Id,metricList[i].aggregate,
509                       metricList[i].unitstype);
510   }
511   for(i = 0; i < noResources; i++){
512     resources[i] = Resource(resourceList[i].name,resourceList[i].Id);
513   }
514   data_values = new visi_GridHistoArray[noMetrics];
515   for (i = 0; i < noMetrics; i++){
516       visi_GridHistoArray *temp = new visi_GridHistoArray(noResources);
517       data_values[i] = *temp;
518       delete temp;
519   }
520   numBins  = noBins;
521   binWidth = width;
522   start_time = startTime;
523   phase_handle = phaseHandle;
524
525 }
526
527
528
529 //
530 //  DataGrid destructor 
531 //
532 visi_DataGrid::~visi_DataGrid(){
533
534   delete[] resources;
535   delete[] metrics;
536   delete[] data_values;
537 }
538
539 const char *visi_DataGrid::GetMyPhaseName(){
540
541     if (phase_handle == -1) return ("Global");
542     if (phase_handle >= 0){
543         for(unsigned i = 0; i < phases.size(); i++){
544             if(phase_handle == (int)phases[i]->getPhaseHandle()){
545                 return phases[i]->getName();
546     }}}
547     return 0;
548 }
549
550 // 
551 // returns metric name for metric number i 
552 //
553 const char   *visi_DataGrid::MetricName(int i){
554   if((i < numMetrics) && (i>=0))
555     return(metrics[i].Name());
556   return(0);
557 }
558
559 // 
560 // returns metric units for metric number i 
561 //
562 const char *visi_DataGrid::MetricUnits(int i){
563
564   if((i < numMetrics) && (i>=0))
565     return(metrics[i].Units());
566   return(0);
567 }
568
569 const visi_unitsType visi_DataGrid::MetricUnitsType(int i) {
570   if((i < numMetrics) && (i>=0))
571     return(metrics[i].UnitsType());
572   return Sampled;
573 }
574
575 // 
576 // returns metric label for data values 
577 //
578 const char *visi_DataGrid::MetricLabel(int i){
579
580   if((i < numMetrics) && (i>=0)){
581     return(metrics[i].Label());
582   }
583   return(0);
584 }
585
586 // 
587 // returns metric label for AVE aggregation over data buckets 
588 //
589 const char *visi_DataGrid::MetricAveLabel(int i){
590
591   if((i < numMetrics) && (i>=0)) {
592     return(metrics[i].AveLabel());
593   }
594   return(0);
595 }
596
597 // 
598 // returns metric label for SUM aggregation over data buckets 
599 //
600 const char *visi_DataGrid::MetricSumLabel(int i){
601
602   if((i < numMetrics) && (i>=0)) {
603     return(metrics[i].SumLabel());
604   }
605   return(0);
606 }
607
608 // 
609 // returns resource name for resource number j 
610 //
611 const char     *visi_DataGrid::ResourceName(int j){
612
613   if((j < numResources) && (j>=0))
614     return(resources[j].Name());
615   return(0);
616 }
617
618
619 // 
620 //  returns fold method for metric i 
621 //
622 int  visi_DataGrid::FoldMethod(int i){
623
624   if((i < numMetrics) && (i >= 0))
625     return(metrics[i].Aggregate());
626   return(VISI_ERROR_INT);
627
628 }
629
630 // 
631 // returns metric identifier associated with metric number i 
632 //
633 u_int  visi_DataGrid::MetricId(int i,bool &error){
634
635   error = true;
636   if((i < numMetrics) && (i >= 0)){
637     error = false;
638     return (metrics[i].Identifier());
639   }
640   return(0);
641 }
642
643 // 
644 // returns resource identifier associated with resource number j 
645 //
646 u_int  visi_DataGrid::ResourceId(int j, bool &error){
647
648   error = true;
649   if((j < numResources) && (j >= 0)){
650     error = false;
651     return(resources[j].Identifier());
652   }
653   return(0);
654 }
655
656 //
657 // returns 1 if datagrid element indicated by metric#, resource#
658 // contains histogram values, otherwise returns false
659 //
660 int visi_DataGrid::Valid(int metric, 
661                          int resource){
662
663   if((metric < 0) || (metric >= numMetrics)){
664     return(VISI_ERROR_INT);
665   }
666   return(data_values[metric].Valid(resource));
667
668 }
669
670 //
671 // invalidates data_grid element indicated by metric#, resource#
672 // sets valid to 0 and frees histogram space 
673 //
674 int visi_DataGrid::Invalidate(int metric,
675                               int resource){
676
677   if((metric < 0) || (metric >= numMetrics)){
678     return(VISI_ERROR_INT);
679   }
680   return(data_values[metric].Invalidate(resource));
681
682 }
683
684
685 //
686 // adds a new set of resources to the data grid
687 //
688 int visi_DataGrid::AddNewResource(int howmany,visi_resourceType *rlist){
689
690 Resource *temp;
691 int i,ok;
692
693   // add new values to resource list
694   temp = resources;
695   resources = new Resource[numResources + howmany];
696
697   for(i = 0; i < numResources; i++){
698       resources[i] = Resource(temp[i].Name(),temp[i].Identifier());
699   }
700   for(i = numResources; i < (numResources + howmany); i++){
701       resources[i] = Resource(rlist[i-numResources].name,
702                           rlist[i-numResources].Id);
703   }
704
705   numResources += howmany;
706
707   // add space to data grid for new resources
708   for(i = 0; i < numMetrics; i++){
709       if((ok = data_values[i].AddNewResources(howmany)) != VISI_OK){
710           delete[] temp;
711           temp = 0;
712           return(ok); 
713       }
714   }
715
716   delete[] temp;
717   temp = 0;
718   return(VISI_OK);
719 }
720
721
722 //
723 //  adds a new set of resources to the data grid
724 //
725 int visi_DataGrid::AddNewMetrics(int howmany,visi_metricType *mlist){
726
727 visi_GridHistoArray *tempdata;
728 Metric *temp;
729 int i;
730
731   // add new values to metric list
732   temp = metrics;
733   metrics = new Metric[numMetrics + howmany];
734
735   for(i = 0; i < numMetrics; i++){
736     metrics[i] = Metric(temp[i].Units(),temp[i].Name(),
737                       temp[i].Identifier(),temp[i].Aggregate(),
738                       temp[i].UnitsType());
739   }
740   for(i = numMetrics; i < (numMetrics + howmany); i++){
741     metrics[i] = Metric(mlist[i-numMetrics].units, mlist[i-numMetrics].name,
742                        mlist[i-numMetrics].Id, mlist[i-numMetrics].aggregate,
743                        mlist[i-numMetrics].unitstype);
744   }
745
746
747   // add space to data grid for new metrics
748
749   tempdata = data_values;
750   data_values = new visi_GridHistoArray[numMetrics + howmany];
751
752   for(i=0; i < numMetrics; i++){
753     if(data_values[i].AddNewValues(tempdata[i].Value(),tempdata[i].Size())
754        != VISI_OK){
755        return(VISI_ERROR_INT); 
756     }
757   }
758
759   for(i=numMetrics; i < (numMetrics + howmany); i++){
760       visi_GridHistoArray *temp = new visi_GridHistoArray(numResources);
761       data_values[i] = *temp;
762       delete temp;
763   }
764
765   numMetrics += howmany;
766   tempdata = 0;
767   temp = 0;
768   return(VISI_OK);
769
770 }
771
772
773 //
774 //  returns 1 if metric with Id equal to test_id is in the data grid
775 //
776 int visi_DataGrid::MetricInGrid(u_int test_id){
777
778   for(int i = 0; i < numMetrics; i++){
779     if (test_id == metrics[i].Identifier()){
780       return(1);
781     }
782   }
783   return(0);
784 }
785
786
787 //
788 //  returns 1 if resource with Id equal to test_id is in the data grid
789 //
790 int visi_DataGrid::ResourceInGrid(u_int test_id){
791
792   for(int i = 0; i < numResources; i++){
793     if (test_id == resources[i].Identifier()){
794       return(1);
795     }
796   }
797   return(0);
798 }
799
800 int phaseCompare(const void *p1, const void *p2) {
801    const PhaseInfo *ph1 = *((const PhaseInfo **)p1);
802    const PhaseInfo *ph2 = *((const PhaseInfo **)p2);
803    return(ph1->getPhaseHandle() - ph2->getPhaseHandle());
804 }
805
806 void visi_DataGrid::AddNewPhase(int handle, visi_timeType start, visi_timeType end,
807                       visi_timeType width, string name){
808     PhaseInfo *p = new PhaseInfo(handle,start,end,width,name.string_of());
809     phases += p;
810     phases.sort(phaseCompare);
811
812 }
813