CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/FWCore/Framework/src/Schedule.cc

Go to the documentation of this file.
00001 #include "FWCore/Framework/interface/Schedule.h"
00002 
00003 #include "DataFormats/Provenance/interface/BranchIDListHelper.h"
00004 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00005 #include "DataFormats/Provenance/interface/ProcessConfiguration.h"
00006 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00007 #include "FWCore/Framework/interface/EDProducer.h"
00008 #include "FWCore/Framework/interface/OutputModuleDescription.h"
00009 #include "FWCore/Framework/interface/TriggerNamesService.h"
00010 #include "FWCore/Framework/interface/TriggerReport.h"
00011 #include "FWCore/Framework/src/Factory.h"
00012 #include "FWCore/Framework/src/OutputWorker.h"
00013 #include "FWCore/Framework/src/TriggerResultInserter.h"
00014 #include "FWCore/Framework/src/WorkerInPath.h"
00015 #include "FWCore/Framework/src/WorkerMaker.h"
00016 #include "FWCore/Framework/src/WorkerT.h"
00017 #include "FWCore/ParameterSet/interface/FillProductRegistryTransients.h"
00018 #include "FWCore/ParameterSet/interface/Registry.h"
00019 #include "FWCore/PluginManager/interface/PluginCapabilities.h"
00020 #include "FWCore/Utilities/interface/ReflexTools.h"
00021 
00022 #include "boost/bind.hpp"
00023 #include "boost/ref.hpp"
00024 
00025 #include <algorithm>
00026 #include <cassert>
00027 #include <cstdlib>
00028 #include <functional>
00029 #include <iomanip>
00030 #include <list>
00031 
00032 namespace edm {
00033   namespace {
00034 
00035     // Function template to transform each element in the input range to
00036     // a value placed into the output range. The supplied function
00037     // should take a const_reference to the 'input', and write to a
00038     // reference to the 'output'.
00039     template <typename InputIterator, typename ForwardIterator, typename Func>
00040     void
00041     transform_into(InputIterator begin, InputIterator end,
00042                    ForwardIterator out, Func func) {
00043       for (; begin != end; ++begin, ++out) func(*begin, *out);
00044     }
00045 
00046     // Function template that takes a sequence 'from', a sequence
00047     // 'to', and a callable object 'func'. It and applies
00048     // transform_into to fill the 'to' sequence with the values
00049     // calcuated by the callable object, taking care to fill the
00050     // outupt only if all calls succeed.
00051     template <typename FROM, typename TO, typename FUNC>
00052     void
00053     fill_summary(FROM const& from, TO& to, FUNC func) {
00054       TO temp(from.size());
00055       transform_into(from.begin(), from.end(), temp.begin(), func);
00056       to.swap(temp);
00057     }
00058 
00059     // -----------------------------
00060 
00061     // Here we make the trigger results inserter directly.  This should
00062     // probably be a utility in the WorkerRegistry or elsewhere.
00063 
00064     Schedule::WorkerPtr
00065     makeInserter(ParameterSet& proc_pset,
00066                  ProductRegistry& preg,
00067                  ActionTable const& actions,
00068                  boost::shared_ptr<ActivityRegistry> areg,
00069                  boost::shared_ptr<ProcessConfiguration> processConfiguration,
00070                  Schedule::TrigResPtr trptr) {
00071 
00072       ParameterSet* trig_pset = proc_pset.getPSetForUpdate("@trigger_paths");
00073       trig_pset->registerIt();
00074 
00075       WorkerParams work_args(proc_pset, trig_pset, preg, processConfiguration, actions);
00076       ModuleDescription md(trig_pset->id(),
00077                            "TriggerResultInserter",
00078                            "TriggerResults",
00079                            processConfiguration);
00080 
00081       areg->preModuleConstructionSignal_(md);
00082       std::auto_ptr<EDProducer> producer(new TriggerResultInserter(*trig_pset, trptr));
00083       areg->postModuleConstructionSignal_(md);
00084 
00085       Schedule::WorkerPtr ptr(new WorkerT<EDProducer>(producer, md, work_args));
00086       ptr->setActivityRegistry(areg);
00087       return ptr;
00088     }
00089 
00090     void loadMissingDictionaries() {
00091       std::string const prefix("LCGReflex/");
00092       while (!missingTypes().empty()) {
00093         StringSet missing(missingTypes());
00094         for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end();
00095            it != itEnd; ++it) {
00096           try {
00097             edmplugin::PluginCapabilities::get()->load(prefix + *it);
00098           }
00099           // We don't want to fail if we can't load a plug-in.
00100           catch(...) {}
00101         }
00102         missingTypes().clear();
00103         for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end();
00104            it != itEnd; ++it) {
00105           checkDictionaries(*it);
00106         }
00107         if (missingTypes() == missing) {
00108           break;
00109         }
00110       }
00111       if (missingTypes().empty()) {
00112         return;
00113       }
00114       std::ostringstream ostr;
00115       for (StringSet::const_iterator it = missingTypes().begin(), itEnd = missingTypes().end();
00116            it != itEnd; ++it) {
00117         ostr << *it << "\n\n";
00118       }
00119       throw Exception(errors::DictionaryNotFound)
00120         << "No REFLEX data dictionary found for the following classes:\n\n"
00121         << ostr.str()
00122         << "Most likely each dictionary was never generated,\n"
00123         << "but it may be that it was generated in the wrong package.\n"
00124         << "Please add (or move) the specification\n"
00125         << "<class name=\"whatever\"/>\n"
00126         << "to the appropriate classes_def.xml file.\n"
00127         << "If the class is a template instance, you may need\n"
00128         << "to define a dummy variable of this type in classes.h.\n"
00129         << "Also, if this class has any transient members,\n"
00130         << "you need to specify them in classes_def.xml.";
00131     }
00132   }
00133 
00134   // -----------------------------
00135 
00136   typedef std::vector<std::string> vstring;
00137 
00138   // -----------------------------
00139 
00140   Schedule::Schedule(ParameterSet& proc_pset,
00141                      service::TriggerNamesService& tns,
00142                      ProductRegistry& preg,
00143                      ActionTable const& actions,
00144                      boost::shared_ptr<ActivityRegistry> areg,
00145                      boost::shared_ptr<ProcessConfiguration> processConfiguration) :
00146     worker_reg_(areg),
00147     act_table_(&actions),
00148     actReg_(areg),
00149     state_(Ready),
00150     trig_name_list_(tns.getTrigPaths()),
00151     end_path_name_list_(tns.getEndPaths()),
00152     results_(new HLTGlobalStatus(trig_name_list_.size())),
00153     endpath_results_(), // delay!
00154     results_inserter_(),
00155     all_workers_(),
00156     all_output_workers_(),
00157     trig_paths_(),
00158     end_paths_(),
00159     wantSummary_(tns.wantSummary()),
00160     total_events_(),
00161     total_passed_(),
00162     stopwatch_(wantSummary_? new RunStopwatch::StopwatchPointer::element_type : static_cast<RunStopwatch::StopwatchPointer::element_type*> (0)),
00163     unscheduled_(new UnscheduledCallProducer),
00164     endpathsAreActive_(true) {
00165 
00166     ParameterSet const& opts = proc_pset.getUntrackedParameterSet("options", ParameterSet());
00167     bool hasPath = false;
00168 
00169     int trig_bitpos = 0;
00170     for (vstring::const_iterator i = trig_name_list_.begin(),
00171            e = trig_name_list_.end();
00172          i != e;
00173          ++i) {
00174       fillTrigPath(proc_pset, preg, processConfiguration, trig_bitpos, *i, results_);
00175       ++trig_bitpos;
00176       hasPath = true;
00177     }
00178 
00179     if (hasPath) {
00180       // the results inserter stands alone
00181       results_inserter_ = makeInserter(proc_pset,
00182                                        preg,
00183                                        actions, actReg_, processConfiguration, results_);
00184       addToAllWorkers(results_inserter_.get());
00185     }
00186 
00187     TrigResPtr epptr(new HLTGlobalStatus(end_path_name_list_.size()));
00188     endpath_results_ = epptr;
00189 
00190     // fill normal endpaths
00191     vstring::iterator eib(end_path_name_list_.begin()), eie(end_path_name_list_.end());
00192     for (int bitpos = 0; eib != eie; ++eib, ++bitpos) {
00193       fillEndPath(proc_pset, preg, processConfiguration, bitpos, *eib);
00194     }
00195 
00196     //See if all modules were used
00197     std::set<std::string> usedWorkerLabels;
00198     for (AllWorkers::iterator itWorker = workersBegin();
00199         itWorker != workersEnd();
00200         ++itWorker) {
00201       usedWorkerLabels.insert((*itWorker)->description().moduleLabel());
00202     }
00203     std::vector<std::string> modulesInConfig(proc_pset.getParameter<std::vector<std::string> >("@all_modules"));
00204     std::set<std::string> modulesInConfigSet(modulesInConfig.begin(), modulesInConfig.end());
00205     std::vector<std::string> unusedLabels;
00206     set_difference(modulesInConfigSet.begin(), modulesInConfigSet.end(),
00207                    usedWorkerLabels.begin(), usedWorkerLabels.end(),
00208                    back_inserter(unusedLabels));
00209     //does the configuration say we should allow on demand?
00210     bool allowUnscheduled = opts.getUntrackedParameter<bool>("allowUnscheduled", false);
00211     std::set<std::string> unscheduledLabels;
00212     if (!unusedLabels.empty()) {
00213       //Need to
00214       // 1) create worker
00215       // 2) if it is a WorkerT<EDProducer>, add it to our list
00216       // 3) hand list to our delayed reader
00217       std::vector<std::string>  shouldBeUsedLabels;
00218 
00219       for (std::vector<std::string>::iterator itLabel = unusedLabels.begin(), itLabelEnd = unusedLabels.end();
00220           itLabel != itLabelEnd;
00221           ++itLabel) {
00222         if (allowUnscheduled) {
00223           bool isTracked;
00224           ParameterSet* modulePSet(proc_pset.getPSetForUpdate(*itLabel, isTracked));
00225           assert(isTracked);
00226           assert(modulePSet != 0);
00227           WorkerParams params(proc_pset, modulePSet, preg,
00228                               processConfiguration, *act_table_);
00229           Worker* newWorker(worker_reg_.getWorker(params, *itLabel));
00230           if (dynamic_cast<WorkerT<EDProducer>*>(newWorker) ||
00231               dynamic_cast<WorkerT<EDFilter>*>(newWorker)) {
00232             unscheduledLabels.insert(*itLabel);
00233             unscheduled_->addWorker(newWorker);
00234             //add to list so it gets reset each new event
00235             addToAllWorkers(newWorker);
00236           } else {
00237             //not a producer so should be marked as not used
00238             shouldBeUsedLabels.push_back(*itLabel);
00239           }
00240         } else {
00241           //everthing is marked are unused so no 'on demand' allowed
00242           shouldBeUsedLabels.push_back(*itLabel);
00243         }
00244       }
00245       if (!shouldBeUsedLabels.empty()) {
00246         std::ostringstream unusedStream;
00247         unusedStream << "'" << shouldBeUsedLabels.front() << "'";
00248         for (std::vector<std::string>::iterator itLabel = shouldBeUsedLabels.begin() + 1,
00249               itLabelEnd = shouldBeUsedLabels.end();
00250             itLabel != itLabelEnd;
00251             ++itLabel) {
00252           unusedStream << ",'" << *itLabel << "'";
00253         }
00254         LogInfo("path")
00255           << "The following module labels are not assigned to any path:\n"
00256           << unusedStream.str()
00257           << "\n";
00258       }
00259     }
00260     if (!unscheduledLabels.empty()) {
00261       for (ProductRegistry::ProductList::const_iterator it = preg.productList().begin(),
00262           itEnd = preg.productList().end();
00263           it != itEnd;
00264           ++it) {
00265         if (it->second.produced() &&
00266             it->second.branchType() == InEvent &&
00267             unscheduledLabels.end() != unscheduledLabels.find(it->second.moduleLabel())) {
00268           it->second.setOnDemand();
00269         }
00270       }
00271     }
00272 
00273     proc_pset.registerIt();
00274     pset::Registry::instance()->extra().setID(proc_pset.id());
00275     processConfiguration->setParameterSetID(proc_pset.id());
00276 
00277     // This is used for a little sanity-check to make sure no code
00278     // modifications alter the number of workers at a later date.
00279     size_t all_workers_count = all_workers_.size();
00280 
00281     for (AllWorkers::iterator i = all_workers_.begin(), e = all_workers_.end();
00282          i != e;
00283          ++i) {
00284 
00285       // All the workers should be in all_workers_ by this point. Thus
00286       // we can now fill all_output_workers_.
00287       OutputWorker* ow = dynamic_cast<OutputWorker*>(*i);
00288       if (ow) all_output_workers_.push_back(ow);
00289     }
00290 
00291     // Now that the output workers are filled in, set any output limits.
00292     limitOutput(proc_pset);
00293 
00294     loadMissingDictionaries();
00295     preg.setFrozen();
00296 
00297     // Sanity check: make sure nobody has added a worker after we've
00298     // already relied on all_workers_ being full.
00299     assert (all_workers_count == all_workers_.size());
00300 
00301     ProcessConfigurationRegistry::instance()->insertMapped(*processConfiguration);
00302     BranchIDListHelper::updateRegistries(preg);
00303     fillProductRegistryTransients(*processConfiguration, preg);
00304   } // Schedule::Schedule
00305 
00306   void
00307   Schedule::limitOutput(ParameterSet const& proc_pset) {
00308     std::string const output("output");
00309 
00310     ParameterSet const& maxEventsPSet = proc_pset.getUntrackedParameterSet("maxEvents", ParameterSet());
00311     int maxEventSpecs = 0;
00312     int maxEventsOut = -1;
00313     ParameterSet const* vMaxEventsOut = 0;
00314     std::vector<std::string> intNamesE = maxEventsPSet.getParameterNamesForType<int>(false);
00315     if (search_all(intNamesE, output)) {
00316       maxEventsOut = maxEventsPSet.getUntrackedParameter<int>(output);
00317       ++maxEventSpecs;
00318     }
00319     std::vector<std::string> psetNamesE;
00320     maxEventsPSet.getParameterSetNames(psetNamesE, false);
00321     if (search_all(psetNamesE, output)) {
00322       vMaxEventsOut = &maxEventsPSet.getUntrackedParameterSet(output);
00323       ++maxEventSpecs;
00324     }
00325 
00326     if (maxEventSpecs > 1) {
00327       throw Exception(errors::Configuration) <<
00328         "\nAt most, one form of 'output' may appear in the 'maxEvents' parameter set";
00329     }
00330 
00331     if (maxEventSpecs == 0) {
00332       return;
00333     }
00334 
00335     for (AllOutputWorkers::const_iterator it = all_output_workers_.begin(), itEnd = all_output_workers_.end();
00336         it != itEnd; ++it) {
00337       OutputModuleDescription desc(maxEventsOut);
00338       if (vMaxEventsOut != 0 && !vMaxEventsOut->empty()) {
00339         std::string moduleLabel = (*it)->description().moduleLabel();
00340         try {
00341           desc.maxEvents_ = vMaxEventsOut->getUntrackedParameter<int>(moduleLabel);
00342         } catch (Exception const&) {
00343           throw Exception(errors::Configuration) <<
00344             "\nNo entry in 'maxEvents' for output module label '" << moduleLabel << "'.\n";
00345         }
00346       }
00347       (*it)->configure(desc);
00348     }
00349   }
00350 
00351   bool const Schedule::terminate() const {
00352     if (all_output_workers_.empty()) {
00353       return false;
00354     }
00355     for (AllOutputWorkers::const_iterator it = all_output_workers_.begin(),
00356          itEnd = all_output_workers_.end();
00357          it != itEnd; ++it) {
00358       if (!(*it)->limitReached()) {
00359         // Found an output module that has not reached output event count.
00360         return false;
00361       }
00362     }
00363     LogInfo("SuccessfulTermination")
00364       << "The job is terminating successfully because each output module\n"
00365       << "has reached its configured limit.\n";
00366     return true;
00367   }
00368 
00369   void Schedule::fillWorkers(ParameterSet& proc_pset,
00370                              ProductRegistry& preg,
00371                              boost::shared_ptr<ProcessConfiguration const> processConfiguration,
00372                              std::string const& name,
00373                              bool ignoreFilters,
00374                              PathWorkers& out) {
00375     vstring modnames = proc_pset.getParameter<vstring>(name);
00376     vstring::iterator it(modnames.begin()), ie(modnames.end());
00377     PathWorkers tmpworkers;
00378 
00379     for (; it != ie; ++it) {
00380 
00381       WorkerInPath::FilterAction filterAction = WorkerInPath::Normal;
00382       if ((*it)[0] == '!')       filterAction = WorkerInPath::Veto;
00383       else if ((*it)[0] == '-')  filterAction = WorkerInPath::Ignore;
00384 
00385       std::string moduleLabel = *it;
00386       if (filterAction != WorkerInPath::Normal) moduleLabel.erase(0, 1);
00387 
00388       bool isTracked;
00389       ParameterSet* modpset = proc_pset.getPSetForUpdate(moduleLabel, isTracked);
00390       if (modpset == 0) {
00391         std::string pathType("endpath");
00392         if (!search_all(end_path_name_list_, name)) {
00393           pathType = std::string("path");
00394         }
00395         throw Exception(errors::Configuration) <<
00396           "The unknown module label \"" << moduleLabel <<
00397           "\" appears in " << pathType << " \"" << name <<
00398           "\"\n please check spelling or remove that label from the path.";
00399       }
00400       assert(isTracked);
00401 
00402       WorkerParams params(proc_pset, modpset, preg, processConfiguration, *act_table_);
00403       Worker* worker = worker_reg_.getWorker(params, moduleLabel);
00404       if (ignoreFilters && filterAction != WorkerInPath::Ignore && dynamic_cast<WorkerT<EDFilter>*>(worker)) {
00405         // We have a filter on an end path, and the filter is not explicitly ignored.
00406         // See if the filter is allowed.
00407         std::vector<std::string> allowed_filters = proc_pset.getUntrackedParameter<vstring>("@filters_on_endpaths");
00408         if (!search_all(allowed_filters, worker->description().moduleName())) {
00409           // Filter is not allowed. Ignore the result, and issue a warning.
00410           filterAction = WorkerInPath::Ignore;
00411           LogWarning("FilterOnEndPath")
00412             << "The EDFilter '" << worker->description().moduleName() << "' with module label '" << moduleLabel << "' appears on EndPath '" << name << "'.\n"
00413             << "The return value of the filter will be ignored.\n"
00414             << "To suppress this warning, either remove the filter from the endpath,\n"
00415             << "or explicitly ignore it in the configuration by using cms.ignore().\n";
00416         }
00417       }
00418       WorkerInPath w(worker, filterAction);
00419       tmpworkers.push_back(w);
00420     }
00421 
00422     out.swap(tmpworkers);
00423   }
00424 
00425   void Schedule::fillTrigPath(ParameterSet& proc_pset,
00426                               ProductRegistry& preg,
00427                               boost::shared_ptr<ProcessConfiguration const> processConfiguration,
00428                               int bitpos, std::string const& name, TrigResPtr trptr) {
00429     PathWorkers tmpworkers;
00430     Workers holder;
00431     fillWorkers(proc_pset, preg, processConfiguration, name, false, tmpworkers);
00432 
00433     for (PathWorkers::iterator wi(tmpworkers.begin()),
00434           we(tmpworkers.end()); wi != we; ++wi) {
00435       holder.push_back(wi->getWorker());
00436     }
00437 
00438     // an empty path will cause an extra bit that is not used
00439     if (!tmpworkers.empty()) {
00440       Path p(bitpos, name, tmpworkers, trptr, *act_table_, actReg_, false);
00441       if (wantSummary_) {
00442         p.useStopwatch();
00443       }
00444       trig_paths_.push_back(p);
00445     }
00446     for_all(holder, boost::bind(&Schedule::addToAllWorkers, this, _1));
00447   }
00448 
00449   void Schedule::fillEndPath(ParameterSet& proc_pset,
00450                              ProductRegistry& preg,
00451                              boost::shared_ptr<ProcessConfiguration const> processConfiguration,
00452                              int bitpos, std::string const& name) {
00453     PathWorkers tmpworkers;
00454     fillWorkers(proc_pset, preg, processConfiguration, name, true, tmpworkers);
00455     Workers holder;
00456 
00457     for (PathWorkers::iterator wi(tmpworkers.begin()), we(tmpworkers.end()); wi != we; ++wi) {
00458       holder.push_back(wi->getWorker());
00459     }
00460 
00461     if (!tmpworkers.empty()) {
00462       Path p(bitpos, name, tmpworkers, endpath_results_, *act_table_, actReg_, true);
00463       if (wantSummary_) {
00464         p.useStopwatch();
00465       }
00466       end_paths_.push_back(p);
00467     }
00468     for_all(holder, boost::bind(&Schedule::addToAllWorkers, this, _1));
00469   }
00470 
00471   void Schedule::endJob() {
00472     bool failure = false;
00473     cms::Exception accumulated("endJob");
00474     AllWorkers::iterator ai(workersBegin()), ae(workersEnd());
00475     for (; ai != ae; ++ai) {
00476       try {
00477         (*ai)->endJob();
00478       }
00479       catch (cms::Exception& e) {
00480         accumulated << "cms::Exception caught in Schedule::endJob\n"
00481                     << e.explainSelf();
00482         failure = true;
00483       }
00484       catch (std::exception& e) {
00485         accumulated << "Standard library exception caught in Schedule::endJob\n"
00486                     << e.what();
00487         failure = true;
00488       }
00489       catch (...) {
00490         accumulated << "Unknown exception caught in Schedule::endJob\n";
00491         failure = true;
00492       }
00493     }
00494     if (failure) {
00495       throw accumulated;
00496     }
00497 
00498 
00499     if (wantSummary_ == false) return;
00500 
00501     TrigPaths::const_iterator pi, pe;
00502 
00503     // The trigger report (pass/fail etc.):
00504 
00505     LogVerbatim("FwkSummary") << "";
00506     LogVerbatim("FwkSummary") << "TrigReport " << "---------- Event  Summary ------------";
00507     LogVerbatim("FwkSummary") << "TrigReport"
00508                               << " Events total = " << totalEvents()
00509                               << " passed = " << totalEventsPassed()
00510                               << " failed = " << (totalEventsFailed())
00511                               << "";
00512 
00513     LogVerbatim("FwkSummary") << "";
00514     LogVerbatim("FwkSummary") << "TrigReport " << "---------- Path   Summary ------------";
00515     LogVerbatim("FwkSummary") << "TrigReport "
00516                               << std::right << std::setw(10) << "Trig Bit#" << " "
00517                               << std::right << std::setw(10) << "Run" << " "
00518                               << std::right << std::setw(10) << "Passed" << " "
00519                               << std::right << std::setw(10) << "Failed" << " "
00520                               << std::right << std::setw(10) << "Error" << " "
00521                               << "Name" << "";
00522     pi = trig_paths_.begin();
00523     pe = trig_paths_.end();
00524     for (; pi != pe; ++pi) {
00525       LogVerbatim("FwkSummary") << "TrigReport "
00526                                 << std::right << std::setw(5) << 1
00527                                 << std::right << std::setw(5) << pi->bitPosition() << " "
00528                                 << std::right << std::setw(10) << pi->timesRun() << " "
00529                                 << std::right << std::setw(10) << pi->timesPassed() << " "
00530                                 << std::right << std::setw(10) << pi->timesFailed() << " "
00531                                 << std::right << std::setw(10) << pi->timesExcept() << " "
00532                                 << pi->name() << "";
00533     }
00534 
00535     LogVerbatim("FwkSummary") << "";
00536     LogVerbatim("FwkSummary") << "TrigReport " << "-------End-Path   Summary ------------";
00537     LogVerbatim("FwkSummary") << "TrigReport "
00538                               << std::right << std::setw(10) << "Trig Bit#" << " "
00539                               << std::right << std::setw(10) << "Run" << " "
00540                               << std::right << std::setw(10) << "Passed" << " "
00541                               << std::right << std::setw(10) << "Failed" << " "
00542                               << std::right << std::setw(10) << "Error" << " "
00543                               << "Name" << "";
00544     pi = end_paths_.begin();
00545     pe = end_paths_.end();
00546     for (; pi != pe; ++pi) {
00547       LogVerbatim("FwkSummary") << "TrigReport "
00548                                 << std::right << std::setw(5) << 0
00549                                 << std::right << std::setw(5) << pi->bitPosition() << " "
00550                                 << std::right << std::setw(10) << pi->timesRun() << " "
00551                                 << std::right << std::setw(10) << pi->timesPassed() << " "
00552                                 << std::right << std::setw(10) << pi->timesFailed() << " "
00553                                 << std::right << std::setw(10) << pi->timesExcept() << " "
00554                                 << pi->name() << "";
00555     }
00556 
00557     pi = trig_paths_.begin();
00558     pe = trig_paths_.end();
00559     for (; pi != pe; ++pi) {
00560       LogVerbatim("FwkSummary") << "";
00561       LogVerbatim("FwkSummary") << "TrigReport " << "---------- Modules in Path: " << pi->name() << " ------------";
00562       LogVerbatim("FwkSummary") << "TrigReport "
00563                                 << std::right << std::setw(10) << "Trig Bit#" << " "
00564                                 << std::right << std::setw(10) << "Visited" << " "
00565                                 << std::right << std::setw(10) << "Passed" << " "
00566                                 << std::right << std::setw(10) << "Failed" << " "
00567                                 << std::right << std::setw(10) << "Error" << " "
00568                                 << "Name" << "";
00569 
00570       for (unsigned int i = 0; i < pi->size(); ++i) {
00571         LogVerbatim("FwkSummary") << "TrigReport "
00572                                   << std::right << std::setw(5) << 1
00573                                   << std::right << std::setw(5) << pi->bitPosition() << " "
00574                                   << std::right << std::setw(10) << pi->timesVisited(i) << " "
00575                                   << std::right << std::setw(10) << pi->timesPassed(i) << " "
00576                                   << std::right << std::setw(10) << pi->timesFailed(i) << " "
00577                                   << std::right << std::setw(10) << pi->timesExcept(i) << " "
00578                                   << pi->getWorker(i)->description().moduleLabel() << "";
00579       }
00580     }
00581 
00582     pi = end_paths_.begin();
00583     pe = end_paths_.end();
00584     for (; pi != pe; ++pi) {
00585       LogVerbatim("FwkSummary") << "";
00586       LogVerbatim("FwkSummary") << "TrigReport " << "------ Modules in End-Path: " << pi->name() << " ------------";
00587       LogVerbatim("FwkSummary") << "TrigReport "
00588                                 << std::right << std::setw(10) << "Trig Bit#" << " "
00589                                 << std::right << std::setw(10) << "Visited" << " "
00590                                 << std::right << std::setw(10) << "Passed" << " "
00591                                 << std::right << std::setw(10) << "Failed" << " "
00592                                 << std::right << std::setw(10) << "Error" << " "
00593                                 << "Name" << "";
00594 
00595       for (unsigned int i = 0; i < pi->size(); ++i) {
00596         LogVerbatim("FwkSummary") << "TrigReport "
00597                                   << std::right << std::setw(5) << 0
00598                                   << std::right << std::setw(5) << pi->bitPosition() << " "
00599                                   << std::right << std::setw(10) << pi->timesVisited(i) << " "
00600                                   << std::right << std::setw(10) << pi->timesPassed(i) << " "
00601                                   << std::right << std::setw(10) << pi->timesFailed(i) << " "
00602                                   << std::right << std::setw(10) << pi->timesExcept(i) << " "
00603                                   << pi->getWorker(i)->description().moduleLabel() << "";
00604       }
00605     }
00606 
00607     LogVerbatim("FwkSummary") << "";
00608     LogVerbatim("FwkSummary") << "TrigReport " << "---------- Module Summary ------------";
00609     LogVerbatim("FwkSummary") << "TrigReport "
00610                               << std::right << std::setw(10) << "Visited" << " "
00611                               << std::right << std::setw(10) << "Run" << " "
00612                               << std::right << std::setw(10) << "Passed" << " "
00613                               << std::right << std::setw(10) << "Failed" << " "
00614                               << std::right << std::setw(10) << "Error" << " "
00615                               << "Name" << "";
00616     ai = workersBegin();
00617     ae = workersEnd();
00618     for (; ai != ae; ++ai) {
00619       LogVerbatim("FwkSummary") << "TrigReport "
00620                                 << std::right << std::setw(10) << (*ai)->timesVisited() << " "
00621                                 << std::right << std::setw(10) << (*ai)->timesRun() << " "
00622                                 << std::right << std::setw(10) << (*ai)->timesPassed() << " "
00623                                 << std::right << std::setw(10) << (*ai)->timesFailed() << " "
00624                                 << std::right << std::setw(10) << (*ai)->timesExcept() << " "
00625                                 << (*ai)->description().moduleLabel() << "";
00626 
00627     }
00628     LogVerbatim("FwkSummary") << "";
00629 
00630     // The timing report (CPU and Real Time):
00631 
00632     LogVerbatim("FwkSummary") << "TimeReport " << "---------- Event  Summary ---[sec]----";
00633     LogVerbatim("FwkSummary") << "TimeReport"
00634                               << std::setprecision(6) << std::fixed
00635                               << " CPU/event = " << timeCpuReal().first/std::max(1, totalEvents())
00636                               << " Real/event = " << timeCpuReal().second/std::max(1, totalEvents())
00637                               << "";
00638 
00639     LogVerbatim("FwkSummary") << "";
00640     LogVerbatim("FwkSummary") << "TimeReport " << "---------- Path   Summary ---[sec]----";
00641     LogVerbatim("FwkSummary") << "TimeReport "
00642                               << std::right << std::setw(22) << "per event "
00643                               << std::right << std::setw(22) << "per path-run "
00644                               << "";
00645     LogVerbatim("FwkSummary") << "TimeReport "
00646                               << std::right << std::setw(10) << "CPU" << " "
00647                               << std::right << std::setw(10) << "Real" << " "
00648                               << std::right << std::setw(10) << "CPU" << " "
00649                               << std::right << std::setw(10) << "Real" << " "
00650                               << "Name" << "";
00651     pi = trig_paths_.begin();
00652     pe = trig_paths_.end();
00653     for (; pi != pe; ++pi) {
00654       LogVerbatim("FwkSummary") << "TimeReport "
00655                                 << std::setprecision(6) << std::fixed
00656                                 << std::right << std::setw(10) << pi->timeCpuReal().first/std::max(1, totalEvents()) << " "
00657                                 << std::right << std::setw(10) << pi->timeCpuReal().second/std::max(1, totalEvents()) << " "
00658                                 << std::right << std::setw(10) << pi->timeCpuReal().first/std::max(1, pi->timesRun()) << " "
00659                                 << std::right << std::setw(10) << pi->timeCpuReal().second/std::max(1, pi->timesRun()) << " "
00660                                 << pi->name() << "";
00661     }
00662     LogVerbatim("FwkSummary") << "TimeReport "
00663                               << std::right << std::setw(10) << "CPU" << " "
00664                               << std::right << std::setw(10) << "Real" << " "
00665                               << std::right << std::setw(10) << "CPU" << " "
00666                               << std::right << std::setw(10) << "Real" << " "
00667                               << "Name" << "";
00668     LogVerbatim("FwkSummary") << "TimeReport "
00669                               << std::right << std::setw(22) << "per event "
00670                               << std::right << std::setw(22) << "per path-run "
00671                               << "";
00672 
00673     LogVerbatim("FwkSummary") << "";
00674     LogVerbatim("FwkSummary") << "TimeReport " << "-------End-Path   Summary ---[sec]----";
00675     LogVerbatim("FwkSummary") << "TimeReport "
00676                               << std::right << std::setw(22) << "per event "
00677                               << std::right << std::setw(22) << "per endpath-run "
00678                               << "";
00679     LogVerbatim("FwkSummary") << "TimeReport "
00680                               << std::right << std::setw(10) << "CPU" << " "
00681                               << std::right << std::setw(10) << "Real" << " "
00682                               << std::right << std::setw(10) << "CPU" << " "
00683                               << std::right << std::setw(10) << "Real" << " "
00684                               << "Name" << "";
00685     pi = end_paths_.begin();
00686     pe = end_paths_.end();
00687     for (; pi != pe; ++pi) {
00688       LogVerbatim("FwkSummary") << "TimeReport "
00689                                 << std::setprecision(6) << std::fixed
00690                                 << std::right << std::setw(10) << pi->timeCpuReal().first/std::max(1, totalEvents()) << " "
00691                                 << std::right << std::setw(10) << pi->timeCpuReal().second/std::max(1, totalEvents()) << " "
00692                                 << std::right << std::setw(10) << pi->timeCpuReal().first/std::max(1, pi->timesRun()) << " "
00693                                 << std::right << std::setw(10) << pi->timeCpuReal().second/std::max(1, pi->timesRun()) << " "
00694                                 << pi->name() << "";
00695     }
00696     LogVerbatim("FwkSummary") << "TimeReport "
00697                               << std::right << std::setw(10) << "CPU" << " "
00698                               << std::right << std::setw(10) << "Real" << " "
00699                               << std::right << std::setw(10) << "CPU" << " "
00700                               << std::right << std::setw(10) << "Real" << " "
00701                               << "Name" << "";
00702     LogVerbatim("FwkSummary") << "TimeReport "
00703                               << std::right << std::setw(22) << "per event "
00704                               << std::right << std::setw(22) << "per endpath-run "
00705                               << "";
00706 
00707     pi = trig_paths_.begin();
00708     pe = trig_paths_.end();
00709     for (; pi != pe; ++pi) {
00710       LogVerbatim("FwkSummary") << "";
00711       LogVerbatim("FwkSummary") << "TimeReport " << "---------- Modules in Path: " << pi->name() << " ---[sec]----";
00712       LogVerbatim("FwkSummary") << "TimeReport "
00713                                 << std::right << std::setw(22) << "per event "
00714                                 << std::right << std::setw(22) << "per module-visit "
00715                                 << "";
00716       LogVerbatim("FwkSummary") << "TimeReport "
00717                                 << std::right << std::setw(10) << "CPU" << " "
00718                                 << std::right << std::setw(10) << "Real" << " "
00719                                 << std::right << std::setw(10) << "CPU" << " "
00720                                 << std::right << std::setw(10) << "Real" << " "
00721                                 << "Name" << "";
00722       for (unsigned int i = 0; i < pi->size(); ++i) {
00723         LogVerbatim("FwkSummary") << "TimeReport "
00724                                   << std::setprecision(6) << std::fixed
00725                                   << std::right << std::setw(10) << pi->timeCpuReal(i).first/std::max(1, totalEvents()) << " "
00726                                   << std::right << std::setw(10) << pi->timeCpuReal(i).second/std::max(1, totalEvents()) << " "
00727                                   << std::right << std::setw(10) << pi->timeCpuReal(i).first/std::max(1, pi->timesVisited(i)) << " "
00728                                   << std::right << std::setw(10) << pi->timeCpuReal(i).second/std::max(1, pi->timesVisited(i)) << " "
00729                                   << pi->getWorker(i)->description().moduleLabel() << "";
00730       }
00731     }
00732     LogVerbatim("FwkSummary") << "TimeReport "
00733                               << std::right << std::setw(10) << "CPU" << " "
00734                               << std::right << std::setw(10) << "Real" << " "
00735                               << std::right << std::setw(10) << "CPU" << " "
00736                               << std::right << std::setw(10) << "Real" << " "
00737                               << "Name" << "";
00738     LogVerbatim("FwkSummary") << "TimeReport "
00739                               << std::right << std::setw(22) << "per event "
00740                               << std::right << std::setw(22) << "per module-visit "
00741                               << "";
00742 
00743     pi = end_paths_.begin();
00744     pe = end_paths_.end();
00745     for (; pi != pe; ++pi) {
00746       LogVerbatim("FwkSummary") << "";
00747       LogVerbatim("FwkSummary") << "TimeReport " << "------ Modules in End-Path: " << pi->name() << " ---[sec]----";
00748       LogVerbatim("FwkSummary") << "TimeReport "
00749                                 << std::right << std::setw(22) << "per event "
00750                                 << std::right << std::setw(22) << "per module-visit "
00751                                 << "";
00752       LogVerbatim("FwkSummary") << "TimeReport "
00753                                 << std::right << std::setw(10) << "CPU" << " "
00754                                 << std::right << std::setw(10) << "Real" << " "
00755                                 << std::right << std::setw(10) << "CPU" << " "
00756                                 << std::right << std::setw(10) << "Real" << " "
00757                                 << "Name" << "";
00758       for (unsigned int i = 0; i < pi->size(); ++i) {
00759         LogVerbatim("FwkSummary") << "TimeReport "
00760                                   << std::setprecision(6) << std::fixed
00761                                   << std::right << std::setw(10) << pi->timeCpuReal(i).first/std::max(1, totalEvents()) << " "
00762                                   << std::right << std::setw(10) << pi->timeCpuReal(i).second/std::max(1, totalEvents()) << " "
00763                                   << std::right << std::setw(10) << pi->timeCpuReal(i).first/std::max(1, pi->timesVisited(i)) << " "
00764                                   << std::right << std::setw(10) << pi->timeCpuReal(i).second/std::max(1, pi->timesVisited(i)) << " "
00765                                   << pi->getWorker(i)->description().moduleLabel() << "";
00766       }
00767     }
00768     LogVerbatim("FwkSummary") << "TimeReport "
00769                               << std::right << std::setw(10) << "CPU" << " "
00770                               << std::right << std::setw(10) << "Real" << " "
00771                               << std::right << std::setw(10) << "CPU" << " "
00772                               << std::right << std::setw(10) << "Real" << " "
00773                               << "Name" << "";
00774     LogVerbatim("FwkSummary") << "TimeReport "
00775                               << std::right << std::setw(22) << "per event "
00776                               << std::right << std::setw(22) << "per module-visit "
00777                               << "";
00778 
00779     LogVerbatim("FwkSummary") << "";
00780     LogVerbatim("FwkSummary") << "TimeReport " << "---------- Module Summary ---[sec]----";
00781     LogVerbatim("FwkSummary") << "TimeReport "
00782                               << std::right << std::setw(22) << "per event "
00783                               << std::right << std::setw(22) << "per module-run "
00784                               << std::right << std::setw(22) << "per module-visit "
00785                               << "";
00786     LogVerbatim("FwkSummary") << "TimeReport "
00787                               << std::right << std::setw(10) << "CPU" << " "
00788                               << std::right << std::setw(10) << "Real" << " "
00789                               << std::right << std::setw(10) << "CPU" << " "
00790                               << std::right << std::setw(10) << "Real" << " "
00791                               << std::right << std::setw(10) << "CPU" << " "
00792                               << std::right << std::setw(10) << "Real" << " "
00793                               << "Name" << "";
00794     ai = workersBegin();
00795     ae = workersEnd();
00796     for (; ai != ae; ++ai) {
00797       LogVerbatim("FwkSummary") << "TimeReport "
00798                                 << std::setprecision(6) << std::fixed
00799                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().first/std::max(1, totalEvents()) << " "
00800                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().second/std::max(1, totalEvents()) << " "
00801                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().first/std::max(1, (*ai)->timesRun()) << " "
00802                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().second/std::max(1, (*ai)->timesRun()) << " "
00803                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().first/std::max(1, (*ai)->timesVisited()) << " "
00804                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().second/std::max(1, (*ai)->timesVisited()) << " "
00805                                 << (*ai)->description().moduleLabel() << "";
00806     }
00807     LogVerbatim("FwkSummary") << "TimeReport "
00808                               << std::right << std::setw(10) << "CPU" << " "
00809                               << std::right << std::setw(10) << "Real" << " "
00810                               << std::right << std::setw(10) << "CPU" << " "
00811                               << std::right << std::setw(10) << "Real" << " "
00812                               << std::right << std::setw(10) << "CPU" << " "
00813                               << std::right << std::setw(10) << "Real" << " "
00814                               << "Name" << "";
00815     LogVerbatim("FwkSummary") << "TimeReport "
00816                               << std::right << std::setw(22) << "per event "
00817                               << std::right << std::setw(22) << "per module-run "
00818                               << std::right << std::setw(22) << "per module-visit "
00819                               << "";
00820 
00821     LogVerbatim("FwkSummary") << "";
00822     LogVerbatim("FwkSummary") << "T---Report end!" << "";
00823     LogVerbatim("FwkSummary") << "";
00824   }
00825 
00826   void Schedule::closeOutputFiles() {
00827     for_all(all_output_workers_, boost::bind(&OutputWorker::closeFile, _1));
00828   }
00829 
00830   void Schedule::openNewOutputFilesIfNeeded() {
00831     for_all(all_output_workers_, boost::bind(&OutputWorker::openNewFileIfNeeded, _1));
00832   }
00833 
00834   void Schedule::openOutputFiles(FileBlock& fb) {
00835     for_all(all_output_workers_, boost::bind(&OutputWorker::openFile, _1, boost::cref(fb)));
00836   }
00837 
00838   void Schedule::writeRun(RunPrincipal const& rp) {
00839     for_all(all_output_workers_, boost::bind(&OutputWorker::writeRun, _1, boost::cref(rp)));
00840   }
00841 
00842   void Schedule::writeLumi(LuminosityBlockPrincipal const& lbp) {
00843     for_all(all_output_workers_, boost::bind(&OutputWorker::writeLumi, _1, boost::cref(lbp)));
00844   }
00845 
00846   bool Schedule::shouldWeCloseOutput() const {
00847     // Return true iff at least one output module returns true.
00848     return (std::find_if (all_output_workers_.begin(), all_output_workers_.end(),
00849                      boost::bind(&OutputWorker::shouldWeCloseFile, _1))
00850                      != all_output_workers_.end());
00851   }
00852 
00853   void Schedule::respondToOpenInputFile(FileBlock const& fb) {
00854     for_all(all_workers_, boost::bind(&Worker::respondToOpenInputFile, _1, boost::cref(fb)));
00855   }
00856 
00857   void Schedule::respondToCloseInputFile(FileBlock const& fb) {
00858     for_all(all_workers_, boost::bind(&Worker::respondToCloseInputFile, _1, boost::cref(fb)));
00859   }
00860 
00861   void Schedule::respondToOpenOutputFiles(FileBlock const& fb) {
00862     for_all(all_workers_, boost::bind(&Worker::respondToOpenOutputFiles, _1, boost::cref(fb)));
00863   }
00864 
00865   void Schedule::respondToCloseOutputFiles(FileBlock const& fb) {
00866     for_all(all_workers_, boost::bind(&Worker::respondToCloseOutputFiles, _1, boost::cref(fb)));
00867   }
00868 
00869   void Schedule::beginJob() {
00870     for_all(all_workers_, boost::bind(&Worker::beginJob, _1));
00871   }
00872 
00873   void Schedule::preForkReleaseResources() {
00874     for_all(all_workers_, boost::bind(&Worker::preForkReleaseResources, _1));
00875   }
00876   void Schedule::postForkReacquireResources(unsigned int iChildIndex, unsigned int iNumberOfChildren) {
00877     for_all(all_workers_, boost::bind(&Worker::postForkReacquireResources, _1, iChildIndex, iNumberOfChildren));
00878   }
00879 
00880   bool Schedule::changeModule(std::string const& iLabel,
00881                               ParameterSet const& iPSet) {
00882     Worker* found = 0;
00883     for (AllWorkers::const_iterator it=all_workers_.begin(), itEnd=all_workers_.end();
00884         it != itEnd; ++it) {
00885       if ((*it)->description().moduleLabel() == iLabel) {
00886         found = *it;
00887         break;
00888       }
00889     }
00890     if (0 == found) {
00891       return false;
00892     }
00893 
00894     std::auto_ptr<Maker> wm(MakerPluginFactory::get()->create(found->description().moduleName()));
00895     wm->swapModule(found, iPSet);
00896     found->beginJob();
00897     return true;
00898   }
00899 
00900   std::vector<ModuleDescription const*>
00901   Schedule::getAllModuleDescriptions() const {
00902     AllWorkers::const_iterator i(workersBegin());
00903     AllWorkers::const_iterator e(workersEnd());
00904 
00905     std::vector<ModuleDescription const*> result;
00906     result.reserve(all_workers_.size());
00907 
00908     for (; i != e; ++i) {
00909       ModuleDescription const* p = (*i)->descPtr();
00910       result.push_back(p);
00911     }
00912     return result;
00913   }
00914 
00915   void
00916   Schedule::availablePaths(std::vector<std::string>& oLabelsToFill) const {
00917     oLabelsToFill.reserve(trig_paths_.size());
00918     std::transform(trig_paths_.begin(),
00919                    trig_paths_.end(),
00920                    std::back_inserter(oLabelsToFill),
00921                    boost::bind(&Path::name, _1));
00922   }
00923 
00924   void
00925   Schedule::modulesInPath(std::string const& iPathLabel,
00926                           std::vector<std::string>& oLabelsToFill) const {
00927     TrigPaths::const_iterator itFound =
00928     std::find_if (trig_paths_.begin(),
00929                  trig_paths_.end(),
00930                  boost::bind(std::equal_to<std::string>(),
00931                              iPathLabel,
00932                              boost::bind(&Path::name, _1)));
00933     if (itFound!=trig_paths_.end()) {
00934       oLabelsToFill.reserve(itFound->size());
00935       for (size_t i = 0; i < itFound->size(); ++i) {
00936         oLabelsToFill.push_back(itFound->getWorker(i)->description().moduleLabel());
00937       }
00938     }
00939   }
00940 
00941   void
00942   Schedule::enableEndPaths(bool active) {
00943     endpathsAreActive_ = active;
00944   }
00945 
00946   bool
00947   Schedule::endPathsEnabled() const {
00948     return endpathsAreActive_;
00949   }
00950 
00951   void
00952   fillModuleInPathSummary(Path const&, ModuleInPathSummary&) {
00953   }
00954 
00955   void
00956   fillModuleInPathSummary(Path const& path,
00957                           size_t which,
00958                           ModuleInPathSummary& sum) {
00959     sum.timesVisited = path.timesVisited(which);
00960     sum.timesPassed  = path.timesPassed(which);
00961     sum.timesFailed  = path.timesFailed(which);
00962     sum.timesExcept  = path.timesExcept(which);
00963     sum.moduleLabel  = path.getWorker(which)->description().moduleLabel();
00964   }
00965 
00966   void
00967   fillPathSummary(Path const& path, PathSummary& sum) {
00968     sum.name        = path.name();
00969     sum.bitPosition = path.bitPosition();
00970     sum.timesRun    = path.timesRun();
00971     sum.timesPassed = path.timesPassed();
00972     sum.timesFailed = path.timesFailed();
00973     sum.timesExcept = path.timesExcept();
00974 
00975     Path::size_type sz = path.size();
00976     std::vector<ModuleInPathSummary> temp(sz);
00977     for (size_t i = 0; i != sz; ++i) {
00978       fillModuleInPathSummary(path, i, temp[i]);
00979     }
00980     sum.moduleInPathSummaries.swap(temp);
00981   }
00982 
00983   void
00984   fillWorkerSummaryAux(Worker const& w, WorkerSummary& sum) {
00985     sum.timesVisited = w.timesVisited();
00986     sum.timesRun     = w.timesRun();
00987     sum.timesPassed  = w.timesPassed();
00988     sum.timesFailed  = w.timesFailed();
00989     sum.timesExcept  = w.timesExcept();
00990     sum.moduleLabel  = w.description().moduleLabel();
00991   }
00992 
00993   void
00994   fillWorkerSummary(Worker const* pw, WorkerSummary& sum) {
00995     fillWorkerSummaryAux(*pw, sum);
00996   }
00997 
00998   void
00999   Schedule::getTriggerReport(TriggerReport& rep) const {
01000     rep.eventSummary.totalEvents = totalEvents();
01001     rep.eventSummary.totalEventsPassed = totalEventsPassed();
01002     rep.eventSummary.totalEventsFailed = totalEventsFailed();
01003 
01004     fill_summary(trig_paths_,  rep.trigPathSummaries, &fillPathSummary);
01005     fill_summary(end_paths_,   rep.endPathSummaries,  &fillPathSummary);
01006     fill_summary(all_workers_, rep.workerSummaries,   &fillWorkerSummary);
01007   }
01008 
01009   void
01010   Schedule::clearCounters() {
01011     total_events_ = total_passed_ = 0;
01012     for_all(trig_paths_, boost::bind(&Path::clearCounters, _1));
01013     for_all(end_paths_, boost::bind(&Path::clearCounters, _1));
01014     for_all(all_workers_, boost::bind(&Worker::clearCounters, _1));
01015   }
01016 
01017   void
01018   Schedule::resetAll() {
01019     for_all(all_workers_, boost::bind(&Worker::reset, _1));
01020     results_->reset();
01021     endpath_results_->reset();
01022   }
01023 
01024   void
01025   Schedule::addToAllWorkers(Worker* w) {
01026     if (!search_all(all_workers_, w)) {
01027       if (wantSummary_) {
01028         w->useStopwatch();
01029       }
01030       all_workers_.push_back(w);
01031     }
01032   }
01033 
01034   void
01035   Schedule::setupOnDemandSystem(EventPrincipal& ep, EventSetup const& es) {
01036     // NOTE: who owns the productdescrption?  Just copied by value
01037     unscheduled_->setEventSetup(es);
01038     ep.setUnscheduledHandler(unscheduled_);
01039   }
01040 }