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