2 * Copyright (c) 1996 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
49 #include "thread/h/thread.h"
50 #include "paradyn/src/TCthread/tunableConst.h"
51 #include "dataManager.thread.SRVR.h"
52 #include "dyninstRPC.xdr.CLNT.h"
55 #include "DMperfstream.h"
56 #include "DMabstractions.h"
57 #include "paradyn/src/pdMain/paradyn.h"
58 #include "paradyn/src/UIthread/Status.h"
60 #include "util/h/Vector.h"
61 #include "util/h/Dictionary.h"
62 #include "util/h/String.h"
65 typedef vector<string> blahType;
67 // bool parse_metrics(string metric_file);
68 bool metMain(string &userFile);
70 // this has to be declared before baseAbstr, cmfAbstr, and rootResource
71 int dataManager::sock_fd;
72 int dataManager::socket;
73 dataManager *dataManager::dm = NULL;
75 dictionary_hash<string,abstraction*> abstraction::allAbstractions(string::hash);
76 abstraction *baseAbstr = new abstraction("BASE");
77 abstraction *cmfAbstr = new abstraction("CMF");
79 dictionary_hash<string,metric*> metric::allMetrics(string::hash);
80 dictionary_hash<metricInstanceHandle,metricInstance *>
81 metricInstance::allMetricInstances(metricInstance::mhash);
82 dictionary_hash<perfStreamHandle,performanceStream*>
83 performanceStream::allStreams(performanceStream::pshash);
84 dictionary_hash<string, resource*> resource::allResources(string::hash);
85 dictionary_hash<string,resourceList *> resourceList::allFoci(string::hash);
87 vector<resource*> resource::resources;
88 vector<string> resource::lib_constraints;
89 vector<metric*> metric::metrics;
90 vector<paradynDaemon*> paradynDaemon::allDaemons;
91 vector<daemonEntry*> paradynDaemon::allEntries;
92 vector<executable*> paradynDaemon::programs;
93 unsigned paradynDaemon::procRunning;
94 vector<resourceList *> resourceList::foci;
95 vector<phaseInfo *> phaseInfo::dm_phases;
96 u_int metricInstance::next_id = 1;
97 u_int performanceStream::next_id = 0;
98 vector<DM_enableType*> paradynDaemon::outstanding_enables;
99 u_int paradynDaemon::next_enable_id = 0;
100 u_int paradynDaemon::count = 0;
102 resource *resource::rootResource = new resource();
103 timeStamp metricInstance::curr_bucket_width;
104 timeStamp metricInstance::global_bucket_width;
105 phaseHandle metricInstance::curr_phase_id;
106 u_int metricInstance::num_curr_hists = 0;
107 u_int metricInstance::num_global_hists = 0;
109 double paradynDaemon::earliestFirstTime = 0;
110 void newSampleRate(float rate);
112 extern void histDataCallBack(sampleValue*, timeStamp, int, int, void*, bool);
113 extern void histFoldCallBack(timeStamp, void*, bool);
116 // IO from application processes.
118 void dynRPCUser::applicationIO(int,int,string data)
121 // NOTE: this fixes a purify error with the commented out code (a memory
122 // segment error occurs occasionally with the line "cout << rest << endl")
123 // this is problably not the best fix, but I can't figure out why
124 // the error is occuring (rest is always '\0' terminated when this
125 // error occurs)---tn
126 fprintf(stdout,data.string_of());
132 // extra should really be per process.
135 rest = P_strdup(data.string_of());
138 ptr = P_strchr(rest, '\n');
142 printf("pid %d:", pid);
144 printf("paradynd: ");
146 if (extra.length()) {
148 extra = (char*) NULL;
150 cout << rest << endl;
153 ptr = P_strchr(rest, '\n');
164 extern status_line *DMstatus;
166 void dynRPCUser::resourceBatchMode(bool onNow)
168 printf("error calling virtual func: dynRPCUser::resourceBatchMode\n");
172 // upcalls from remote process.
174 void dynRPCUser::resourceInfoCallback(int,
175 vector<string> resource_name,
176 string abstr, u_int type) {
178 printf("error calling virtual func: dynRPCUser::resourceInfoCallback\n");
182 void dynRPCUser::mappingInfoCallback(int,
188 AMnewMapping(abstraction.string_of(),type.string_of(),key.string_of(),
194 uniqueName(stringHandle base) { name = base; nextId = 0; }
200 // handles a completed enable response: updates metricInstance state
201 // and send the calling thread the response
203 void DMenableResponse(DM_enableType &enable,vector<bool> &successful){
206 vector<metricInstance *> &mis = (*enable.request);
207 assert(successful.size() == mis.size());
208 vector<metricInstInfo> *response = new vector<metricInstInfo>(mis.size());
210 // update MI state and response vector
211 for(u_int i=0; i < mis.size(); i++){
212 if(mis[i] && successful[i]){ // this MI could be enabled
213 mis[i]->setEnabled();
214 metric *metricptr = metric::getMetric(mis[i]->getMetricHandle());
217 if(enable.ph_type == CurrentPhase){
218 u_int old_current = mis[i]->currUsersCount();
219 bool current_data = mis[i]->isCurrHistogram();
220 mis[i]->newCurrDataCollection(metricptr->getStyle(),
223 mis[i]->newGlobalDataCollection(metricptr->getStyle(),
226 mis[i]->addCurrentUser(enable.ps_handle);
227 // set sample rate to match current phase hist. bucket width
228 if(!metricInstance::numCurrHists()){
229 float rate = phaseInfo::GetLastBucketWidth();
232 // new active curr. histogram added if there are no previous
233 // curr. subscribers and either persistent_collection is clear
234 // or there was no curr. histogram prior to this
236 && (mis[i]->currUsersCount() == 1) &&
237 (!(mis[i]->isCollectionPersistent()) || (!current_data))){
238 metricInstance::incrNumCurrHists();
240 // new global histogram if this metricInstance was just enabled
241 if(!((*enable.enabled)[i])){
242 metricInstance::incrNumGlobalHists();
245 else { // this is a global phase enable
246 mis[i]->newGlobalDataCollection(metricptr->getStyle(),
249 mis[i]->addGlobalUser(enable.ps_handle);
251 // if this is first global histogram enabled and there are no
252 // curr hists, then set sample rate to global bucket width
253 if(!metricInstance::numCurrHists()){
254 if(!metricInstance::numGlobalHists()){
255 float rate = Histogram::getGlobalBucketWidth();
258 // new global hist added: update count
259 if(!((*enable.enabled)[i])){
260 metricInstance::incrNumGlobalHists();
263 // update response vector
264 (*response)[i].successfully_enabled = true;
265 (*response)[i].mi_id = mis[i]->getHandle();
266 (*response)[i].m_id = mis[i]->getMetricHandle();
267 (*response)[i].r_id = mis[i]->getFocusHandle();
268 (*response)[i].metric_name = mis[i]->getMetricName();
269 (*response)[i].focus_name = mis[i]->getFocusName();
270 (*response)[i].metric_units = metricptr->getUnits();
271 (*response)[i].units_type = metricptr->getUnitsType();
273 // update the persistence flags: the OR of new & previous values
274 if(enable.persistent_data){
275 mis[i]->setPersistentData();
277 if(enable.persistent_collection){
278 mis[i]->setPersistentCollection();
280 if(enable.phase_persistent_data){
281 mis[i]->setPhasePersistentData();
285 cout << "mis enabled but no metric handle: "
286 << mis[i]->getMetricHandle() << endl;
290 else { // was not successfully enabled
291 (*response)[i].successfully_enabled = false;
292 (*response)[i].mi_id = mis[i]->getHandle();
293 (*response)[i].m_id = mis[i]->getMetricHandle();
294 (*response)[i].r_id = mis[i]->getFocusHandle();
295 (*response)[i].metric_name = mis[i]->getMetricName();
296 (*response)[i].focus_name = mis[i]->getFocusName();
300 // (*response)[i].mi_id = mis[i]->getHandle();
301 // (*response)[i].m_id = mis[i]->getMetricHandle();
302 // (*response)[i].r_id = mis[i]->getFocusHandle();
303 // (*response)[i].metric_name = mis[i]->getMetricName();
304 // (*response)[i].focus_name = mis[i]->getFocusName();
308 // make response call
309 dictionary_hash_iter<perfStreamHandle,performanceStream*>
310 allS(performanceStream::allStreams);
311 perfStreamHandle h; performanceStream *ps;
312 while(allS.next(h,ps)){
313 if(h == (perfStreamHandle)(enable.ps_handle)){
314 ps->callDataEnableFunc(response,enable.client_id);
321 // handle an enable response from a daemon. If all daemons have responded
322 // then make response callback to calling thread, and check the outstanding
323 // enables list to see if this enable response satisfies any waiting requests.
324 // and enable for an MI is successful if its done entry is true and if its
327 void dynRPCUser::enableDataCallback(u_int daemon_id,
328 vector<int> return_id,
329 vector<u_int> mi_ids,
332 // find element in outstanding_enables corr. to request_id
334 DM_enableType *request_entry = 0;
335 for(u_int i=0; i < paradynDaemon::outstanding_enables.size(); i++){
336 if((paradynDaemon::outstanding_enables[i])->request_id == request_id){
338 request_entry = paradynDaemon::outstanding_enables[i];
343 // a request entry can be removed if a new phase event occurs
344 // between the enable request and response, so ignore the response
347 assert(daemon_id < paradynDaemon::allDaemons.size());
348 paradynDaemon *pd = paradynDaemon::allDaemons[daemon_id];
350 // for each mi in request update mi's components with new daemon if
351 // it was successfully enabled
352 assert(mi_ids.size() == return_id.size());
353 for(u_int j=0; j< return_id.size(); j++){
354 if(return_id[j] != -1){
355 metricInstanceHandle mh = mi_ids[j];
356 metricInstance *mi = request_entry->findMI(mh);
358 component *comp = new component(pd,return_id[j], mi);
360 aflag=(mi->addComponent(comp));
362 // if at least one daemon could enable, update done and enabled
363 request_entry->setDone(mh);
366 // update count of outstanding daemon responses
367 assert(request_entry->how_many);
368 request_entry->how_many--;
370 // all daemons have responded to enable request, send result to caller
371 if(!request_entry->how_many) {
372 vector<bool> successful( request_entry->request->size());
373 for(u_int k=0; k < request_entry->request->size(); k++){
374 // if MI is 0 or if done is false
375 if(!((*(request_entry->done))[k])
376 || !((*(request_entry->request))[k])){
377 successful[k] = false;
380 successful[k] = true;
383 // if all daemons have responded update state for request and send
385 // a successful enable has both the enabled flag set and an mi*
387 // clear currentlyEnabling flag and decrement the count of
388 // waiting enables for all MI's
389 for(u_int i1=0; i1 < request_entry->done->size(); i1++){
390 if((*request_entry->request)[i1]){
391 ((*request_entry->request)[i1])->clearCurrentlyEnabling();
392 if(request_entry->ph_type == CurrentPhase){
393 ((*request_entry->request)[i1])->decrCurrWaiting();
396 ((*request_entry->request)[i1])->decrGlobalWaiting();
400 // update MI state for this entry and send response to caller
401 DMenableResponse(*request_entry,successful);
404 // remove this entry from the outstanding enables list
405 u_int size = paradynDaemon::outstanding_enables.size();
406 paradynDaemon::outstanding_enables[which] =
407 paradynDaemon::outstanding_enables[size-1];
408 paradynDaemon::outstanding_enables.resize(size-1);
410 // for each element on outstanding_enables, check to see if there are
411 // any outstatnding_enables that can be satisfied by this request
412 // if so, update state, and for any outstanding_enables that are
413 // complete, send the result to the client thread
414 // update not_all_done
415 for(u_int i2=0; i2 < paradynDaemon::outstanding_enables.size(); i2++){
416 DM_enableType *next_entry = paradynDaemon::outstanding_enables[i2];
417 next_entry->updateAny(*(request_entry->request),successful);
419 delete request_entry;
422 if(paradynDaemon::outstanding_enables.size()){
426 if((paradynDaemon::outstanding_enables[i3])->not_all_done){
429 else { // this entry's request is complete
430 // update MI state for this entry and send response to caller
431 DM_enableType *temp = paradynDaemon::outstanding_enables[i3];
432 successful.resize(temp->request->size());
433 for(u_int k2=0; k2 < successful.size(); k2++){
434 if(!((*(temp->done))[k2])) successful[k2] = false;
435 else successful[k2] = true;
437 // decrement the number of waiting for enables for
438 // each MI in this response
439 for(u_int k3=0; k3 < temp->request->size(); k3++){
440 if((*temp->request)[k3]){
441 if(temp->ph_type == CurrentPhase){
442 ((*temp->request)[k3])->decrCurrWaiting();
445 ((*temp->request)[k3])->decrGlobalWaiting();
449 DMenableResponse(*temp,successful);
451 // remove entry from outstanding_enables list
452 u_int newsize=paradynDaemon::outstanding_enables.size()-1;
453 paradynDaemon::outstanding_enables[i3] =
454 paradynDaemon::outstanding_enables[newsize];
455 paradynDaemon::outstanding_enables.resize(newsize);
458 if(i3 >= paradynDaemon::outstanding_enables.size()) done = true;
465 // Upcall from daemon in response to getPredictedDataCost call
466 // id - perfStreamHandle assoc. with the call
467 // req_id - an identifier assoc. with the request
468 // val - the cost of enabling the metric/focus pair
470 void dynRPCUser::getPredictedDataCostCallback(u_int id,
475 // find the assoc. perfStream and update it's pred data cost value
476 dictionary_hash_iter<perfStreamHandle,performanceStream*>
477 allS(performanceStream::allStreams);
478 perfStreamHandle h; performanceStream *ps;
479 while(allS.next(h,ps)){
480 if(h == (perfStreamHandle)id){
481 ps->predictedDataCostCallback(req_id,val,clientID);
484 // TODO: call correct routine
489 // Display errors using showError function from the UIM class
490 // This function allows to display error messages from paradynd
491 // using the "upcall" or "call back" mechanism.
492 // Parameters: errCode = Error code
493 // errString = Error message
494 // hostName = Host name where the error occur
495 // Call: there is a macro defined in "showerror.h". This macro must be
496 // used when calling this function. A typical call is:
497 // showErrorCallback(99, "Erro message test"). This macro will
498 // automatically insert the additional host info required.
500 void dynRPCUser::showErrorCallback(int errCode,
506 if (errString.length() > 0) {
507 if (hostName.length() > 0) {
508 msg = string("<Msg from daemon on host ") + hostName +
509 string("> ") + errString;
512 msg = string("<Msg from daemon on host ?> ") + errString;
514 uiMgr->showError(errCode, P_strdup(msg.string_of()));
517 uiMgr->showError(errCode, "");
521 // hostName.length() should always be > 0, otherwise
522 // hostName is not defined (i.e. "?" will be used instead).
523 // if errString.length()==0, (i.e. errString.string_of()==""),
524 // then we will use the default error message in errorList.tcl
525 // This message, however, will not include any info about the current
531 // Paradynd calls this igen fn when it starts a new process (more
532 // specifically, after it starts the new process and the new process
533 // has completed running DYNINSTinit).
535 void dynRPCUser::newProgramCallbackFunc(int pid,
536 vector<string> argvString,
541 // there better be a paradynd running on this machine!
543 for (unsigned i = 0; i < paradynDaemon::allDaemons.size(); i++) {
544 paradynDaemon *pd = paradynDaemon::allDaemons[i];
545 if (pd->machine.length() && (pd->machine == machine_name)){
546 if (!paradynDaemon::addRunningProgram(pid, argvString, pd, calledFromExec,
550 uiMgr->enablePauseOrRun();
556 // for now, abort if there is no paradynd, this should not happen
557 printf("process started on %s, can't find paradynd there\n",
558 machine_name.string_of());
559 printf("paradyn error #1 encountered\n");
563 void dynRPCUser::newMetricCallback(T_dyninstRPC::metricInfo info)
568 void dynRPCUser::firstSampleCallback (int,double) {
570 assert(0 && "Invalid virtual function");
573 void dynRPCUser::cpDataCallbackFunc(int,double,int,double,double)
575 assert(0 && "Invalid virtual function");
578 // batch the sample delivery
579 void dynRPCUser::batchSampleDataCallbackFunc(int,
580 vector<T_dyninstRPC::batch_buffer_entry>)
582 assert(0 && "Invalid virtual function");
586 // When a paradynd is started remotely, ie not by paradyn, this upcall
587 // reports the information for that paradynd to paradyn
590 dynRPCUser::reportSelf (string , string , int , string)
597 dynRPCUser::reportStatus (string)
599 assert(0 && "Invalid virtual function");
603 dynRPCUser::processStatus(int, u_int)
605 assert(0 && "Invalid virtual function");
609 dynRPCUser::endOfDataCollection(int)
611 assert(0 && "Invalid virtual function");
616 // establish socket that will be advertised to paradynd's
617 // this socket will allow paradynd's to connect to paradyn for pvm
620 DMsetupSocket (int &sockfd)
622 // setup "well known" socket for pvm paradynd's to connect to
624 aflag = ((dataManager::dm->socket =
625 RPC_setup_socket (sockfd, AF_INET, SOCK_STREAM)) >= 0);
628 // bind fd for this thread
629 msg_bind (sockfd, true);
635 // accept the connection
636 int new_fd = RPC_getConnect(dataManager::dm->sock_fd);
638 uiMgr->showError(4, "");
640 // add new daemon to dictionary of all deamons
641 paradynDaemon::addDaemon(new_fd);
644 bool dataManager::DM_sequential_init(const char* met_file){
645 string mfile = met_file;
646 return(metMain(mfile));
649 int dataManager::DM_post_thread_create_init(int tid) {
652 thr_name("Data Manager");
653 dataManager::dm = new dataManager(tid);
655 // supports argv passed to paradynDaemon
656 // new paradynd's may try to connect to well known port
657 DMsetupSocket (dataManager::dm->sock_fd);
660 aflag=(RPC_make_arg_list(paradynDaemon::args,
661 dataManager::dm->socket, 1, 1, "", false));
664 // start initial phase
665 string dm_phase0 = "phase_0";
666 phaseInfo::startPhase(0.0,dm_phase0,false,false);
669 unsigned int msgSize = 64;
670 msg_send (MAINtid, MSG_TAG_DM_READY, (char *) NULL, 0);
671 unsigned int tag = MSG_TAG_ALL_CHILDREN_READY;
672 msg_recv (&tag, DMbuff, &msgSize);
677 // Main loop for the dataManager thread.
679 void *DMmain(void* varg)
681 unsigned fd_first = 0;
682 // We declare the "printChangeCollection" tunable constant here; it will
683 // last for the lifetime of this function, which is pretty much forever.
684 // (used to be declared as global in DMappContext.C. Globally declared
685 // tunables are now a no-no). Note that the variable name (printCC) is
687 tunableBooleanConstantDeclarator printCC("printChangeCollection",
688 "Print the name of metric/focus when enabled or disabled",
689 false, // initial value
693 // Now the same for "printSampleArrival"
694 extern bool our_print_sample_arrival;
695 our_print_sample_arrival = false;
696 extern void printSampleArrivalCallback(bool);
697 tunableBooleanConstantDeclarator printSA("printSampleArrival",
698 "Print out status lines to show the arrival of samples",
699 our_print_sample_arrival, // init val
700 printSampleArrivalCallback,
703 int tid; memcpy((void*)&tid,varg, sizeof(int));
704 dataManager::DM_post_thread_create_init(tid);
708 paradynDaemon *pd = NULL;
710 for(unsigned i = 0; i < paradynDaemon::allDaemons.size(); i++){
711 pd = paradynDaemon::allDaemons[i];
712 // handle up to max async requests that may have been buffered
713 // while blocking on a sync request
714 while (pd->buffered_requests()){
715 if(pd->process_buffered() == T_dyninstRPC::error) {
716 cout << "error on paradyn daemon\n";
717 paradynDaemon::removeDaemon(pd, true);
721 // ret = msg_poll(&tag, true);
722 ret = msg_poll_preference(&tag, true,fd_first);
723 fd_first = !fd_first;
724 assert(ret != THR_ERR);
726 if (tag == MSG_TAG_FILE) {
727 // must be an upcall on something speaking the dynRPC protocol.
728 if (ret == dataManager::dm->sock_fd){
729 DMnewParadynd(); // set up a new daemon
732 for(unsigned i = 0; i < paradynDaemon::allDaemons.size(); i++){
733 pd = paradynDaemon::allDaemons[i];
734 if(pd->get_fd() == ret){
735 if(pd->waitLoop() == T_dyninstRPC::error) {
736 cout << "error on paradyn daemon\n";
737 paradynDaemon::removeDaemon(pd, true);
740 // handle async requests that may have been buffered
741 // while blocking on a sync request
742 while(pd->buffered_requests()){
743 if(pd->process_buffered() == T_dyninstRPC::error) {
744 cout << "error on paradyn daemon\n";
745 paradynDaemon::removeDaemon(pd, true);
749 } else if (dataManager::dm->isValidTag
750 ((T_dataManager::message_tags)tag)) {
751 if (dataManager::dm->waitLoop(true,
752 (T_dataManager::message_tags)tag) == T_dataManager::error) {
757 cerr << "Unrecognized message in DMmain.C\n";
764 void addMetric(T_dyninstRPC::metricInfo &info)
766 // if metric already exists return
767 if(metric::allMetrics.defines(info.name)){
770 metric *met = new metric(info);
772 // now tell all perfStreams
773 dictionary_hash_iter<perfStreamHandle,performanceStream*>
774 allS(performanceStream::allStreams);
776 performanceStream *ps;
777 while(allS.next(h,ps)){
778 if(ps->controlFunc.mFunc){
779 // set the correct destination thread.
780 dataManager::dm->setTid(ps->threadId);
781 dataManager::dm->newMetricDefined(ps->controlFunc.mFunc,
788 met->getUnitsType());
794 // I don't want to parse for '/' more than once, thus the use of a string vector
795 resourceHandle createResource(vector<string>& resource_name, string& abstr, unsigned type) {
796 resource *parent = NULL;
797 unsigned r_size = resource_name.size();
803 // Should this case ever occur ?
806 parent = resource::rootResource; break;
808 for (unsigned ri=0; ri<(r_size-1); ri++)
809 p_name += string("/") + resource_name[ri];
810 parent = resource::string_to_resource(p_name);
814 if (!parent) assert(0);
817 /* first check to see if the resource has already been defined */
818 resource *p = resource::resources[parent->getHandle()];
819 string myName = p_name;
821 myName += resource_name[r_size - 1];
822 resourceHandle *child = p->findChild(myName.string_of());
828 // if abstr is not defined then use default abstraction
829 if(!abstr.string_of()){
830 abstr = string("BASE");
834 resource *ret = new resource(parent->getHandle(),resource_name,
837 // check to see if the suppressMagnify option should be set...if
838 // this resource is specifed in the mdl exclude_lib option
839 vector<string> shared_lib_constraints;
840 if(resource::get_lib_constraints(shared_lib_constraints) &&
841 (string(parent->getFullName()) == "/Code")){
842 for(u_int i=0; i < shared_lib_constraints.size(); i++){
843 if(shared_lib_constraints[i] == ret->getName()){
844 ret->setSuppressMagnify();
849 /* inform others about it if they need to know */
850 dictionary_hash_iter<perfStreamHandle,performanceStream*>
851 allS(performanceStream::allStreams);
853 performanceStream *ps;
854 resourceHandle r_handle = ret->getHandle();
855 string name = ret->getFullName();
856 while(allS.next(h,ps)){
857 ps->callResourceFunc(parent->getHandle(),r_handle,ret->getFullName(),
858 ret->getAbstractionName());
863 void newSampleRate(float rate)
865 paradynDaemon *pd = NULL;
866 for(unsigned i = 0; i < paradynDaemon::allDaemons.size(); i++){
867 pd = paradynDaemon::allDaemons[i];
868 pd->setSampleRate(rate);
873 // Note - the metric parser has been moved into the dataManager
874 bool parse_metrics(string metric_file) {
875 bool parseResult = metMain(metric_file);