Bug fix to assert failure that sometimes occured with the trace data stuff
[dyninst.git] / paradyn / src / DMthread / DMmetric.h
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
43 #ifndef dmmetric_H
44 #define dmmetric_H
45 #include "util/h/sys.h"
46 #include "util/h/hist.h"
47 #include "dataManager.thread.h"
48 #include "dataManager.thread.SRVR.h"
49 #include <string.h>
50 #include "paradyn/src/UIthread/Status.h"
51 #include <stdlib.h>
52 #include "util/h/Vector.h"
53 #include "util/h/Dictionary.h"
54 #include "util/h/String.h"
55 #include "util/h/aggregateSample.h"
56 #include "DMinclude.h"
57 #include "DMdaemon.h"
58 #include "paradyn/src/TCthread/tunableConst.h"
59
60 // trace data streams
61 typedef void (*dataCallBack2)(void *data,
62                              int length,
63                              void *userData);
64
65 class metricInstance;
66
67 // a part of an mi.
68 //
69 class component {
70     friend class metricInstance;
71     friend class paradynDaemon;
72     public:
73         component(paradynDaemon *d, int i, metricInstance *mi) {
74             daemon = d;
75             id = i;
76             // Is this add unique?
77             assert(i >= 0);
78             d->activeMids[(unsigned)id] = mi;
79             sample = 0;
80         }
81         ~component() {
82             daemon->disableDataCollection(id);
83             assert(id>=0);
84             daemon->disabledMids += (unsigned) id;
85             daemon->activeMids.undef((unsigned)id);
86         }
87         int getId(){return(id);}
88         paradynDaemon *getDaemon() { return(daemon); }
89
90     private:
91         //sampleInfo sample;
92         sampleInfo *sample;
93         paradynDaemon *daemon;
94         int id;
95 };
96
97
98 //
99 //  info about a metric in the system
100 //
101 class metric {
102     friend class dataManager;
103     friend class metricInstance;
104     friend class paradynDaemon;
105     friend void addMetric(T_dyninstRPC::metricInfo &info);
106     friend void histDataCallBack(sampleValue *, timeStamp , 
107                                  int , int , void *, bool);
108     friend void DMenableResponse(DM_enableType&,vector<bool>&);
109     public:
110         metric(T_dyninstRPC::metricInfo i); 
111         const T_dyninstRPC::metricInfo  *getInfo() { return(&info); }
112         const char *getName() { return((info.name.string_of()));}
113         const char *getUnits() { return((info.units.string_of()));}
114         dm_MetUnitsType  getUnitsType() { 
115             if(info.unitstype == 0) return(UnNormalized);
116             else if(info.unitstype == 1) return(Normalized);
117             else return(Sampled);}
118         metricHandle getHandle() { return(info.handle);}
119         metricStyle  getStyle() { return((metricStyle) info.style); }
120         int   getAggregate() { return info.aggregate;}
121
122         static unsigned  size(){return(metrics.size());}
123         static const T_dyninstRPC::metricInfo  *getInfo(metricHandle handle);
124         static const char *getName(metricHandle handle);
125         static const metricHandle  *find(const string name); 
126         static vector<string> *allMetricNames(bool all);
127         static vector<met_name_id> *allMetricNamesIds(bool all);
128         bool isDeveloperMode() { return info.developerMode; }
129
130     private:
131         static dictionary_hash<string, metric*> allMetrics;
132         static vector<metric*> metrics;  // indexed by metric id
133         T_dyninstRPC::metricInfo info;
134
135         static metric  *getMetric(metricHandle iName); 
136 };
137
138 struct archive_type {
139     Histogram *data;
140     phaseHandle phaseId;
141 };
142
143 typedef struct archive_type ArchiveType;
144
145 class metricInstance {
146     friend class dataManager;
147     friend class metric;
148     friend class paradynDaemon;
149     friend void histDataCallBack(sampleValue *buckets, timeStamp, int count, 
150                                  int first, void *arg, bool globalFlag);
151     friend void DMdoEnableData(perfStreamHandle,perfStreamHandle,vector<metricRLType> *,
152                                u_int,phaseType,phaseHandle,u_int,u_int,u_int);
153     friend void DMenableResponse(DM_enableType&,vector<bool>&);
154     friend void DMdisableRoutine(perfStreamHandle,perfStreamHandle,
155                                 metricInstanceHandle, phaseType);
156     // trace data streams
157     friend void traceDataCallBack(void *data, int length, void *arg);
158     public:
159         metricInstance(resourceListHandle rl, metricHandle m,phaseHandle ph);
160         ~metricInstance(); 
161         float getValue() {
162             float ret;
163             if (!data) abort();
164             ret = data->getValue();
165             ret /= enabledTime;
166             return(ret);
167         }
168         float getTotValue() {
169             float ret;
170
171             if (!data) abort();
172             ret = data->getValue();
173             return(ret);
174         }
175         int currUsersCount(){return(users.size());}
176         int globalUsersCount(){return(global_users.size());}
177         int getSampleValues(sampleValue*, int, int, phaseType);
178         int getArchiveValues(sampleValue*, int, int, phaseHandle);
179
180         static unsigned  mhash(const metricInstanceHandle &val){
181             return((unsigned)val);
182         }
183         metricInstanceHandle getHandle(){ return(id); }
184         metricHandle getMetricHandle(){ return(met); }
185         resourceListHandle getFocusHandle(){ return(focus); }
186         const char *getMetricName(){ return(metric::getName(met));}
187         const char *getFocusName(){return(resourceList::getName(focus));}
188         bool convertToIDList(vector<u_int> &rl){
189             return resourceList::convertToIDList(focus,rl);
190         }
191         void addInterval(timeStamp s,timeStamp e,sampleValue v,bool b){
192              if(data) 
193                  data->addInterval(s,e,v,b);
194              if(global_data)
195                  global_data->addInterval(s,e,v,b);
196         }
197         
198         // trace data streams
199         void sendTraceData(void *data, int length) {
200             if(traceFunc)
201                 (traceFunc)(data,length,this);
202         }
203         void assignTraceFunc(dataCallBack2 dcb) {
204             traceFunc = dcb;
205         }
206
207         bool isCurrHistogram(){if (data) return(true); else return(false);}
208         bool isGlobalHistogram(){ 
209                 if(global_data) return(true); else return(false);
210         }
211         bool isEnabled(){return(enabled);}
212         void setEnabled(){ enabled = true;}
213         void clearEnabled(){ enabled = false;}
214         bool isCurrentlyEnabling(){return(currently_enabling);}
215         void setCurrentlyEnabling(){ currently_enabling = true;}
216         void clearCurrentlyEnabling(){ currently_enabling = false;}
217
218         bool isCurrEnableOutstanding(){ return(currEnablesWaiting != 0);}
219         bool isGlobalEnableOutstanding(){return(globalEnablesWaiting != 0);}
220         void incrCurrWaiting(){ currEnablesWaiting++; }
221         void incrGlobalWaiting(){ globalEnablesWaiting++; }
222         void decrGlobalWaiting(){
223           if(globalEnablesWaiting) globalEnablesWaiting--;
224         }
225         void decrCurrWaiting(){
226           if(currEnablesWaiting) currEnablesWaiting--;
227         }
228
229         void setPersistentData(){ persistent_data = true; } 
230         void setPhasePersistentData(){ phase_persistent_data = true; } 
231         void setPersistentCollection(){ persistent_collection = true; } 
232         // returns true if the metric instance can be deleted 
233         bool clearPersistentData();  
234         void clearPhasePersistentData(){phase_persistent_data=false;}  
235         void clearPersistentCollection(){ persistent_collection = false; } 
236         bool isDataPersistent(){ return persistent_data;}
237         bool isPhaseDataPersistent(){ return phase_persistent_data;}
238         bool isCollectionPersistent(){ return persistent_collection;}
239         // returns false if componet was already on list (not added)
240         bool addComponent(component *new_comp);
241         bool removeComponent(paradynDaemon *daemon);
242         // bool addPart(sampleInfo *new_part);
243         // writes header info plus all values in histogram into file
244         void saveAllData (ofstream&, phaseType ph);
245
246         static timeStamp GetGlobalWidth(){return(global_bucket_width);}
247         static timeStamp GetCurrWidth(){return(curr_bucket_width);}
248         static void SetGlobalWidth(timeStamp nw){global_bucket_width = nw;}
249         static void SetCurrWidth(timeStamp nw){curr_bucket_width = nw;}
250         static phaseHandle GetCurrPhaseId(){return(curr_phase_id);}
251         static void setPhaseId(phaseHandle ph){curr_phase_id = ph;}
252         static void stopAllCurrentDataCollection(phaseHandle);
253         static u_int numGlobalHists(){ return(num_global_hists); }
254         static u_int numCurrHists(){ return(num_curr_hists); }
255         static void incrNumGlobalHists(){ num_global_hists++; }
256         static void incrNumCurrHists(){ num_curr_hists++; }
257         static void decrNumCurrHists(){ if(num_curr_hists) num_curr_hists--; }
258         static void decrNumGlobalHists(){ if(num_global_hists) num_global_hists--; }
259
260     private:
261         metricHandle met;
262         resourceListHandle focus;
263         float enabledTime;
264         bool enabled;    // set if data for mi is currently enabled
265         bool currently_enabling; // set if MI is curr. being enabled 
266         // to keep track of outstanding enable requests for this MI 
267         u_int currEnablesWaiting; 
268         u_int globalEnablesWaiting;
269
270         // one component for each daemon contributing to the metric value 
271         // each new component must be added to aggSample, and when
272         // all processes in that component exit, the component should be removed
273         // from aggSample.
274         // When all components have a value, aggSample will return an aggregated
275         // sample, that is bucketed by a histogram.
276         vector<component *> components; 
277         aggregateSample aggSample;
278
279         vector<perfStreamHandle> users;  // subscribers to curr. phase data
280         Histogram *data;                 // data corr. to curr. phase
281         vector<perfStreamHandle> global_users;  // subscribers to global data
282         Histogram *global_data;     // data corr. to global phase
283         vector<ArchiveType *> old_data;  // histograms of data from old phases 
284         
285         // if set, archive old data on disable and on new phase definition
286         bool persistent_data;  
287         // if set, don't disable on new phase definition
288         bool persistent_collection; 
289         // if set, don't delete data on disable, but on new phase clear flag 
290         bool phase_persistent_data;
291
292         unsigned id;
293         static dictionary_hash<metricInstanceHandle,metricInstance *> 
294             allMetricInstances;
295
296         static u_int next_id;
297         // info. about phase data
298         static phaseHandle curr_phase_id;  // TODO: set this on Startphase
299         static timeStamp global_bucket_width;  // updated on fold
300         static timeStamp curr_bucket_width;    // updated on fold
301
302         // these values only change on enable, disable, and phase start events
303         // they count the number of active histograms (active means that data
304         // is currently being collected for the histogram)
305         static u_int num_curr_hists; // num of curr. phase active histograms 
306         static u_int num_global_hists; // num of global phase active histograms 
307         
308         // trace data streams
309         vector<perfStreamHandle> trace_users;  // subscribers to trace data
310         dataCallBack2 traceFunc;
311
312         static metricInstance *getMI(metricInstanceHandle);
313         static metricInstance *find(metricHandle, resourceListHandle);
314         void newCurrDataCollection(metricStyle,dataCallBack,foldCallBack);
315         void newGlobalDataCollection(metricStyle,dataCallBack,foldCallBack);
316         void addCurrentUser(perfStreamHandle p); 
317         void addGlobalUser(perfStreamHandle p); 
318         // clear enabled flag and remove comps and parts
319         void dataDisable();  
320         void removeGlobalUser(perfStreamHandle);
321         void removeCurrUser(perfStreamHandle);
322         bool deleteCurrHistogram();
323
324         // trace data streams
325         void newTraceDataCollection(dataCallBack2);
326         void addTraceUser(perfStreamHandle p);
327         void removeTraceUser(perfStreamHandle);
328
329         resourceList *getresourceList(){return(resourceList::getFocus(focus));}
330 };
331 #endif