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