Added extra arg to enableDataCollection call. This is probably temporaray
[dyninst.git] / paradyn / src / UIthread / paradyn.tcl.C
1 /* paradyn.tcl.C
2
3    This code implements the tcl "paradyn" command.  See the README file for 
4    command descriptions.
5
6 */
7 /* $Log: paradyn.tcl.C,v $
8 /* Revision 1.17  1994/06/14 15:20:17  markc
9 /* Added extra arg to enableDataCollection call.  This is probably temporaray
10 /* since the data manager or configuration language will specify this info.
11 /*
12  * Revision 1.16  1994/05/31  19:11:49  hollings
13  * Changes to permit direct access to resources and resourceLists.
14  *
15  * Revision 1.15  1994/05/26  21:26:10  karavan
16  * corrected return value for Process command, to return TCL_ERROR if call
17  * to Add_Executable fails.
18  *
19  * Revision 1.14  1994/05/18  00:50:12  hollings
20  * added pid argument to core command.
21  *
22  * Revision 1.13  1994/05/12  23:34:16  hollings
23  * made path to paradyn.h relative.
24  *
25  * Revision 1.12  1994/05/09  20:59:27  hollings
26  * Changed paradyn shg start to clearSHG not init it.
27  *
28  * Revision 1.11  1994/05/06  06:40:06  karavan
29  * added shg start command
30  *
31  * Revision 1.10  1994/05/05  02:13:29  karavan
32  * moved CmdTabEntry definition from paradyn.tcl.C to UIglobals.h
33  *
34  * Revision 1.9  1994/05/02  20:38:31  hollings
35  * added search pause command and shg commands.
36  *
37  * Revision 1.8  1994/04/27  22:55:09  hollings
38  * Merged refine auto and search.
39  *
40  * Revision 1.7  1994/04/21  23:24:51  hollings
41  * added process command.
42  *
43  * Revision 1.6  1994/04/19  22:09:14  rbi
44  * Added new tcl commands and updated "enable" to return met id
45  *
46  * Revision 1.5  1994/04/10  19:12:12  newhall
47  * added visi command
48  *
49  * Revision 1.4  1994/04/09  18:37:20  hollings
50  * Fixed paramter to tunable constant to work.
51  *
52  * Revision 1.3  1994/04/06  22:40:15  markc
53  * Included assert.h.
54  *
55  * Revision 1.2  1994/04/05  23:49:25  rbi
56  * Fixed a bunch of tcl related stuff.
57  *
58  * Revision 1.1  1994/04/05  04:42:38  karavan
59  * initial version of UI thread code and tcl paradyn command
60  * */
61
62 #include <string.h>
63 extern "C" {
64  #include "tcl.h"
65 }
66
67 #include "../DMthread/DMresource.h"
68 #include "util/h/tunableConst.h"
69 #include "VM.CLNT.h"
70 #include "thread/h/thread.h"
71 #include "../pdMain/paradyn.h"
72 #include "UIglobals.h"
73 #include <assert.h>
74
75 extern Boolean detachApplication(applicationContext,Boolean);
76
77 int ParadynPauseCmd(ClientData clientData, 
78                 Tcl_Interp *interp, 
79                 int argc, 
80                 char *argv[])
81 {
82   dataMgr->pauseApplication(context);
83   return TCL_OK;
84 }
85
86
87 int ParadynContCmd(ClientData clientData, 
88                 Tcl_Interp *interp, 
89                 int argc, 
90                 char *argv[])
91 {
92   dataMgr->continueApplication(context);
93   return TCL_OK;
94 }
95
96 int ParadynStatusCmd(ClientData clientData, 
97                 Tcl_Interp *interp, 
98                 int argc, 
99                 char *argv[])
100 {
101   dataMgr->printStatus(context);
102   return TCL_OK;
103 }
104
105 int ParadynMetricsCmd(ClientData clientData, 
106                         Tcl_Interp *interp, 
107                         int argc, 
108                         char *argv[])
109 {
110   String_Array ml;
111   int i;
112   
113   ml = dataMgr->getAvailableMetrics(context);
114   for (i=0; i < ml.count; i++)
115     Tcl_AppendElement(interp, ml.data[i]);
116   return TCL_OK;
117 }
118
119 int ParadynResourcesCmd(ClientData clientData, 
120                         Tcl_Interp *interp, 
121                         int argc, 
122                         char *argv[])
123 {
124   resource *parent, *child;
125   resourceList *resList, *children;
126   int i, j, count, count2;
127   char *name;
128
129   parent = uim_rootRes;
130   resList = parent->getChildren();
131
132   count = resList->getCount();
133
134   for (i = 0; i < count; i++) {
135     parent = resList->getNth(i);
136
137     name = parent->getFullName();
138     Tcl_AppendElement(interp, name);
139
140     children = parent->getChildren();
141     count2 = children->getCount();
142
143     for (j = 0; j < count2; j++) {
144       child = children->getNth(j);
145       name = child->getFullName();
146       Tcl_AppendElement(interp, name);
147     }
148   }
149   return TCL_OK;
150 }
151
152 int ParadynListCmd(ClientData clientData, 
153                 Tcl_Interp *interp, 
154                 int argc, 
155                 char *argv[])
156 {
157   String_Array ml;
158   tunableConstant *c;
159   int i;
160   List<tunableConstant*> curr;
161
162   dataMgr->printResources();
163   ml = dataMgr->getAvailableMetrics(context);
164   for (i=0; i < ml.count; i++) {
165     printf("%s\n", ml.data[i]);
166   }
167   printf("CONSTANTS\n");
168   assert(tunableConstant::allConstants);
169   for (curr = *tunableConstant::allConstants; c = *curr; curr++) {
170     printf("%s = %f\n", c->getName(), c->getValue());
171   }
172   printf("bucketWidth %f\n", dataMgr->getCurrentBucketWidth());
173   printf("number of buckets = %d\n", dataMgr->getMaxBins());
174   return TCL_OK;
175 }
176
177 int ParadynDetachCmd (ClientData clientData,
178                       Tcl_Interp *interp,
179                       int argc,
180                       char *argv[])
181 {
182   dataMgr->detachApplication(context, True);
183   return TCL_OK;
184 }
185
186 int ParadynGetTotalCmd (ClientData clientData,
187                      Tcl_Interp *interp,
188                      int argc,
189                      char *argv[])
190 {
191   int met;
192   metricInstance *mi;
193   float val;
194
195   if (argc < 2) {
196     sprintf(interp->result, "USAGE: gettotal <metid>");
197     return TCL_ERROR;
198   }
199
200   if (Tcl_GetInt(interp, argv[1], &met) == TCL_ERROR) {
201     sprintf(interp->result, "Could not parse '%s' as an integer", argv[1]);
202     return TCL_ERROR;
203   }
204
205   mi = uim_enabled.find((void *) met);
206
207   if (!mi) {
208     sprintf (interp->result, "unable to find metric %d\n", met); 
209     return TCL_ERROR;
210   }
211   else {
212     val = dataMgr->getTotValue(mi);
213     sprintf(interp->result, "%g", val);
214   }
215
216   return TCL_OK;
217 }
218
219 int ParadynPrintCmd (ClientData clientData,
220                      Tcl_Interp *interp,
221                      int argc,
222                      char *argv[])
223 {
224   if (argv[1][0] == 'm') {   // print metric
225     float val;
226     metricInstance *mi;
227     int met;
228
229     if (Tcl_GetInt(interp, argv[2], &met) == TCL_ERROR) 
230       return TCL_ERROR;
231     mi = uim_enabled.find((void *) met);
232     if (!mi) {
233       sprintf (interp->result, "unable to find metric %d\n", met); 
234       return TCL_ERROR;
235      } else {
236       val = dataMgr->getMetricValue(mi);
237       printf ("metric %s, val = %f\n", 
238                dataMgr->getMetricName(dataMgr->getMetric(mi)), val);
239     }
240   } else if (argv[1][0] == 's') {     //print shg
241       perfConsult->printSHGList();
242   } else if (argv[1][0] == 'r') {     // print refine
243     int i;
244     searchHistoryNode *currentSHGNode;
245     SHNptr_Array currentRefinementList;
246         
247     currentSHGNode = perfConsult->getCurrentRefinement();
248     currentRefinementList = perfConsult-> getAllRefinements (currentSHGNode);
249
250     for (i=0; i < currentRefinementList.count; i++) {
251       currentSHGNode = currentRefinementList.data[i];
252       perfConsult->printSHGNode(currentSHGNode);
253       printf ("\n");
254     }
255   } else {
256     sprintf (interp->result, "Unknown option: paradyn print %s\n", argv[1]);
257     return TCL_ERROR;
258   }
259   return TCL_OK;
260 }
261
262 void processUsage()
263 {
264   printf("USAGE: process <-user user> <-machine machine> <-daemon> daemon> \"command\"\n");
265 }
266
267 /****
268  * Process
269  * Calls data manager service "addExecutable".  
270  * Returns TCL_OK or TCL_ERROR
271  */
272 int ParadynProcessCmd(ClientData clientData,
273                       Tcl_Interp *interp,
274                       int argc,
275                       char *argv[])
276 {
277     int i;
278     char *user = NULL;
279     char *machine = NULL;
280     char *paradynd = NULL;
281
282     for (i=1; i < argc-1; i++) {
283         if (!strcmp("-user", argv[i])) {
284             if (i+1 == argc) {
285                 processUsage();
286                 return TCL_ERROR;
287             }
288             user = argv[++i];
289         } else if (!strcmp("-machine", argv[i])) {
290             if (i+1 == argc) {
291                 processUsage();
292                 return TCL_ERROR;
293             }
294             machine = argv[++i];
295         } else if (!strcmp("-daemon", argv[i])) {
296             if (i+1 == argc) {
297                 processUsage();
298                 return TCL_ERROR;
299             }
300             paradynd = argv[++i];
301         } else if (argv[i][0] != '-') {
302             break;
303         } else {
304             processUsage();
305             return TCL_ERROR;
306         }
307     }
308
309     if (dataMgr->addExecutable(context, machine, user, paradynd, argc-i, 
310                                &argv[i]) < 0)
311       return TCL_ERROR;
312     else
313       return TCL_OK;
314   }
315
316 /*
317  * build_resource_list
318  * parses string of form <aaa/bbb/ccc,ddd/eee>, building up a 
319  * list of resources which is returned.
320  * returns NULL if any resource not defined or if argument does not 
321  * match regular expression for the string.
322  */
323 resourceList *build_resource_list (Tcl_Interp *interp, char *list)
324 {
325   char **argv1, **argv2;
326   int argc1, argc2;
327   resourceList *ret;
328   resource *parent, *child;
329   int res, el;
330
331   printf("list is %s\n",list);
332   ret = new resourceList;
333
334   if (Tcl_SplitList(interp, list, &argc1, &argv1) != TCL_OK) {
335     printf("Could not split list '%s'", list);
336     return NULL;
337   }
338
339   for (res = 0; res < argc1; res++) {
340     if (Tcl_SplitList(interp, argv1[res], &argc2, &argv2) != TCL_OK) {
341       printf("Could not split list '%s'", argv1[res]);
342       return NULL;
343     }
344     parent = uim_rootRes;
345     for (el = 0; el < argc2; el++) {
346       child = parent->findChild(argv2[el]);
347       if (!child) {
348         printf ("Resource %s (child of %s) not defined\n", argv2[el], 
349                 ((el == 0) ? "/" : argv2[el-1]) );
350         return NULL;
351       }
352       parent = child;
353     }
354     ret->add(child);
355     free(argv2);
356   }
357
358   free(argv1);
359   return ret;
360 }
361
362 //
363 //  disable  <metid>
364 //
365 int ParadynDisableCmd (ClientData clientData,
366                       Tcl_Interp *interp,
367                       int argc,
368                       char *argv[])
369 {
370   int met;
371   metricInstance *mi;
372
373   // Hold Everything!
374   dataMgr->pauseApplication (context);
375
376   if (argc < 2) {
377     sprintf(interp->result, "USAGE: disable <metid>");
378     return TCL_ERROR;
379   }
380
381   if (Tcl_GetInt(interp, argv[1], &met) == TCL_ERROR) {
382     sprintf(interp->result, "Could not parse '%s' as an integer", argv[1]);
383     return TCL_ERROR;
384   }
385
386   mi = uim_enabled.find((void *) met);
387
388   if (!mi) {
389     sprintf (interp->result, "unable to find metric %d\n", met); 
390     return TCL_ERROR;
391   }
392   else {
393     dataMgr->disableDataCollection (uim_defaultStream, mi);
394   }
395
396   return TCL_OK;
397 }
398
399 //
400 //  enable <metric> ?<resource>? ...
401 //    returns metric id
402 //
403 int ParadynEnableCmd (ClientData clientData,
404                       Tcl_Interp *interp,
405                       int argc,
406                       char *argv[])
407 {
408   metric *met;
409   char *name;
410   metricInstance *mi;
411   resourceList *resList;
412
413   // Hold Everything!
414   dataMgr->pauseApplication (context);
415
416   // Build a resource list from the tcl list
417   if (argc == 2)
418     resList = dataMgr->getRootResources();
419   else {
420     resList = build_resource_list (interp, argv[2]);
421     if (resList == NULL) {
422       sprintf (interp->result, "unable to build resource list for %s",
423                argv[2]);
424       return TCL_ERROR;
425     }
426   }
427
428   // DEBUG
429   name = resList->getCanonicalName();
430   printf ("enable request for %s\n", name);
431   delete(name);
432
433   // Now check the metric 
434   met = dataMgr->findMetric (context, argv[1]);
435   if (!met) {
436     sprintf (interp->result, "metric %s is not defined\n", argv[1]);
437     return TCL_ERROR;
438   }
439   else {
440     // Finally enable the data collection
441     // ... and specify aggregation style
442     mi = dataMgr->enableDataCollection (uim_defaultStream, resList,
443                                         met, Sum);
444     if (mi) {
445       uim_enabled.add(mi, (void *) uim_eid);
446       sprintf(interp->result,"%d",uim_eid);
447       printf ("metric %s, id = %d\n", dataMgr->getMetricName(met), uim_eid);
448       uim_eid++;
449     } else {
450       sprintf (interp->result, "can't enable metric %s for focus \n", argv[1]);
451       return TCL_ERROR;
452     }
453   }
454
455   return TCL_OK;
456 }
457
458 int ParadynCoreCmd (ClientData clientData,
459                     Tcl_Interp *interp,
460                     int argc,
461                     char *argv[])
462 {
463   int pid;
464
465   if (argc != 2) {
466       printf("usage: paradyn core <pid>\n");
467       return TCL_ERROR;
468   }
469   pid = atoi(argv[1]);
470   dataMgr->coreProcess(context, pid);
471   return TCL_OK;
472 }
473
474 int ParadynSetCmd (ClientData clientData,
475                     Tcl_Interp *interp,
476                     int argc,
477                     char *argv[])
478 {
479   char *sp;
480   tunableConstant *curr;
481   float f;
482   double d;
483
484   if (argc != 3) {
485     sprintf(interp->result,"USAGE: %s <variable> <value>", argv[0]);
486     return TCL_ERROR;
487   }
488   assert (tunableConstant::allConstants && tunableConstant::pool);
489   sp = tunableConstant::pool->findAndAdd(argv[1]);
490   curr = tunableConstant::allConstants->find(sp);
491
492   if (Tcl_GetDouble(interp, argv[2], &d) == TCL_ERROR)
493     return TCL_ERROR;
494   else 
495     f = (float) d;
496   if (curr) {
497     if (!curr->setValue(f)) {
498       sprintf (interp->result, "value %f not valid.\n", f);
499       return TCL_ERROR;
500     }
501     else {
502       printf ("%s set to %f\n", curr->getName(), curr->getValue());
503     }
504   } else {
505     sprintf (interp->result, "variable %s not defined\n", argv[1]);
506     return TCL_ERROR;
507   }
508   return TCL_OK;
509 }
510
511 int ParadynSearchCmd (ClientData clientData,
512                       Tcl_Interp *interp,
513                       int argc,
514                       char *argv[])
515 {
516   int limit;
517
518   if (argc == 2 && !strcmp(argv[1], "pause")) {
519     // stop the search
520     perfConsult->pauseSearch();
521     return TCL_OK;
522   } else if (argc == 3) {
523     if (Tcl_GetInt (interp, argv[2], &limit) == TCL_ERROR) 
524       return TCL_ERROR;
525   } else if (argc == 2) {
526     limit = -1;
527   } else {
528     printf("Usage: paradyn search <false|true> <int>\n");
529     printf("       paradyn search pause\n");
530     return TCL_ERROR;
531   }
532
533   if (dataMgr->applicationDefined(context) != True) {
534     sprintf (interp->result, "no program defined, can't search\n");
535     return TCL_ERROR;
536   } else {
537     perfConsult->search(True, limit);
538     return TCL_OK;
539   }
540 }
541
542
543 int ParadynSHGCmd (ClientData clientData,
544                    Tcl_Interp *interp,
545                    int argc,
546                    char *argv[])
547 {
548   int node;
549
550   if (argc == 2 && !strcmp(argv[1], "get")) {
551     node = perfConsult->getCurrentNodeId();
552     sprintf(interp->result, "%d", node);
553     return(TCL_OK);
554   } else if (argc == 2 && !strcmp(argv[1], "reset")) {
555     perfConsult->resetRefinement();
556     sprintf(interp->result, "1");
557     return(TCL_OK);
558   } else if (argc == 3 && 
559              !strcmp(argv[1], "set") && 
560              (node = atoi(argv[2]) > 0)) {
561     sprintf(interp->result, "%d", perfConsult->setCurrentSHGnode(node));
562     return TCL_OK;
563   } else if (argc == 2 && !strcmp(argv[1], "start")) {
564     perfConsult->clearSHG();
565     return TCL_OK;
566   } else {
567     printf("Usage: paradyn shg set <int>\n");
568     printf("       paradyn shg get\n");
569     printf("       paradyn shg reset\n");
570     printf("       paradyn shg start\n");
571     return TCL_ERROR;
572   }
573 }
574
575 int ParadynVisiCmd (ClientData clientData,
576                     Tcl_Interp *interp,
577                     int argc,
578                     char *argv[])
579 {
580   if (argv[1][0] == 'a') {
581     VM_activeVisiInfo_Array temp;
582     int i;
583
584     temp = vmMgr->VMActiveVisis();
585     for(i=0;i<temp.count;i++){
586       printf("active_info %d: name %s TypeId %d visiNum = %d\n",i,
587              temp.data[i].name,temp.data[i].visiTypeId,temp.data[i].visiNum);
588     }
589   }
590   else if (argv[1][0] == 'i') {
591       VM_visiInfo_Array visi_info;
592       int i;
593
594       visi_info = vmMgr->VMAvailableVisis();
595       for(i=0;i<visi_info.count;i++){
596         printf("visi %d: name %s visiTypeId %d\n",i,
597                visi_info.data[i].name,visi_info.data[i].visiTypeId);
598       }
599     } 
600   else if (argv[1][0] == 'c') {
601     int ok, i;
602     if (Tcl_GetInt (interp, argv[2], &i) != TCL_OK) 
603       return TCL_ERROR;
604     ok = vmMgr->VMCreateVisi(i); 
605   } 
606   else if (argv[1][0] == 'k') {
607     int i;
608     if (Tcl_GetInt (interp, argv[2], &i) != TCL_OK) 
609       return TCL_ERROR;
610     vmMgr->VMDestroyVisi(i);
611   } 
612   else {
613     sprintf(interp->result,
614             "USAGE: visi [kill <ivalue>|create <ivalue>|info|active<cmd>]");
615     return TCL_ERROR;
616   }
617   return TCL_OK;
618 }
619
620 static struct cmdTabEntry Pd_Cmds[] = {
621   {"pause", ParadynPauseCmd},
622   {"cont", ParadynContCmd},
623   {"status", ParadynStatusCmd},
624   {"list", ParadynListCmd},
625   {"detach", ParadynDetachCmd},
626   {"disable", ParadynDisableCmd},
627   {"enable", ParadynEnableCmd},
628   {"gettotal", ParadynGetTotalCmd},
629   {"metrics", ParadynMetricsCmd},
630   {"print", ParadynPrintCmd},
631   {"process", ParadynProcessCmd},
632   {"resources", ParadynResourcesCmd},
633   {"set", ParadynSetCmd},
634   {"core", ParadynCoreCmd},
635   {"search", ParadynSearchCmd},
636   {"shg", ParadynSHGCmd},
637   {"visi", ParadynVisiCmd},
638   {NULL, NULL}
639 };
640
641 int ParadynCmd(ClientData clientData, 
642                 Tcl_Interp *interp, 
643                 int argc, 
644                 char *argv[])
645 {
646   int i;
647
648   if (argc < 2) {
649     sprintf(interp->result,"USAGE: %s <cmd>", argv[0]);
650     return TCL_ERROR;
651   }
652
653   for (i = 0; Pd_Cmds[i].cmdname; i++) {
654     if (strcmp(Pd_Cmds[i].cmdname,argv[1]) == 0) {
655       return ((Pd_Cmds[i].func)(clientData,interp,argc-1,argv+1));      
656       }
657   }
658
659   sprintf(interp->result,"unknown paradyn cmd '%s'",argv[1]);
660   return TCL_ERROR;  
661 }
662
663 void initParadynCmd(Tcl_Interp *interp)
664 {
665   Tcl_CreateCommand(interp, "paradyn", ParadynCmd, (ClientData) NULL,
666                     (Tcl_CmdDeleteProc *) NULL);
667
668   return;
669 }