second part of sampling rate change
[dyninst.git] / paradyn / src / DMthread / DMpublic.C
1
2 /*
3  * dataManagerImpl.C - provide the interface methods for the dataManager thread
4  *   remote class.
5  *
6  * $Log: DMpublic.C,v $
7  * Revision 1.51  1995/11/03 00:05:25  newhall
8  * second part of sampling rate change
9  *
10  * Revision 1.50  1995/10/13  22:06:52  newhall
11  * Added code to change sampling rate as bucket width changes (this is not
12  * completely implemented in daemon code yet, so now it has no effect).
13  * Purify fixes.  Added phaseType parameter to sampleDataCallbackFunc
14  * Added 2 new DM interface routines: getResourceName, getResourceLabelName
15  *
16  * Revision 1.49  1995/09/18  18:22:12  newhall
17  * changes to avoid for-scope problem
18  *
19  * Revision 1.48  1995/09/05  16:24:16  newhall
20  * added DM interface routines for PC, added resourceList method functions
21  *
22  * Revision 1.47  1995/08/20  03:51:33  newhall
23  * *** empty log message ***
24  *
25  * Revision 1.46  1995/08/20 03:37:13  newhall
26  * changed parameters to DM_sequential_init
27  * added persistent data and persistent collection flags
28  *
29  * Revision 1.45  1995/08/18  22:06:55  mjrg
30  * Fixed dataManager::defineDaemon
31  *
32  * Revision 1.44  1995/08/11  21:50:33  newhall
33  * Removed DM kludge method function.  Added calls to metDoDaemon,
34  * metDoProcess and metDoTunable that were moved out of metMain
35  *
36  * Revision 1.43  1995/08/08  03:10:06  newhall
37  * bug fix to DMresourceListNameCompare
38  * changed newPerfData and sampleDataCallbackFunc definitions
39  *
40  * Revision 1.42  1995/08/01  02:11:18  newhall
41  * complete implementation of phase interface:
42  *   - additions and changes to DM interface functions
43  *   - changes to DM classes to support data collection at current or
44  *     global phase granularity
45  * added alphabetical ordering to foci name creation
46  *
47  * Revision 1.41  1995/07/06  01:52:53  newhall
48  * update for new version of Histogram library, removed compiler warnings
49  *
50  * Revision 1.40  1995/06/02  20:48:27  newhall
51  * * removed all pointers to datamanager class objects from datamanager
52  *    interface functions and from client threads, objects are now
53  *    refered to by handles or by passing copies of DM internal data
54  * * removed applicationContext class from datamanager
55  * * replaced List and HTable container classes with STL containers
56  * * removed global variables from datamanager
57  * * remove redundant lists of class objects from datamanager
58  * * some reorginization and clean-up of data manager classes
59  * * removed all stringPools and stringHandles
60  * * KLUDGE: there are PC friend members of DM classes that should be
61  *    removed when the PC is re-written
62  *
63  * Revision 1.38  1995/02/26  02:14:07  newhall
64  * added some of the phase interface support
65  *
66  * Revision 1.37  1995/02/16  19:10:44  markc
67  * Removed start slash from comments
68  *
69  * Revision 1.36  1995/02/16  08:16:42  markc
70  * Changed Bool to bool
71  * Changed igen-xdr functions to use string/vectors rather than char igen-arrays
72  *
73  * Revision 1.35  1995/01/26  17:58:23  jcargill
74  * Changed igen-generated include files to new naming convention; fixed
75  * some bugs compiling with gcc-2.6.3.
76  *
77  * Revision 1.34  1994/11/09  18:39:36  rbi
78  * the "Don't Blame Me" commit
79  *
80  * Revision 1.33  1994/11/07  08:24:37  jcargill
81  * Added ability to suppress search on children of a resource, rather than
82  * the resource itself.
83  *
84  * Revision 1.32  1994/11/04  16:30:41  rbi
85  * added getAvailableDaemons()
86  *
87  * Revision 1.31  1994/11/02  11:46:21  markc
88  * Changed shadowing nam.
89  *
90  * Revision 1.30  1994/09/30  19:17:47  rbi
91  * Abstraction interface change.
92  *
93  * Revision 1.29  1994/09/22  00:56:05  markc
94  * Added const to args to addExecutable()
95  *
96  * Revision 1.28  1994/08/22  15:59:07  markc
97  * Add interface calls to support daemon definitions.
98  *
99  * Revision 1.27  1994/08/11  02:17:42  newhall
100  * added dataManager interface routine destroyPerformanceStream
101  *
102  * Revision 1.26  1994/08/08  20:15:20  hollings
103  * added suppress instrumentation command.
104  *
105  * Revision 1.25  1994/08/05  16:03:59  hollings
106  * more consistant use of stringHandle vs. char *.
107  *
108  * Revision 1.24  1994/07/25  14:55:37  hollings
109  * added suppress resource option.
110  *
111  * Revision 1.23  1994/07/14  23:45:54  hollings
112  * added hybrid cost model.
113  *
114  * Revision 1.22  1994/07/07  03:29:35  markc
115  * Added interface function to start a paradyn daemon
116  *
117  * Revision 1.21  1994/07/02  01:43:12  markc
118  * Removed all uses of type aggregation from enableDataCollection.
119  * The metricInfo structure now contains the aggregation operator.
120  *
121  * Revision 1.20  1994/06/27  21:23:29  rbi
122  * Abstraction-specific resources and mapping info
123  *
124  * Revision 1.19  1994/06/17  22:08:00  hollings
125  * Added code to provide upcall for resource batch mode when a large number
126  * of resources is about to be added.
127  *
128  * Revision 1.18  1994/06/14  15:23:17  markc
129  * Added support for aggregation.
130  *
131  * Revision 1.17  1994/06/02  16:08:16  hollings
132  * fixed duplicate naming problem for printResources.
133  *
134  * Revision 1.16  1994/05/31  19:11:33  hollings
135  * Changes to permit direct access to resources and resourceLists.
136  *
137  * Revision 1.15  1994/05/10  03:57:38  hollings
138  * Changed data upcall to return array of buckets.
139  *
140  * Revision 1.14  1994/05/09  20:56:22  hollings
141  * added changeState callback.
142  *
143  * Revision 1.13  1994/04/21  23:24:27  hollings
144  * removed process name from calls to RPC_make_arg_list.
145  *
146  * Revision 1.12  1994/04/20  15:30:11  hollings
147  * Added error numbers.
148  * Added data manager function to get histogram buckets.
149  *
150  * Revision 1.11  1994/04/19  22:08:38  rbi
151  * Added getTotValue method to get non-normalized metric data.
152  *
153  * Revision 1.10  1994/04/18  22:28:32  hollings
154  * Changes to create a canonical form of a resource list.
155  *
156  * Revision 1.9  1994/04/06  21:26:41  markc
157  * Added "include <assert.h>"
158  *
159  * Revision 1.8  1994/04/01  20:45:05  hollings
160  * Added calls to query bucketWidth and max number of bins.
161  *
162  * Revision 1.7  1994/03/31  01:39:01  markc
163  * Added dataManager continue/pause Process.
164  *
165  * Revision 1.6  1994/03/20  01:49:49  markc
166  * Gave process structure a buffer to allow multiple writers.  Added support
167  * to register name of paradyn daemon.  Changed addProcess to return type int.
168  *
169  * Revision 1.5  1994/03/08  17:39:34  hollings
170  * Added foldCallback and getResourceListName.
171  *
172  * Revision 1.4  1994/02/24  04:36:32  markc
173  * Added an upcall to dyninstRPC.I to allow paradynd's to report information at
174  * startup.  Added a data member to the class that igen generates.
175  * Make depend differences due to new header files that igen produces.
176  * Added support to allow asynchronous starts of paradynd's.  The dataManager has
177  * an advertised port that new paradynd's can connect to.
178  *
179  * Revision 1.3  1994/02/08  17:20:29  hollings
180  * Fix to not core dump when parent is null.
181  *
182  * Revision 1.2  1994/02/03  23:26:59  hollings
183  * Changes to work with g++ version 2.5.2.
184  *
185  * Revision 1.1  1994/02/02  00:42:34  hollings
186  * Changes to the Data manager to reflect the file naming convention and
187  * to support the integration of the Performance Consultant.
188  *
189  * Revision 1.1  1994/01/28  01:34:18  hollings
190  * The initial version of the Data Management thread.
191  *
192  *
193  */
194 extern "C" {
195 #include <malloc.h>
196 }
197
198 #include <assert.h>
199 #include "dataManager.thread.h"
200 #include "dataManager.thread.SRVR.h"
201 #include "dataManager.thread.CLNT.h"
202 #include "dyninstRPC.xdr.CLNT.h"
203 #include "visi.xdr.h"
204 #include "util/h/sys.h"
205 #include "util/h/Vector.h"
206 #include "util/h/Dictionary.h"
207 #include "util/h/makenan.h"
208 #include "DMmetric.h"
209 #include "DMdaemon.h"
210 #include "DMresource.h"
211 #include "DMperfstream.h"
212 #include "DMphase.h"
213 #include "DMinclude.h"
214
215 // the argument list passed to paradynds
216 vector<string> paradynDaemon::args = 0;
217
218 void histDataCallBack(sampleValue *buckets,
219                       timeStamp start_time,
220                       int count,
221                       int first,
222                       void *arg)
223 {
224     metricInstance *mi = (metricInstance *) arg;
225     performanceStream *ps = 0;
226
227     if(start_time == 0.0) { 
228         // update global data
229         for(unsigned i=0; i < mi->global_users.size(); i++) {
230             ps = performanceStream::find(mi->global_users[i]); 
231             if(ps) {
232                 ps->callSampleFunc(mi->getHandle(), 
233                                    buckets, count, first,GlobalPhase);
234             }
235         }
236         // update curr. phase data if curr. phase started at time 0.0
237         if (phaseInfo::GetLastPhaseStart() == 0.0) {
238             for(unsigned i=0; i < mi->users.size(); i++) {
239                 ps = performanceStream::find(mi->users[i]); 
240                 if(ps) {
241                     ps->callSampleFunc(mi->getHandle(), 
242                                        buckets, count, first,CurrentPhase);
243                 }
244             }
245         }
246     }
247
248     else {  // update just curr. phase data
249         for(unsigned i=0; i < mi->users.size(); i++) {
250             ps = performanceStream::find(mi->users[i]); 
251             if(ps)
252                 ps->callSampleFunc(mi->getHandle(), 
253                                    buckets, count, first,CurrentPhase);
254         }
255     }
256
257     for(int i=first; i < count; i++){
258         if(buckets[i] < 0) printf("bucket %d : %f \n",i,buckets[i]);
259     }
260 }
261
262 //
263 // start_time specifies the phaseType (globalType starts at 0.0) 
264 //
265 void histFoldCallBack(timeStamp width, void *arg,timeStamp start_time)
266 {
267
268     // need to check if current phase also starts at 0.0
269     // if it does, then fold applies to both global and curr phase
270     if(start_time == 0.0){
271         timeStamp curr_start =  phaseInfo::GetLastPhaseStart(); 
272         if(curr_start == 0.0){
273             if(metricInstance::GetCurrWidth() != width) {
274                 metricInstance::SetCurrWidth(width);
275                 performanceStream::foldAll(width,CurrentPhase);
276                 if(metricInstance::numCurrHists()){  // change sampling rate
277                     newSampleRate(width);
278                 }
279             }
280             phaseInfo::setCurrentBucketWidth(width);
281         }
282         if(metricInstance::GetGlobalWidth() != width) {
283             metricInstance::SetGlobalWidth(width);
284             performanceStream::foldAll(width,GlobalPhase);
285             if(!metricInstance::numCurrHists()){  // change the sampling rate
286                 newSampleRate(width);
287             }
288         }
289     }
290     else {  // fold applies to current phase
291         if(metricInstance::GetCurrWidth() != width) {
292             metricInstance::SetCurrWidth(width);
293             performanceStream::foldAll(width,CurrentPhase);
294             newSampleRate(width); // change sampling rate
295         }
296         phaseInfo::setCurrentBucketWidth(width);
297     }
298 }
299
300
301 void dataManager::setResourceSearchSuppress(resourceHandle res, bool newValue)
302 {
303     resource *r = resource::handle_to_resource(res);
304     if(r)
305         r->setSuppress(newValue);
306 }
307
308 void dataManager::setResourceSearchChildrenSuppress(resourceHandle res, 
309                                                     bool newValue)
310 {
311     resource *r = resource::handle_to_resource(res);
312     if(r) r->setSuppressChildren(newValue);
313 }
314
315 void dataManager::setResourceInstSuppress(resourceHandle res, bool newValue)
316 {
317     resource *r = resource::handle_to_resource(res);
318     if (r) paradynDaemon::setInstSuppress(r, newValue);
319 }
320
321 bool dataManager::addDaemon(const char *machine,
322                             const char *login,
323                             const char *name)
324 {
325   // fix args so that if char * points to "" then it pts to NULL
326   string m = 0;
327   if(machine && strlen(machine))  m = machine;
328   string l = 0;
329   if(login && strlen(login)) l = login;
330   string n = 0;
331   if(!name) { 
332       char *temp = 0; 
333       if(!paradynDaemon::setDefaultArgs(temp))
334           return false;
335       n = temp;
336       delete temp;
337   }
338   else {
339       n = name;
340   }
341   return (paradynDaemon::getDaemon(m, l, n));
342 }
343
344 //
345 // define a new entry for the daemon dictionary
346 //
347 bool dataManager::defineDaemon(const char *command,
348                                const char *dir,
349                                const char *login,
350                                const char *name,
351                                const char *machine,
352                                const char *flavor)
353 {
354   if(!name || !command)
355       return false;
356   return (paradynDaemon::defineDaemon(command, dir, login, name, machine, flavor));
357 }
358
359
360 bool dataManager::addExecutable(const char *machine,
361                                 const char *login,
362                                 const char *name,
363                                 const char *dir,
364                                 const vector<string> *argv)
365 {
366     string m = machine;
367     string l = login;
368     string n = name;
369     string d = dir;
370     return(paradynDaemon::newExecutable(m, l, n, d, *argv));
371 }
372
373 bool dataManager::applicationDefined()
374 {
375     return(paradynDaemon::applicationDefined());
376 }
377
378 bool dataManager::startApplication()
379 {
380     return(paradynDaemon::startApplication());
381 }
382
383 bool dataManager::pauseApplication()
384 {
385     return(paradynDaemon::pauseAll());
386 }
387
388 bool dataManager::pauseProcess(int pid)
389 {
390     return(paradynDaemon::pauseProcess(pid));
391 }
392
393 bool dataManager::continueApplication()
394 {
395     return(paradynDaemon::continueAll());
396 }
397
398 bool dataManager::continueProcess(int pid)
399 {
400     return(paradynDaemon::continueProcess(pid));
401 }
402
403 bool dataManager::detachApplication(bool pause)
404 {
405    return(paradynDaemon::detachApplication(pause));
406 }
407
408 perfStreamHandle dataManager::createPerformanceStream(dataType dt,
409                                                       dataCallback dc,
410                                                       controlCallback cc)
411 {
412     int td;
413     performanceStream *ps;
414
415     td = getRequestingThread();
416     ps = new performanceStream(dt, dc, cc, td);
417     return(ps->Handle());
418     ps = 0;
419 }
420
421 int dataManager::destroyPerformanceStream(perfStreamHandle handle){
422
423     performanceStream *ps = performanceStream::find(handle);
424     if(!ps) return(0);
425     delete ps;
426     return(1);
427 }
428
429 vector<string> *dataManager::getAvailableMetrics()
430 {
431     return(metric::allMetricNames());
432 }
433
434 vector<met_name_id> *dataManager::getAvailableMetInfo()
435 {
436     return(metric::allMetricNamesIds());
437 }
438
439
440 metricHandle *dataManager::findMetric(const char *name)
441 {
442     string n = name;
443     const metricHandle *met = metric::find(n);
444     if(met){
445         metricHandle *ret = new metricHandle;
446         *ret = *met;
447         return(ret);
448     }
449     return 0;
450 }
451
452 vector<resourceHandle> *dataManager::getRootResources()
453 {
454     return(resource::rootResource->getChildren());
455 }
456
457 resourceHandle *dataManager::getRootResource()
458 {
459     resourceHandle *rh = new resourceHandle;
460     *rh = resource::rootResource->getHandle();
461     return(rh);
462 }
463
464 //
465 // called by DM enable routines
466 //
467 metricInstance *DMenableData(perfStreamHandle ps_handle,
468                              metricHandle m, 
469                              resourceListHandle rl,
470                              phaseType type,
471                              unsigned persistent_data, 
472                              unsigned persistent_collection)
473 {
474     // does this this metric/focus combination already exist? 
475      metricInstance *mi = metricInstance::find(m,rl);
476
477     if (!mi) {  // create new metricInstance
478         if(!(mi = new metricInstance(rl,m,phaseInfo::CurrentPhaseHandle()))) {
479             return 0;
480     }}
481     
482     bool newly_enabled = false;
483     if ( !(mi->isEnabled()) ){  // enable data collection for this MI
484         if (!(paradynDaemon::enableData(rl,m,mi))) { 
485             return 0;
486         }
487         newly_enabled = true;
488     }
489
490     metric *metricptr = metric::getMetric(m);
491
492     // update appropriate MI info. 
493     if (type == CurrentPhase) {
494          u_int old_current = mi->currUsersCount();
495          bool current_data = mi->isCurrHistogram();
496          mi->newCurrDataCollection(metricptr->getStyle(),
497                                    histDataCallBack,
498                                    histFoldCallBack);
499          mi->newGlobalDataCollection(metricptr->getStyle(),
500                                    histDataCallBack,
501                                    histFoldCallBack);
502          mi->addCurrentUser(ps_handle);
503
504          // set sample rate to match current phase hist. bucket width
505          if(!metricInstance::numCurrHists()){
506                 float rate = phaseInfo::GetLastBucketWidth();
507                 newSampleRate(rate);
508          }
509
510          // new active curr. histogram added if there are no previous
511          // curr. subscribers and either persistent_collection is clear
512          // or there was no curr. histogram prior to this
513          if((!old_current) 
514             && (mi->currUsersCount() == 1)
515             && ((!mi->isCollectionPersistent()) || (!current_data))){ 
516              metricInstance::incrNumCurrHists();
517          }
518          // new global histogram added if this metricInstance was just enabled
519          if(newly_enabled){ 
520              metricInstance::incrNumGlobalHists();
521          }
522     }
523     else {
524          mi->newGlobalDataCollection(metricptr->getStyle(),
525                                    histDataCallBack,
526                                    histFoldCallBack);
527          mi->addGlobalUser(ps_handle);
528
529          // if this is first global histogram enabled and there are no
530          // curr hists, then set sample rate to match global hist. bucket width
531          if(!metricInstance::numCurrHists()){
532             if(!metricInstance::numGlobalHists()){ 
533                 float rate = Histogram::getGlobalBucketWidth();
534                 newSampleRate(rate);
535          }}
536
537          // new global hist added: update count
538          if(newly_enabled){  // new active global histogram added
539              metricInstance::incrNumGlobalHists();
540          }
541     }
542
543     // update persistence flags:  the OR of new and previous values
544     if(persistent_data) {
545         mi->setPersistentData();
546     }
547     if(persistent_collection) {
548         mi->setPersistentCollection();
549     }
550
551 //    cout << "num global hists " << metricInstance::numGlobalHists() << endl;
552 //    cout << "num curr hists " << metricInstance::numCurrHists() << endl;
553     return mi;
554 }
555
556 metricInstInfo *dataManager::enableDataCollection(perfStreamHandle ps_handle,
557                                         const vector<resourceHandle> *focus, 
558                                         metricHandle m,
559                                         phaseType type,
560                                         unsigned persistent_data,
561                                         unsigned persistent_collection)
562 {
563     if(!focus || !focus->size()){
564         if(focus) 
565             printf("error in enableDataCollection size = %d\n",focus->size());
566         else
567             printf("error in enableDataCollection focus is NULL\n");
568         return 0;
569     } 
570     resourceListHandle rl = resourceList::getResourceList(*focus);
571
572     metricInstance *mi = DMenableData(ps_handle,m,rl,type,persistent_data,
573                                      persistent_collection);
574     if(!mi) return 0;
575     metricInstInfo *temp = new metricInstInfo;
576     assert(temp);
577     metric *metricptr = metric::getMetric(m);
578     assert(metricptr);
579     temp->mi_id = mi->getHandle();
580     temp->m_id = m;
581     temp->r_id = rl;
582     resourceList *rl_temp = resourceList::getFocus(rl);
583     temp->metric_name = metricptr->getName();
584     temp->metric_units = metricptr->getUnits();
585     temp->focus_name = rl_temp->getName();
586     return(temp);
587     temp = 0;
588 }
589
590 //
591 // same as other enableDataCollection routine, except takes focus handle
592 // argument and returns metricInstanceHandle on successful enable 
593 //
594 metricInstanceHandle *dataManager::enableDataCollection2(perfStreamHandle ps,
595                                                 resourceListHandle rlh,
596                                                 metricHandle mh,
597                                                 phaseType pType,
598                                                 unsigned persistent_data,
599                                                 unsigned persistent_collection){
600
601     metricInstance *mi = DMenableData(ps,mh,rlh,pType,persistent_data,
602                                       persistent_collection);
603     if(mi){
604         metricInstanceHandle *mi_h = new metricInstanceHandle;
605         *mi_h = mi->getHandle();
606         return(mi_h);
607     }
608     return 0;
609 }
610
611 // data is really disabled when there are no current or global users and
612 // when the persistent_collection flag is clear
613 // when persistent_data flag is clear:
614 // current histogram is destroyed when there are no curr users 
615 // global histogram is destroyed whern there are no curr or gloabl users
616 // clear active flag on archived histograms rather than deleting them
617 void dataManager::disableDataCollection(perfStreamHandle handle, 
618                                         metricInstanceHandle mh,
619                                         phaseType type)
620 {
621
622 //    cout << " in dataManager::disableDataCollection: mh = " << mh << endl;
623     metricInstance *mi = metricInstance::getMI(mh);
624     if (!mi) return;
625
626     // if this mi is not enabled then return
627     if(!mi->isEnabled()) return;
628
629     u_int num_curr_users = mi->currUsersCount();
630
631     // remove user from appropriate list
632     if (type == CurrentPhase) {
633         mi->removeCurrUser(handle); 
634     }
635     else {
636         mi->removeGlobalUser(handle);
637     }
638
639     if (mi->isCollectionPersistent()) {
640         // just remove handle from appropriate client list and return
641         return;
642     }
643
644     // really disable MI data collection?  
645     if (!(mi->currUsersCount())) {
646         u_int num_curr_hists = metricInstance::numCurrHists();
647         if (!(mi->isDataPersistent())){
648             // remove histogram
649             if(mi->deleteCurrHistogram()){
650                 assert(metricInstance::numCurrHists());
651                 metricInstance::decrNumCurrHists();
652             }
653         }
654         else {  // clear active flag on current phase histogram
655             if(mi->data) {
656                 mi->data->clearActive();
657                 mi->data->setFoldOnInactive();
658                 assert(metricInstance::numCurrHists());
659                 if(num_curr_users)
660                     metricInstance::decrNumCurrHists();
661         }}
662
663         if (!(mi->globalUsersCount())) {
664             mi->dataDisable();  // makes disable call to daemons
665             if (!(mi->isDataPersistent())){
666                 delete mi;      
667                 assert(metricInstance::numGlobalHists());
668                 metricInstance::decrNumGlobalHists();
669             }
670             else {
671                 if(mi->global_data) {
672                     mi->global_data->clearActive();
673                     mi->global_data->setFoldOnInactive();
674                     assert(metricInstance::numGlobalHists());
675                     metricInstance::decrNumGlobalHists();
676             }}
677         }
678
679         // if this was last curr histogram then set sampling rate to global
680         if((num_curr_hists) && 
681            (!metricInstance::numCurrHists()) &&  
682            (metricInstance::numGlobalHists())){
683
684             float rate = Histogram::getGlobalBucketWidth();
685             newSampleRate(rate);
686         }
687     }
688 //    cout << "num global hists " << metricInstance::numGlobalHists() << endl;
689 //    cout << "num curr hists " << metricInstance::numCurrHists() << endl;
690     return;
691 }
692
693 //
694 // This routine returns a list of foci which are the result of combining
695 // each child of resource rh with the remaining resources that make up rlh
696 // if the resource rh is a component of the focus rlh, otherwise it returns 0
697 //
698 vector<resourceListHandle> *dataManager::magnify(resourceHandle rh, 
699                                                  resourceListHandle rlh){
700
701     resourceList *rl = resourceList::getFocus(rlh);
702     if(rl){
703         return(rl->magnify(rh));
704     }
705     return 0;
706 }
707
708
709 //
710 // This routine returns a list of foci each of which is the result of combining
711 // a child of one of the resources with the remaining resource components of
712 // rlh, this routine returns 0 if no resource components of rlh have children
713 //
714 vector<resourceListHandle> *dataManager::magnify2(resourceListHandle rlh){
715     resourceList *rl = resourceList::getFocus(rlh);
716     if(rl){
717         (rl->magnify());
718     }
719     return 0;
720 }
721
722
723 //
724 // if resource rh is a decendent of a component of the focus, return a new
725 // focus consisting of rh replaced with it's corresponding entry in rlh,
726 // otherwise return the focus rlh
727 //
728 resourceListHandle *dataManager::constrain(resourceHandle rh,
729                                           resourceListHandle rlh){
730     resourceList *rl = resourceList::getFocus(rlh);
731     if (rl) {
732          resourceListHandle *return_handle = rl->constrain(rh);
733         if(return_handle){
734             return return_handle;
735         }
736     }
737     resourceListHandle *default_handle = new resourceListHandle;
738     *default_handle = rlh;
739     return default_handle;
740 }
741
742 //
743 // like constrain, except it returns 0 on failure
744 //
745 resourceListHandle *dataManager::morespecific(resourceHandle rh,
746                                               resourceListHandle rlh){
747     resourceList *rl = resourceList::getFocus(rlh);
748     if (rl) {
749         return(rl->constrain(rh));
750     }
751     return 0;
752 }
753
754 //
755 // returns true if seppressSearch is true for this focus
756 //
757 bool dataManager::isSuppressed(resourceListHandle rlh){
758
759     resourceList *rl = resourceList::getFocus(rlh);
760     if (rl) {
761         return(rl->isSuppressed());
762     }
763     return 0;
764 }
765
766 //
767 // returns the name for the focus associated with this MI
768 // returns 0 on error
769 //
770 const char *dataManager::getFocusNameFromMI(metricInstanceHandle mh){
771     metricInstance *mi = metricInstance::getMI(mh);
772     if(mi){ 
773         return resourceList::getName(mi->getFocusHandle()); 
774     }
775     return 0;
776 }
777
778 //
779 // setting and clearing persistentCollection or persistentData flags
780 // have no enable/disable side effects 
781 //
782 void dataManager::setPersistentCollection(metricInstanceHandle mh){
783     metricInstance *mi = metricInstance::getMI(mh);
784     if(!mi) return;
785     mi->setPersistentCollection();
786 }
787 void dataManager::clearPersistentCollection(metricInstanceHandle mh){
788     metricInstance *mi = metricInstance::getMI(mh);
789     if(!mi) return;
790     mi->clearPersistentCollection();
791 }
792 void dataManager::setPersistentData(metricInstanceHandle mh){
793     metricInstance *mi = metricInstance::getMI(mh);
794     if(!mi) return;
795     mi->setPersistentData();
796
797 }
798 void dataManager::clearPersistentData(metricInstanceHandle mh){
799     metricInstance *mi = metricInstance::getMI(mh);
800     if(!mi) return;
801     mi->clearPersistentData();
802 }
803
804 metricHandle *dataManager::getMetric(metricInstanceHandle mh)
805 {
806     metricInstance *mi = metricInstance::getMI(mh);
807     if(!mi) return 0;
808
809     metricHandle *handle = new metricHandle;
810     *handle = mi->getMetricHandle();
811     return(handle);
812 }
813
814 string *dataManager::getMetricNameFromMI(metricInstanceHandle mh)
815 {
816     metricInstance *mi = metricInstance::getMI(mh);
817     if(mi){ 
818         string *name = new string(metric::getName(mi->getMetricHandle()));
819         return(name);
820     }
821     return 0;
822 }
823
824 string *dataManager::getMetricName(metricHandle m)
825 {
826     string *name = new string(metric::getName(m));
827     if(name->string_of())
828         return(name);
829     return 0;
830 }
831
832 sampleValue dataManager::getMetricValue(metricInstanceHandle mh)
833 {
834     metricInstance *mi = metricInstance::getMI(mh);
835     if(mi) 
836         return(mi->getValue());
837     float ret = PARADYN_NaN;
838     return(ret);
839 }
840
841 sampleValue dataManager::getTotValue(metricInstanceHandle mh)
842 {
843     metricInstance *mi = metricInstance::getMI(mh);
844     if(mi) 
845         return(mi->getTotValue());
846     float ret = PARADYN_NaN;
847     return(ret);
848 }
849
850 // TODO: this should be removed...it doesn't have any effect on smapling rate 
851 void dataManager::setSampleRate(perfStreamHandle handle, timeStamp rate)
852 {
853     performanceStream *ps = performanceStream::find(handle);
854     if(ps)
855       ps->setSampleRate(rate);
856 }
857
858
859
860 //
861 // converts from a vector of resourceHandles to a resourceListHandle
862 //
863 resourceListHandle dataManager::getResourceList(const vector<resourceHandle> *h)
864 {
865   
866     resourceListHandle r = resourceList::getResourceList(*h);
867     return r;
868 }
869
870
871 //
872 // converts from a resourceListHandle to a vector of resourceHandles
873 //
874 vector<resourceHandle> *dataManager::getResourceHandles(resourceListHandle h)
875 {
876     return resourceList::getResourceHandles(h);
877 }
878
879 //
880 // converts from a resource name to a resourceHandle
881 //
882 resourceHandle *dataManager::findResource(const char *name){
883
884     resourceHandle *rl = new resourceHandle;
885     string r_name = name;
886     if(resource::string_to_handle(r_name,rl)){
887         return(rl);
888     }
889     return 0;
890 }
891
892 //
893 // returns name of resource (this is not a unique representation of 
894 // the name instead it is the unique name trunctated)
895 // so for "/Code/blah.c/foo" this routine will return "foo"
896 //
897 string *dataManager::getResourceLabelName(resourceHandle h){
898
899      const char *s = resource::getName(h);
900      if(s){
901          string *name = new string(s);
902          return(name);
903      }
904      return 0;
905 }
906
907 //
908 // returns full name of resource ie.  "/Code/blah.c/foo"
909 //
910 string *dataManager::getResourceName(resourceHandle h){
911
912      const char *s = resource::getFullName(h);
913      if(s){
914          string *name = new string(s);
915          return(name);
916      }
917      return 0;
918 }
919
920 //
921 // converts from a focus name to a resourceListHandle
922 //
923 resourceListHandle *dataManager::findResourceList(const char *name){
924
925     string n = name;
926     const resourceListHandle *temp = resourceList::find(n);
927     if(temp){
928         resourceListHandle *h = new resourceListHandle;
929         *h = *temp;
930         return(h);
931     }
932     return 0;
933 }
934
935
936 float dataManager::getPredictedDataCost(resourceListHandle rl_handle, 
937                                         metricHandle m_handle)
938 {
939     metric *m = metric::getMetric(m_handle);
940     if(m){
941         resourceList *rl = resourceList::getFocus(rl_handle);
942         if(rl){
943             return(paradynDaemon::predictedDataCost(rl, m));
944     } }
945     float ret = PARADYN_NaN;
946     return(ret);
947 }
948
949 float dataManager::getCurrentHybridCost() 
950 {
951     return(paradynDaemon::currentHybridCost());
952 }
953
954 // caller provides array of sampleValue to be filled
955 // returns number of buckets filled
956 int dataManager::getSampleValues(metricInstanceHandle mh,
957                                  sampleValue *buckets,
958                                  int numberOfBuckets,
959                                  int first,
960                                  phaseType phase)
961 {
962     metricInstance *mi = metricInstance::getMI(mh);
963     if(mi) 
964         return(mi->getSampleValues(buckets, numberOfBuckets, first, phase));
965     return(0); 
966 }
967
968
969 // fill the passed array of buckets with the archived histogram values
970 // of the passed metricInstance
971 // returns number of buckets filled
972 int dataManager::getArchiveValues(metricInstanceHandle mh,
973                      sampleValue *buckets,
974                      int numberOfBuckets,
975                      int first,
976                      phaseHandle phase_id){
977
978     metricInstance *mi = metricInstance::getMI(mh);
979     if(mi) 
980         return(mi->getArchiveValues(buckets, numberOfBuckets, first, phase_id));
981     return 0;
982 }
983
984
985 void dataManager::printResources()
986 {
987     printAllResources();
988 }
989
990 void dataManager::printStatus()
991 {
992     paradynDaemon::printStatus();
993 }
994
995 void dataManager::coreProcess(int pid)
996 {
997     paradynDaemon::dumpCore(pid);
998 }
999
1000 void dataManager::StartPhase(timeStamp start_Time, const char *name)
1001 {
1002     string n = name;
1003     phaseInfo::startPhase(start_Time,n);
1004 //    cout << "in dataManager::StartPhase " << endl;
1005     // change the sampling rate
1006     if(metricInstance::numCurrHists()){
1007        // set sampling rate to curr phase histogram bucket width 
1008        float rate = phaseInfo::GetLastBucketWidth();
1009        newSampleRate(rate);
1010     }
1011     else {
1012        // set sampling rate to global phase histogram bucket width 
1013        float rate = Histogram::getGlobalBucketWidth();
1014        newSampleRate(rate);
1015     }
1016 //    cout << "num global hists " << metricInstance::numGlobalHists() << endl;
1017 //    cout << "num curr hists " << metricInstance::numCurrHists() << endl;
1018
1019 }
1020
1021 vector<T_visi::phase_info> *dataManager::getAllPhaseInfo(){
1022     return(phaseInfo::GetAllPhaseInfo());
1023 }
1024
1025 //
1026 // Now for the upcalls.  We provide code that get called in the thread that
1027 //   requested the call back.
1028 //
1029 void dataManagerUser::newMetricDefined(metricInfoCallback cb,
1030                                   perfStreamHandle p_handle,
1031                                   const char *name,
1032                                   int style,
1033                                   int aggregate,
1034                                   const char *units,
1035                                   metricHandle handle)
1036 {
1037     
1038     (cb)(p_handle, name, style, aggregate, units, handle);
1039 }
1040
1041 void dataManagerUser::newResourceDefined(resourceInfoCallback cb,
1042                                          perfStreamHandle handle,
1043                                          resourceHandle parent,
1044                                          resourceHandle newResource,
1045                                          const char *name,
1046                                          const char *abstr)
1047 {
1048     (cb)(handle, parent, newResource, name, abstr);
1049 }
1050
1051 void dataManagerUser::changeResourceBatchMode(resourceBatchModeCallback cb,
1052                                          perfStreamHandle handle,
1053                                          batchMode mode)
1054 {
1055     (cb)(handle, mode);
1056 }
1057
1058 void dataManagerUser::histFold(histFoldCallback cb,
1059                                perfStreamHandle handle,
1060                                timeStamp width,
1061                                phaseType phase_type)
1062 {
1063     (cb)(handle, width, phase_type);
1064 }
1065
1066 void dataManagerUser::changeState(appStateChangeCallback cb,
1067                                   perfStreamHandle handle,
1068                                   appState state)
1069 {
1070     (cb)(handle, state);
1071 }
1072
1073 void dataManagerUser::newPerfData(sampleDataCallbackFunc func,
1074                              perfStreamHandle handle,
1075                              metricInstanceHandle mi,
1076                              int bucketNum,
1077                              sampleValue value,
1078                              phaseType type)
1079 {
1080     (func)(handle, mi, bucketNum, value, type);
1081 }
1082
1083 void dataManagerUser::newPhaseInfo(newPhaseCallback cb,
1084                                    perfStreamHandle handle,
1085                                    const char *name,
1086                                    phaseHandle phase,
1087                                    timeStamp begin,
1088                                    timeStamp end,
1089                                    float bucketwidth) {
1090
1091     (cb)(handle,name,phase,begin,end,bucketwidth);
1092 }
1093
1094
1095 T_dyninstRPC::metricInfo *dataManager::getMetricInfo(metricHandle m_handle) {
1096
1097     const T_dyninstRPC::metricInfo *met = metric::getInfo(m_handle);
1098     if(met){ 
1099         T_dyninstRPC::metricInfo *copy = new T_dyninstRPC::metricInfo;
1100         copy->style = met->style;
1101         copy->units = met->units;
1102         copy->name = met->name;
1103         copy->aggregate = met->aggregate;
1104         copy->handle = met->handle;
1105         return(copy);
1106     }
1107     return 0;
1108 }
1109
1110 #ifdef n_def
1111 resourceHandle dataManager::newResource(resourceHandle parent, 
1112                                         const char *newResource) {
1113     // rbi: kludge 
1114     // calls to this method should specify an abstraction,
1115     // but that involves a bunch of other changes that I don't want 
1116     // to make right now.
1117     // the kludge works because we know that all calls to this method 
1118     // are for BASE abstraction resources.  
1119
1120     // TEMP: until this routine is called with vector of strings for new res
1121     string res = resource::resources[parent]->getFullName();
1122     res += string("/");
1123     res += string(newResource);
1124     char *word = strdup(res.string_of());
1125     string next;
1126     vector<string> temp;
1127     unsigned j=1;
1128     for(unsigned i=1; i < res.length(); i++){
1129         if(word[i] == '/'){
1130             word[i] = '\0';
1131             next = &word[j];
1132             temp += next;
1133             j = i+1;
1134         }
1135     }
1136     next = &word[j];
1137     temp += next;
1138     string base = string("BASE");
1139     resourceHandle r = createResource(parent, temp, res, base);  
1140     paradynDaemon::tellDaemonsOfResource(res.string_of(),newResource);
1141     return(r);
1142 }
1143 #endif
1144
1145 resourceHandle dataManager::newResource(resourceHandle parent,
1146                                         const char *name)
1147 {
1148
1149     // rbi: kludge
1150     // calls to this method should specify an abstraction,
1151     // but that involves a bunch of other changes that I don't want
1152     // to make right now.
1153     // the kludge works because we know that all calls to this method
1154     // are for BASE abstraction resources.
1155     
1156     string abs = "BASE";
1157     resource *parent_res = resource::handle_to_resource(parent);
1158     vector<string> res_name = parent_res->getParts();
1159     res_name += name;
1160     resourceHandle child = createResource(res_name,abs);
1161     paradynDaemon::tellDaemonsOfResource(parent_res->getHandle(), 
1162                                          child, 
1163                                          name);
1164     return(child);
1165
1166 }
1167
1168 timeStamp dataManager::getGlobalBucketWidth()
1169 {
1170     return(Histogram::getGlobalBucketWidth());
1171 }
1172
1173 timeStamp dataManager::getCurrentBucketWidth()
1174 {
1175     return(phaseInfo::GetLastBucketWidth());
1176 }
1177
1178 timeStamp dataManager::getCurrentStartTime() 
1179 {
1180     return(phaseInfo::GetLastPhaseStart());
1181 }
1182
1183 u_int dataManager::getCurrentPhaseId() 
1184 {
1185     return(phaseInfo::CurrentPhaseHandle());
1186 }
1187
1188
1189
1190 int dataManager::getMaxBins()
1191 {
1192     return(Histogram::getNumBins());
1193 }
1194
1195 void dataManager::printDaemons()
1196 {
1197   paradynDaemon::printDaemons();
1198 }
1199
1200 vector<string> *dataManager::getAvailableDaemons()
1201 {
1202     return(paradynDaemon::getAvailableDaemons());
1203 }
1204