CMS 3D CMS Logo

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