added way to request unique resource name.
[dyninst.git] / paradynd / src / main.C
1 /*
2  * Main loop for the default paradynd.
3  *
4  * $Log: main.C,v $
5  * Revision 1.12  1994/05/16 22:31:50  hollings
6  * added way to request unique resource name.
7  *
8  * Revision 1.11  1994/04/12  15:29:19  hollings
9  * Added samplingRate as a global set by an RPC call to control sampling
10  * rates.
11  *
12  * Revision 1.10  1994/04/09  18:34:54  hollings
13  * Changed {pause,continue}Application to {pause,continue}AllProceses, and
14  * made the RPC interfaces use these.  This makes the computation of pause
15  * Time correct.
16  *
17  * Revision 1.9  1994/04/06  21:35:39  markc
18  * Added correct machine name reporting.
19  *
20  * Revision 1.8  1994/04/01  20:06:41  hollings
21  * Added ability to start remote paradynd's
22  *
23  * Revision 1.7  1994/03/31  01:57:27  markc
24  * Added support for pauseProcess, continueProcess.  Added pvm interface code.
25  *
26  * Revision 1.6  1994/03/20  01:53:09  markc
27  * Added a buffer to each process structure to allow for multiple writers on the
28  * traceStream.  Replaced old inst-pvm.C.  Changed addProcess to return type
29  * int.
30  *
31  * Revision 1.5  1994/02/28  05:09:42  markc
32  * Added pvm hooks and ifdefs.
33  *
34  * Revision 1.4  1994/02/25  13:40:55  markc
35  * Added hooks for pvm support.
36  *
37  * Revision 1.3  1994/02/24  04:32:33  markc
38  * Changed header files to reflect igen changes.  main.C does not look at the number of command line arguments now.
39  *
40  * Revision 1.2  1994/02/01  18:46:52  hollings
41  * Changes for adding perfConsult thread.
42  *
43  * Revision 1.1  1994/01/27  20:31:27  hollings
44  * Iinital version of paradynd speaking dynRPC igend protocol.
45  *
46  *
47  */
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <sys/types.h>
51 #include <sys/time.h>
52 #include <assert.h>
53
54 #include "util/h/list.h"
55 #include "rtinst/h/rtinst.h"
56
57 #include "symtab.h"
58 #include "process.h"
59 #include "inst.h"
60 #include "instP.h"
61 #include "ast.h"
62 #include "util.h"
63 #include "dyninstP.h"
64 #include "metric.h"
65 #include "dyninstRPC.SRVR.h"
66
67 dynRPC *tp;
68 extern void controllerMainLoop();
69 extern void initLibraryFunctions();
70
71 #ifdef PARADYND_PVM
72 static dynRPC *init_pvm_code(char *argv[], char *machine, int family,
73                              int type, int well_known_socket, int flag);
74 static char machine_name[80];
75 #endif     
76
77 int ready;
78
79 // default to once a second.
80 float samplingRate = 1.0;
81
82 main(int argc, char *argv[])
83 {
84     int i, family, type, well_known_socket, flag;
85     char *machine;
86     metricList stuff;
87
88     initLibraryFunctions();
89
90     // process command line args passed in
91     // flag == 1 --> started by paradyn
92     assert (RPC_undo_arg_list (argc, argv, &machine, family, type,
93                        well_known_socket, flag) == 0);
94
95 #ifdef PARADYND_PVM
96     tp = init_pvm_code(argv, machine, family, type, well_known_socket, flag);
97 #else
98     if (!flag) {
99         int pid;
100
101
102         pid = fork();
103         if (pid == 0) {
104             close(0);
105             close(1);
106             close(2);
107
108             // setup socket
109             tp = new dynRPC(family, well_known_socket, type, machine, 
110                             NULL, NULL, 0);
111         } else if (pid > 0) {
112             printf("PARADYND %d\n", pid);
113             fflush(stdout);
114             _exit(-1);
115         } else {
116             fflush(stdout);
117             exit(-1);
118         }
119     } else {
120         // already setup on this FD.
121         tp = new dynRPC(0, NULL, NULL);
122     }
123 #endif
124
125     //
126     // tell client about our metrics.
127     //
128     stuff = getMetricList();
129     for (i=0; i < stuff->count; i++) {
130         tp->newMetricCallback(stuff->elements[i].info);
131         if (tp->callErr < 0) {
132             printf("RPC error\n");
133             exit(-1);
134         }
135     }
136
137     controllerMainLoop();
138 }
139
140 void dynRPC::addResource(String parent, String name)
141 {
142     resource pr;
143     extern resource findResource(char*);
144
145     pr = findResource(parent);
146     if (pr) (void) newResource(pr, NULL, name, 0.0, FALSE);
147 }
148
149 void dynRPC::coreProcess(int pid)
150 {
151     process *proc;
152
153     proc = processList.find((void *) pid);
154     dumpCore(proc);
155 }
156
157 String dynRPC::getStatus(int pid)
158 {
159     process *proc;
160     extern char *getProcessStatus(process *proc);
161     char ret[50];
162
163     proc = processList.find((void *) pid);
164
165     if (!proc) {
166         sprintf (ret, "PID:%d not found for getStatus\n", pid);
167         return (ret);
168     }
169     else
170         return(getProcessStatus(proc));
171 }
172
173 //
174 // NOTE: This version of getAvailableMetrics assumes that new metrics are
175 //   NOT added during execution.
176 //
177 metricInfo_Array dynRPC::getAvailableMetrics(void)
178 {
179     int i;
180     static int inited;
181     static metricInfo_Array metInfo;
182
183     if (!inited) {
184         metricList stuff;
185
186         stuff = getMetricList();
187         metInfo.count = stuff->count;
188         metInfo.data = (metricInfo*) calloc(sizeof(metricInfo), metInfo.count);
189         for (i=0; i < metInfo.count; i++) {
190             metInfo.data[i] = stuff->elements[i].info;
191         }
192         inited = 1;
193     }
194     return(metInfo);
195 }
196
197 double dynRPC::getPredictedDataCost(String_Array focusString, String metric)
198 {
199     metric m;
200     double val;
201     resourceList l;
202
203     m = findMetric(metric);
204     l = findFocus(focusString.count, focusString.data);
205     if (!l) return(0.0);
206     val = guessCost(l, m);
207
208     return(val);
209 }
210
211 void dynRPC::disableDataCollection(int mid)
212 {
213     metricInstance mi;
214     extern void printResourceList(resourceList);
215
216     printf("disable of %s for RL =", getMetricName(mi->met));
217     printResourceList(mi->resList);
218     printf("\n");
219
220     mi = allMIs.find((void *) mid);
221     mi->disable();
222     allMIs.remove(mi);
223     delete(mi);
224 }
225
226 int dynRPC::enableDataCollection(String_Array foucsString,String metric)
227 {
228     int id;
229     metric m;
230     resourceList l;
231
232     m = findMetric(metric);
233     l = findFocus(foucsString.count, foucsString.data);
234     if (!l) return(-1);
235     id = startCollecting(l, m);
236     return(id);
237 }
238
239 //
240 // not implemented yet.
241 //
242 void dynRPC::setSampleRate(double sampleInterval)
243 {
244     samplingRate = sampleInterval;
245     return;
246 }
247
248 Boolean dynRPC::detachProgram(int program,Boolean pause)
249 {
250     return(detachProcess(program, pause));
251 }
252
253 //
254 // Continue all processes
255 //
256 void dynRPC::continueApplication()
257 {
258     continueAllProcesses();
259 }
260
261 //
262 // Continue a process
263 //
264 void dynRPC::continueProgram(int program)
265 {
266     struct List<process *> curr;
267
268     for (curr = processList; *curr; curr++) {
269         if ((*curr)->pid == pid) break;
270     }
271     if (*curr)
272         continueProcess(*curr);
273     else
274         printf("Can't continue PID %d\n", program);
275 }
276
277 //
278 //  Stop all processes 
279 //
280 Boolean dynRPC::pauseApplication()
281 {
282     pauseAllProcesses();
283     return TRUE;
284 }
285
286 //
287 //  Stop a single process
288 //
289 Boolean dynRPC::pauseProgram(int program)
290 {
291     struct List<process *> curr;
292
293     for (curr = processList; *curr; curr++) {
294         if ((*curr)->pid == program) break;
295     }
296     if (!(*curr)) {
297         printf("Can't pause PID %d\n", program);
298         return FALSE;
299     }
300     pauseProcess(*curr);
301     flushPtrace();
302     return TRUE;
303 }
304
305 Boolean dynRPC::startProgram(int program)
306 {
307     continueAllProcesses();
308     return(False);
309 }
310
311 //
312 // This is not implemented yet.
313 //
314 Boolean dynRPC::attachProgram(int pid)
315 {
316     return(FALSE);
317 }
318
319 //
320 // start a new program for the tool.
321 //
322 int dynRPC::addExecutable(int argc,String_Array argv)
323 {
324     return(addProcess(argc, argv.data));
325 }
326
327 #ifdef PARADYND_PVM
328 dynRPC *
329 init_pvm_code(char *argv[], char *machine, int family,
330               int type, int well_known_socket, int flag)
331 {
332   dynRPC *temp;
333   extern int PDYN_initForPVM (char **, char *, int, int, int, int);
334
335   assert(PDYN_initForPVM (argv, machine, family, type, well_known_socket,
336                          flag) == 0);
337
338   assert(!gethostname(machine_name, 99));
339
340   // connect to paradyn
341   if (flag == 1)
342     temp = new dynRPC(0, NULL, NULL);
343   else
344     {
345       temp = new dynRPC(family, well_known_socket, type, machine, NULL, NULL);
346       temp->reportSelf (machine_name, argv[0], getpid());
347     }
348
349     return temp;
350 }
351
352 int
353 PDYND_report_to_paradyn (int pid, int argc, char **argv)
354 {
355     String_Array sa;
356
357     sa.count = argc;
358     sa.data = argv;
359     
360     assert(tp);
361     tp->newProgramCallbackFunc(pid, argc, sa, machine_name);
362     return 0;
363 }
364 #endif