severalResourceInfoCallback
[dyninst.git] / paradyn / src / DMthread / DMdaemon.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 #ifndef dmdaemon_H
43 #define dmdaemon_H
44
45 #include <string.h>
46 #include <stdlib.h>
47 #include "util/h/sys.h"
48 #include "util/h/Vector.h"
49 #include "util/h/Dictionary.h"
50 #include "util/h/String.h"
51 // trace data streams
52 #include "util/h/ByteArray.h"
53 #include "util/h/machineType.h"
54 #include "dataManager.thread.h"
55 #include "dataManager.thread.SRVR.h"
56 #include "dyninstRPC.xdr.CLNT.h"
57 #include "../UIthread/Status.h"
58 #include "DMinclude.h"
59 #include "DMresource.h"
60 #include "DMperfstream.h"
61
62 class metricInstance;
63 class metric;
64
65 //
66 // used to store info. about an enable request that has not received
67 // a response from the daemons yet
68 //
69 class DM_enableType{
70     friend class paradynDaemon;
71     friend class dynRPCUser;
72     friend class phaseInfo;
73     friend void DMenableResponse(DM_enableType&,vector<bool>&);
74  public: 
75     DM_enableType(perfStreamHandle ph,perfStreamHandle pth,phaseType t,phaseHandle ph_h,
76                   u_int rI,u_int cI,vector <metricInstance *> *r,
77                   vector <bool> *d,vector <bool> *e,u_int h,u_int pd,u_int pc,
78                   u_int ppd): ps_handle(ph),pt_handle(pth),ph_type(t), ph_handle(ph_h),
79                   request_id(rI), client_id(cI), request(r),done(d),enabled(e),
80                   how_many(h), persistent_data(pd), persistent_collection(pc),
81                   phase_persistent_data(ppd), not_all_done(0) { 
82                            for(u_int i=0; i < done->size(); i++){
83                                if(!(*done)[i]) not_all_done++;
84                            }
85     }
86     DM_enableType(){ ps_handle = 0; pt_handle = 0; ph_type = GlobalPhase; ph_handle= 0; 
87                 request_id = 0; client_id = 0; request = 0; done = 0; 
88                 enabled = 0; how_many =0; persistent_data = 0; 
89                 persistent_collection = 0; phase_persistent_data = 0; 
90     }
91     ~DM_enableType(){ delete request; delete done; delete enabled;}
92
93     metricInstance *findMI(metricInstanceHandle mh);
94     void setDone(metricInstanceHandle mh);
95
96     void updateAny(vector<metricInstance *> &completed_mis,
97                    vector<bool> successful);
98
99  private:
100     perfStreamHandle ps_handle;  // client thread
101     perfStreamHandle pt_handle;  // client thread for traces
102     phaseType ph_type;           // phase type assoc. with enable request
103     phaseHandle ph_handle;       // phase id, used if request is for curr phase
104     u_int request_id;            // DM assigned enable request identifier
105     u_int client_id;             // enable request id sent by calling thread
106     vector <metricInstance *> *request;  // MI's assoc. w/ enable request
107     vector <bool> *done;         // which elements are waiting for replies
108     vector <bool> *enabled;      // which elements were already enabled
109     u_int how_many;              // number of daemons 
110     u_int persistent_data;
111     u_int persistent_collection;
112     u_int phase_persistent_data;
113     u_int not_all_done;
114 };
115
116
117 // hash functions for dictionary members
118 inline unsigned uiHash(const unsigned &ptr) {
119   return (ptr >> 4);
120 }
121
122 // an entry in the daemon dictionary
123 // initial entries are obtained from Paradyn config files
124 class daemonEntry {
125
126 public:
127   daemonEntry (){ }
128   daemonEntry (const string &m, const string &c, const string &n,
129                const string &l, const string &, const string &f) : 
130                machine(m), command(c), name(n), login(l), dir(0), 
131                flavor(f) { }
132   ~daemonEntry() { }
133   bool setAll(const string &m, const string &c, const string &n,
134               const string &l, const string &d, const string &f);
135   void print();
136   const char *getCommand() const { return command.string_of();}
137   const char *getName() const { return name.string_of();}
138   const char *getLogin() const { return login.string_of();}
139   const char *getDir() const { return dir.string_of();}
140   const char *getMachine() const { return machine.string_of();}
141   const char *getFlavor() const { return flavor.string_of();}
142   const string &getNameString() const { return name;}
143   const string &getMachineString() const { return machine;}
144   const string &getCommandString() const { return command;}
145   const string &getFlavorString() const { return flavor;}
146
147 private:
148   string machine;
149   string command;
150   string name;
151   string login;
152   string dir;
153   string flavor;
154 };
155
156 //
157 // a binary running somewhere under the control of a paradynd*.
158 //
159 class executable {
160     public:
161         executable(unsigned id, const vector<string> &av, paradynDaemon *p)
162                  : pid(id), argv(av), controlPath(p) { exited = false; }
163         unsigned pid;
164         vector<string> argv;
165         paradynDaemon *controlPath;
166         bool exited; // true if this process has exited
167 };
168
169 //
170 // A handle to a running paradynd* somewhere.
171 //
172 // the machine field should have a value EXCEPT
173 // if the paradynDaemon has been started via the second
174 // constructor, and has not called reportSelf yet (pvm daemons)
175 // 
176 // method functions are for process and daemon control as well
177 // as for enabling and disabling data collection
178 //
179 // IMPORTANT NOTE: whenever the paradynDaemon constructor is used, it
180 // is the user's responsability to check whether the new object have been
181 // successfully created or not (i.e. by checking the public variable
182 // "bool errorConditionFound" in class dynRPCUser). In this way, we allow
183 // the user to take the appropriate error recovery actions instead of
184 // executing an "assert(0)" - naim
185 //
186 class paradynDaemon: public dynRPCUser {
187         friend class dynRPCUser;
188         friend class component;
189         friend class phaseInfo;
190         friend class dataManager;
191         friend void *DMmain(void* varg);
192         friend void newSampleRate(float rate);
193         friend bool metDoDaemon();
194         friend int dataManager::DM_post_thread_create_init(int tid);
195         friend void DMdoEnableData(perfStreamHandle,perfStreamHandle,vector<metricRLType>*,
196                                  u_int,phaseType,phaseHandle,u_int,u_int,u_int);
197     public:
198         paradynDaemon(const string &m, const string &u, const string &c,
199                       const string &n, const string &flav);
200         paradynDaemon(int f); // remaining values are set via a callback
201         ~paradynDaemon();
202         
203         // replace the igen provided error handler
204         virtual void handle_error();
205         virtual void firstSampleCallback(int program, double firstTime);
206         virtual void reportStatus(string);
207         virtual void processStatus(int pid, u_int stat);
208         virtual void reportSelf (string m, string p, int pd, string flav);
209         virtual void batchSampleDataCallbackFunc(int program,
210                                vector<T_dyninstRPC::batch_buffer_entry>);
211         // trace data streams
212         virtual void batchTraceDataCallbackFunc(int program,
213                                vector<T_dyninstRPC::trace_batch_buffer_entry>);
214
215         virtual void cpDataCallbackFunc(int, double, int, double, double);
216
217         virtual void endOfDataCollection(int);
218         virtual void resourceInfoCallback(unsigned int, vector<string> resource_name,
219                                           string abstr, u_int type);
220         virtual void severalResourceInfoCallback(vector<T_dyninstRPC::resourceInfoCallbackStruct>);
221         virtual void resourceBatchMode(bool onNow);  
222         void reportResources();
223
224         double getEarliestFirstTime() const { return earliestFirstTime;}
225         static void setEarliestFirstTime(double f){
226             if(!earliestFirstTime) earliestFirstTime = f;
227         }
228         void setTimeFactor(timeStamp timef) {
229             time_factor = timef;
230         }
231         timeStamp getTimeFactor() { return time_factor; }
232         timeStamp getAdjustedTime(timeStamp time) { return time + time_factor; }
233
234         // Not working -- would provide a read that didn't block other threads
235         static int read(const void *handle, char *buf, const int len);
236
237         // application and daemon definition functions
238         static bool defineDaemon(const char *command, const char *dir,
239                                  const char *login, const char *name,
240                                  const char *machine, const char *flavor);
241
242         static bool addRunningProgram(int pid, const vector<string> &paradynd_argv, 
243                                       paradynDaemon *daemon,
244                                       bool calledFromExec, bool isInitiallyRunning);
245            // start a new program; propagate all enabled metrics to it
246
247         static bool newExecutable(const string &machine, const string &login,
248                                   const string &name, const string &dir, 
249                                   const vector<string> &argv);
250            // launch new process
251
252         static bool attachStub(const string &machine, const string &user,
253                                const string &cmd, int pid,
254                                const string &daemonName,
255                                int afterAttach // 0 --> as is, 1 --> pause, 2 --> run
256                                );
257            // attach to an already-running process.
258            // cmd gives the full path to the executable, used just to parse the
259            // symbol table.
260            // the word Stub was appended to the name to avoid conflict with the
261            // igen call "attach"
262
263         static bool addDaemon(int new_fd);
264         static bool getDaemon (const string &machine, 
265                                const string &login, 
266                                const string &name);
267         static bool detachApplication(bool);
268         static void removeDaemon(paradynDaemon *d, bool informUser);
269
270         // application and daemon control functions
271         static bool startApplication();
272         static bool pauseProcess(unsigned pid);
273         static bool continueProcess(unsigned pid);
274         static bool pauseAll(); 
275         static bool continueAll();
276         static bool setInstSuppress(resource *, bool);
277         static void enableData(vector<metricInstance *> *miVec, 
278                                vector<bool> *done,
279                                vector<bool> *enabled,
280                                DM_enableType *new_entry,
281                                bool need_to_enable);
282
283         static void tellDaemonsOfResource(u_int parent,
284                                           u_int res,const char *name, u_int type);
285         // sets the name of the daemon to use
286         static bool setDefaultArgs(char *&name);
287
288         // debugging and daemon info. routines 
289         static void dumpCore(int pid);
290         // TODO: remove these
291         static void printStatus();
292         static void printDaemons();
293         static void printEntries();
294         static void printPrograms();
295         void print();
296
297         static bool applicationDefined(){return(programs.size() != 0);}
298         static vector<string> *getAvailableDaemons();
299         static paradynDaemon  *machineName2Daemon(const string &theMachName);
300            // returns the paradynDaemon w/ this machine name, NULL if not found.
301
302         static void getPredictedDataCostCall(perfStreamHandle,metricHandle,
303                                       resourceListHandle,resourceList*,metric*,
304                                       u_int);
305         static float currentSmoothObsCost();
306         const string &getDaemonMachineName() const {return machine;}
307
308     private:
309         bool   dead;    // has there been an error on the link.
310         string machine;
311         string login;
312         string command;
313         string name;
314         string flavor;
315         u_int id;
316
317         status_line *status;
318
319         timeStamp time_factor; // for adjusting the time to account for 
320                                // clock differences between daemons.
321
322         // all active metrics ids for this daemon.
323         dictionary_hash<unsigned, metricInstance*> activeMids;
324         vector<unsigned> disabledMids;
325
326         // used to hold responses to resourceInfoCallback
327         vector<u_int> newResourceTempIds;
328         vector<resourceHandle> newResourceHandles;
329         static u_int count;
330
331         static double earliestFirstTime;
332
333         // list of all possible daemons: currently one per unique name
334         static vector<daemonEntry*> allEntries; 
335         // list of all active programs
336         static vector<executable*>  programs;
337         // list of all active daemons: one for each unique name/machine pair 
338         static vector<paradynDaemon*>  allDaemons;
339         static unsigned procRunning; // how many processes are running or ready to run.
340         static vector<DM_enableType*> outstanding_enables;
341         static u_int next_enable_id;
342
343         // these args are passed to the paradynd when started
344         // for paradyndPVM these args contain the info to connect to the
345         // "well known" socket for new paradynd's
346         static vector<string> args;
347
348         // start a daemon on a machine, if one not currently running there
349         static paradynDaemon *getDaemonHelper (const string &machine,
350                                                const string &login,
351                                                const string &name);
352         static daemonEntry *findEntry (const string &machine, 
353                                        const string &name);
354
355         void propagateMetrics();
356
357 };
358 #endif