Added code to change sampling rate as bucket width changes (this is not
[dyninst.git] / paradyn / src / DMthread / DMmetric.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 extern "C" {
17 #include <malloc.h>
18 #include <stdio.h>
19 }
20 #include "DMmetric.h"
21
22 extern void histDataCallBack(sampleValue*, timeStamp, int, int, void*);
23 extern void histFoldCallBack(timeStamp, void*, timeStamp);
24
25 metric::metric(T_dyninstRPC::metricInfo i){
26
27     if(allMetrics.defines(i.name)) return;
28     info.style = i.style;
29     info.units = i.units;
30     info.name = i.name;
31     info.aggregate = i.aggregate;
32     info.handle = metrics.size();
33     metric *met = this;
34     allMetrics[i.name] = met;
35     metrics += met;
36 }
37
38 const T_dyninstRPC::metricInfo *metric::getInfo(metricHandle handle) { 
39    
40     if(handle < metrics.size()){
41         metric *met = metrics[handle];
42         return(met->getInfo());
43     }
44     else{
45         return 0 ;
46     }
47 }
48
49 const char *metric::getName(metricHandle handle){
50      if(handle < metrics.size()){
51         metric *met = metrics[handle];
52         return(met->info.name.string_of());
53      }
54      else{
55         return 0 ;
56      }
57 }
58
59 const metricHandle *metric::find(const string iName){ 
60      if(allMetrics.defines(iName)){
61         return(&(allMetrics[iName])->info.handle);
62      }
63      else{
64         return 0 ;
65      }
66 }
67
68 metric *metric::getMetric(metricHandle handle){ 
69      if(handle < metrics.size()){
70         return(metrics[handle]);
71      }
72      else{
73         return 0 ;
74      }
75 }
76
77 vector<string> *metric::allMetricNames(){
78
79     vector<string> *temp = new vector<string>;
80     string name;
81     for(unsigned i=0; i < metrics.size(); i++){
82         metric *met = metrics[i];
83         string name = met->getName();
84         *temp += name; 
85
86     }
87     return(temp);
88     temp = 0;
89 }
90
91 vector<met_name_id> *metric::allMetricNamesIds(){
92
93     vector<met_name_id> *temp = new vector<met_name_id>;
94     met_name_id next;
95     for(unsigned i=0; i < metrics.size(); i++){
96         metric *met = metrics[i];
97         next.name = met->getName();
98         next.id = met->getHandle();
99         *temp += next; 
100     }
101     return(temp);
102     temp = 0;
103 }
104
105 metricInstance::metricInstance(resourceListHandle rl, 
106                                metricHandle m,
107                                phaseHandle ph){
108     met = m;
109     focus = rl;
110     enabledTime = 0.0;
111     metric *mp = metric::getMetric(m);
112     sample.aggOp = mp->getAggregate();
113     data = 0;
114     global_data = 0;
115     persistent_data = 0;
116     persistent_collection = 0;
117     enabled = false;
118     metricInstance::curr_phase_id = ph;
119
120     // find an Id for this metricInstance
121     for(unsigned i=0; i < nextId.size(); i++){
122         if((!nextId[i])){
123             id = i;
124             nextId[i] = true;
125             allMetricInstances[id] = this;
126             return;
127     }}
128     // if not found, add a new element to the id array
129     id = nextId.size();
130     nextId += true;
131     assert(id < nextId.size());
132     allMetricInstances[id] = this;
133 }
134
135 metricInstance::~metricInstance() {
136     for(unsigned i=0; i < components.size(); i++){
137         delete (components[i]);    
138     }
139     for(unsigned j=0; j < parts.size(); j++){
140         delete (parts[j]);    
141     }
142     for(unsigned k=0; k < old_data.size(); k++){
143         delete (old_data[k]);    
144     }
145     if (data) delete(data);
146     if (global_data) delete(global_data);
147     nextId[id] = false;
148     // remove metricInstace from list of allMetricsInstances
149     allMetricInstances.undef(id);
150 }
151
152 int metricInstance::getArchiveValues(sampleValue *buckets,int numOfBuckets,
153                                     int first,phaseHandle phase_id){
154
155     // find histogram associated with phase_id
156     for(unsigned i = 0; i < old_data.size(); i++){
157         if((old_data[i])->phaseId == phase_id){
158             if((old_data[i])->data)
159                 return((old_data[i])->data->getBuckets(buckets,
160                                                        numOfBuckets,first));
161         }
162     }
163     return -1;
164 }
165
166 int metricInstance::getSampleValues(sampleValue *buckets,int numOfBuckets,
167                                     int first,phaseType phase){
168
169     if(phase == CurrentPhase){
170         if (!data) return (-1);
171         return(data->getBuckets(buckets, numOfBuckets, first));
172     }
173     else {
174         if (!global_data) return (-1);
175         return(global_data->getBuckets(buckets, numOfBuckets, first));
176     }
177
178 }
179
180 metricInstance *metricInstance::getMI(metricInstanceHandle mh){
181
182     if(allMetricInstances.defines(mh)){
183         return(allMetricInstances[mh]);
184     }
185     return 0;
186 }
187
188 // TODO: remove asserts
189 void metricInstance::dataDisable(){
190     
191     assert(!users.size());
192     assert(!global_users.size());
193     for(unsigned i=0; i < components.size(); i++){
194         delete (components[i]);  // this disables data collection  
195     }
196     components.resize(0);
197     // deleteing components deletes parts as well
198     // for(unsigned j=0; j < parts.size(); j++){
199     //   delete (parts[j]);    
200     // } 
201     parts.resize(0);
202     enabled = false;
203     // if data is persistent this must be cleared 
204     sample.firstSampleReceived = false;  
205     assert(!components.size());
206     assert(!parts.size());
207 }
208
209 void metricInstance::removeCurrUser(perfStreamHandle ps){
210
211     // remove ps from vector of users
212     unsigned size = users.size();
213     for(unsigned i=0; i < size; i++){
214         if(users[i] == ps){
215             users[i] = users[size-1];
216             users.resize(size-1);
217             assert(users.size() < size);
218             return;
219     } }
220 }
221
222 void metricInstance::removeGlobalUser(perfStreamHandle ps){
223
224     // remove ps from vector of users
225     unsigned size = global_users.size();
226     for(unsigned i=0; i < size; i++){
227         if(global_users[i] == ps){
228             global_users[i] = global_users[size-1];
229             global_users.resize(size-1);
230             assert(global_users.size() < size);
231             return;
232     } }
233 }
234
235 // returns true if histogram really was deleted
236 bool metricInstance::deleteCurrHistogram(){
237
238     // if curr histogram exists and ther are no users delete
239     if(!(users.size()) && data) {
240         delete data;
241         data = 0;
242         return true;
243     }
244     return false;
245 }
246
247 metricInstance *metricInstance::find(metricHandle mh, resourceListHandle rh){
248
249     
250     dictionary_hash_iter<metricInstanceHandle,metricInstance *> 
251                         allMI(allMetricInstances);
252     metricInstanceHandle handle;
253     metricInstance *mi;
254     while(allMI.next(handle,mi)){
255         if((mi->getMetricHandle() == mh) && (mi->getFocusHandle() == rh)){
256             return(mi);
257         }
258     }
259     return 0;
260 }
261
262 bool metricInstance::addComponent(component *new_comp){
263
264     paradynDaemon *new_daemon =  new_comp->getDaemon();
265     for (unsigned i=0; i < components.size(); i++){
266          if((components[i])->getDaemon() == new_daemon) return false;
267     }
268     components += new_comp;
269     return true;
270 }
271
272 bool metricInstance::addPart(sampleInfo *new_part){
273     
274     parts += new_part;
275     return true;
276 }
277
278 // stops currentPhase data collection for all metricInstances
279 void metricInstance::stopAllCurrentDataCollection(phaseHandle last_phase_id) {
280
281     dictionary_hash_iter<metricInstanceHandle,metricInstance *> 
282                         allMI(allMetricInstances);
283     metricInstanceHandle handle;
284     metricInstance *mi;
285  
286     vector<metricInstance *> remove_list;
287     allMI.reset();
288     while(allMI.next(handle,mi)){
289         remove_list += mi;
290     }
291      
292     assert(remove_list.size() == allMetricInstances.size());
293     for(unsigned i=0; i < remove_list.size(); i++){
294         mi = remove_list[i];
295         // remove all users from user list
296         mi->users.resize(0);
297         assert(!(mi->users.size()));
298
299         bool was_deleted = false;
300         // if persistent data archive curr histogram
301         if(mi->isDataPersistent()){
302             if (mi->data) {
303                 if(mi->data->isActive()) was_deleted = true;    
304                 mi->data->clearActive();
305                 mi->data->clearFoldOnInactive();
306                 ArchiveType *temp = new ArchiveType;
307                 temp->data = mi->data;
308                 temp->phaseId = last_phase_id; 
309                 mi->old_data += temp;
310                 mi->data = 0;
311                 temp = 0; 
312             }
313         }
314         else { // else delete curr histogram
315             was_deleted = mi->deleteCurrHistogram();
316         }
317
318
319         // if not persistent collection
320         if (!(mi->isCollectionPersistent())){
321             // really disable data collection 
322             if((mi->isEnabled()) && (!mi->globalUsersCount())) { 
323                 // disable MI data collection 
324                 mi->dataDisable();
325                 if(!(mi->isDataPersistent())){
326                     delete(mi);
327                 }
328                 metricInstance::decrNumGlobalHists();
329             }
330             if(was_deleted)
331                 metricInstance::decrNumCurrHists();
332         }
333         else { // else, create new curr histogram with empty curr users list
334             metric *m = metric::getMetric(mi->met);
335             mi->newCurrDataCollection(m->getStyle(),
336                                       histDataCallBack,
337                                       histFoldCallBack);
338         }
339     }
340 }
341
342
343 void metricInstance::addCurrentUser(perfStreamHandle p) {
344
345     for(unsigned i=0; i < users.size(); i++){
346         if(users[i] == p) return;
347     }
348     users += p;
349     assert(users.size());
350 }
351
352 void metricInstance::addGlobalUser(perfStreamHandle p) {
353
354     for(unsigned i=0; i < global_users.size(); i++){
355         if(global_users[i] == p) return;
356     }
357     global_users += p;
358     assert(global_users.size());
359 }
360
361 void metricInstance::newGlobalDataCollection(metricStyle style, 
362                                              dataCallBack dcb, 
363                                              foldCallBack fcb) {
364
365     // histogram has already been created
366     if (global_data) {
367         global_data->setActive();
368         global_data->clearFoldOnInactive();
369         return;  
370     }
371     // call constructor for start time 0.0 
372     global_data = new Histogram(style, dcb, fcb, this);
373 }
374
375 void metricInstance::newCurrDataCollection(metricStyle style, 
376                                            dataCallBack dcb, 
377                                            foldCallBack fcb) {
378
379     // histogram has already been created
380     if (data) {
381         data->setActive();
382         data->clearFoldOnInactive();
383         return;  
384     }
385     // create new histogram
386     timeStamp start_time = phaseInfo::GetLastPhaseStart();
387     if(start_time == 0.0) {
388         data = new Histogram(style, dcb, fcb, this);
389
390     }
391     else {
392         data = new Histogram(start_time, style, dcb, fcb, this);
393     }
394 }
395