CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/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/interface/OutputModule.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/MessageLogger/interface/MessageLogger.h"
00018 #include "FWCore/ParameterSet/interface/FillProductRegistryTransients.h"
00019 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00020 #include "FWCore/ParameterSet/interface/Registry.h"
00021 #include "FWCore/Utilities/interface/Algorithms.h"
00022 #include "FWCore/Utilities/interface/ConvertException.h"
00023 #include "FWCore/Utilities/interface/ExceptionCollector.h"
00024 #include "FWCore/Utilities/interface/ReflexTools.h"
00025 
00026 #include "boost/bind.hpp"
00027 #include "boost/ref.hpp"
00028 
00029 #include <algorithm>
00030 #include <cassert>
00031 #include <cstdlib>
00032 #include <functional>
00033 #include <iomanip>
00034 #include <list>
00035 #include <exception>
00036 
00037 namespace edm {
00038   namespace {
00039 
00040     // Function template to transform each element in the input range to
00041     // a value placed into the output range. The supplied function
00042     // should take a const_reference to the 'input', and write to a
00043     // reference to the 'output'.
00044     template <typename InputIterator, typename ForwardIterator, typename Func>
00045     void
00046     transform_into(InputIterator begin, InputIterator end,
00047                    ForwardIterator out, Func func) {
00048       for (; begin != end; ++begin, ++out) func(*begin, *out);
00049     }
00050 
00051     // Function template that takes a sequence 'from', a sequence
00052     // 'to', and a callable object 'func'. It and applies
00053     // transform_into to fill the 'to' sequence with the values
00054     // calcuated by the callable object, taking care to fill the
00055     // outupt only if all calls succeed.
00056     template <typename FROM, typename TO, typename FUNC>
00057     void
00058     fill_summary(FROM const& from, TO& to, FUNC func) {
00059       TO temp(from.size());
00060       transform_into(from.begin(), from.end(), temp.begin(), func);
00061       to.swap(temp);
00062     }
00063 
00064     // -----------------------------
00065 
00066     // Here we make the trigger results inserter directly.  This should
00067     // probably be a utility in the WorkerRegistry or elsewhere.
00068 
00069     Schedule::WorkerPtr
00070     makeInserter(ParameterSet& proc_pset,
00071                  ProductRegistry& preg,
00072                  ActionTable const& actions,
00073                  boost::shared_ptr<ActivityRegistry> areg,
00074                  boost::shared_ptr<ProcessConfiguration> processConfiguration,
00075                  Schedule::TrigResPtr trptr) {
00076 
00077       ParameterSet* trig_pset = proc_pset.getPSetForUpdate("@trigger_paths");
00078       trig_pset->registerIt();
00079 
00080       WorkerParams work_args(proc_pset, trig_pset, preg, processConfiguration, actions);
00081       ModuleDescription md(trig_pset->id(),
00082                            "TriggerResultInserter",
00083                            "TriggerResults",
00084                            processConfiguration.get());
00085 
00086       areg->preModuleConstructionSignal_(md);
00087       std::auto_ptr<EDProducer> producer(new TriggerResultInserter(*trig_pset, trptr));
00088       areg->postModuleConstructionSignal_(md);
00089 
00090       Schedule::WorkerPtr ptr(new WorkerT<EDProducer>(producer, md, work_args));
00091       ptr->setActivityRegistry(areg);
00092       return ptr;
00093     }
00094 
00095     bool binary_search_string(std::vector<std::string> const& v, std::string const& s) {
00096       return std::binary_search(v.begin(), v.end(), s);
00097     }
00098     
00099     void
00100     initializeBranchToReadingWorker(ParameterSet const& opts,
00101                                     ProductRegistry const& preg,
00102                                     std::multimap<std::string,Worker*>& branchToReadingWorker)
00103     {
00104       // See if any data has been marked to be deleted early (removing any duplicates)
00105       auto vBranchesToDeleteEarly = opts.getUntrackedParameter<std::vector<std::string>>("canDeleteEarly",std::vector<std::string>());
00106       if(not vBranchesToDeleteEarly.empty()) {
00107         std::sort(vBranchesToDeleteEarly.begin(),vBranchesToDeleteEarly.end(),std::less<std::string>());
00108         vBranchesToDeleteEarly.erase(std::unique(vBranchesToDeleteEarly.begin(),vBranchesToDeleteEarly.end()),
00109                                      vBranchesToDeleteEarly.end());
00110         
00111         // Are the requested items in the product registry?
00112         auto allBranchNames = preg.allBranchNames();
00113         //the branch names all end with a period, which we do not want to compare with
00114         for(auto & b:allBranchNames) {
00115           b.resize(b.size()-1);
00116         }
00117         std::sort(allBranchNames.begin(),allBranchNames.end(),std::less<std::string>());
00118         std::vector<std::string> temp;
00119         temp.reserve(vBranchesToDeleteEarly.size());  
00120         
00121         std::set_intersection(vBranchesToDeleteEarly.begin(),vBranchesToDeleteEarly.end(),
00122                               allBranchNames.begin(),allBranchNames.end(),
00123                               std::back_inserter(temp));
00124         vBranchesToDeleteEarly.swap(temp);
00125         if(temp.size() != vBranchesToDeleteEarly.size()) {
00126           std::vector<std::string> missingProducts;
00127           std::set_difference(temp.begin(),temp.end(),
00128                               vBranchesToDeleteEarly.begin(),vBranchesToDeleteEarly.end(),
00129                               std::back_inserter(missingProducts));
00130           LogInfo l("MissingProductsForCanDeleteEarly");
00131           l<<"The following products in the 'canDeleteEarly' list are not available in this job and will be ignored.";
00132           for(auto const& n:missingProducts){
00133             l<<"\n "<<n;
00134           }
00135         }
00136         //set placeholder for the branch, we will remove the nullptr if a
00137         // module actually wants the branch.
00138         for(auto const& branch:vBranchesToDeleteEarly) {
00139           branchToReadingWorker.insert(make_pair(branch,nullptr));
00140         }
00141       }
00142     }
00143   }
00144 
00145   // -----------------------------
00146 
00147   typedef std::vector<std::string> vstring;
00148 
00149   // -----------------------------
00150 
00151   Schedule::Schedule(ParameterSet& proc_pset,
00152                      service::TriggerNamesService& tns,
00153                      ProductRegistry& preg,
00154                      ActionTable const& actions,
00155                      boost::shared_ptr<ActivityRegistry> areg,
00156                      boost::shared_ptr<ProcessConfiguration> processConfiguration,
00157                      const ParameterSet* subProcPSet) :
00158     worker_reg_(areg),
00159     act_table_(&actions),
00160     actReg_(areg),
00161     state_(Ready),
00162     trig_name_list_(tns.getTrigPaths()),
00163     end_path_name_list_(tns.getEndPaths()),
00164     results_(new HLTGlobalStatus(trig_name_list_.size())),
00165     endpath_results_(), // delay!
00166     results_inserter_(),
00167     all_workers_(),
00168     all_output_workers_(),
00169     trig_paths_(),
00170     end_paths_(),
00171     wantSummary_(tns.wantSummary()),
00172     total_events_(),
00173     total_passed_(),
00174     stopwatch_(wantSummary_? new RunStopwatch::StopwatchPointer::element_type : static_cast<RunStopwatch::StopwatchPointer::element_type*> (0)),
00175     unscheduled_(new UnscheduledCallProducer),
00176     endpathsAreActive_(true) {
00177 
00178     ParameterSet const& opts = proc_pset.getUntrackedParameterSet("options", ParameterSet());
00179     bool hasPath = false;
00180 
00181     int trig_bitpos = 0;
00182     vstring labelsOnTriggerPaths;
00183     for (vstring::const_iterator i = trig_name_list_.begin(),
00184            e = trig_name_list_.end();
00185          i != e;
00186          ++i) {
00187       fillTrigPath(proc_pset, preg, processConfiguration, trig_bitpos, *i, results_, &labelsOnTriggerPaths);
00188       ++trig_bitpos;
00189       hasPath = true;
00190     }
00191 
00192     if (hasPath) {
00193       // the results inserter stands alone
00194       results_inserter_ = makeInserter(proc_pset,
00195                                        preg,
00196                                        actions, actReg_, processConfiguration, results_);
00197       addToAllWorkers(results_inserter_.get());
00198     }
00199 
00200     TrigResPtr epptr(new HLTGlobalStatus(end_path_name_list_.size()));
00201     endpath_results_ = epptr;
00202 
00203     // fill normal endpaths
00204     vstring::iterator eib(end_path_name_list_.begin()), eie(end_path_name_list_.end());
00205     for (int bitpos = 0; eib != eie; ++eib, ++bitpos) {
00206       fillEndPath(proc_pset, preg, processConfiguration, bitpos, *eib);
00207     }
00208 
00209     //See if all modules were used
00210     std::set<std::string> usedWorkerLabels;
00211     for (AllWorkers::iterator itWorker = workersBegin();
00212         itWorker != workersEnd();
00213         ++itWorker) {
00214       usedWorkerLabels.insert((*itWorker)->description().moduleLabel());
00215     }
00216     std::vector<std::string> modulesInConfig(proc_pset.getParameter<std::vector<std::string> >("@all_modules"));
00217     std::set<std::string> modulesInConfigSet(modulesInConfig.begin(), modulesInConfig.end());
00218     std::vector<std::string> unusedLabels;
00219     set_difference(modulesInConfigSet.begin(), modulesInConfigSet.end(),
00220                    usedWorkerLabels.begin(), usedWorkerLabels.end(),
00221                    back_inserter(unusedLabels));
00222     //does the configuration say we should allow on demand?
00223     bool allowUnscheduled = opts.getUntrackedParameter<bool>("allowUnscheduled", false);
00224     std::set<std::string> unscheduledLabels;
00225     std::vector<std::string>  shouldBeUsedLabels;
00226     if (!unusedLabels.empty()) {
00227       //Need to
00228       // 1) create worker
00229       // 2) if it is a WorkerT<EDProducer>, add it to our list
00230       // 3) hand list to our delayed reader
00231 
00232       for (std::vector<std::string>::iterator itLabel = unusedLabels.begin(), itLabelEnd = unusedLabels.end();
00233           itLabel != itLabelEnd;
00234           ++itLabel) {
00235         if (allowUnscheduled) {
00236           bool isTracked;
00237           ParameterSet* modulePSet(proc_pset.getPSetForUpdate(*itLabel, isTracked));
00238           assert(isTracked);
00239           assert(modulePSet != 0);
00240           WorkerParams params(proc_pset, modulePSet, preg,
00241                               processConfiguration, *act_table_);
00242           Worker* newWorker(worker_reg_.getWorker(params, *itLabel));
00243           if (dynamic_cast<WorkerT<EDProducer>*>(newWorker) ||
00244               dynamic_cast<WorkerT<EDFilter>*>(newWorker)) {
00245             unscheduledLabels.insert(*itLabel);
00246             unscheduled_->addWorker(newWorker);
00247             //add to list so it gets reset each new event
00248             addToAllWorkers(newWorker);
00249           } else {
00250             //not a producer so should be marked as not used
00251             shouldBeUsedLabels.push_back(*itLabel);
00252           }
00253         } else {
00254           //everthing is marked are unused so no 'on demand' allowed
00255           shouldBeUsedLabels.push_back(*itLabel);
00256         }
00257       }
00258       if (!shouldBeUsedLabels.empty()) {
00259         std::ostringstream unusedStream;
00260         unusedStream << "'" << shouldBeUsedLabels.front() << "'";
00261         for (std::vector<std::string>::iterator itLabel = shouldBeUsedLabels.begin() + 1,
00262               itLabelEnd = shouldBeUsedLabels.end();
00263             itLabel != itLabelEnd;
00264             ++itLabel) {
00265           unusedStream << ",'" << *itLabel << "'";
00266         }
00267         LogInfo("path")
00268           << "The following module labels are not assigned to any path:\n"
00269           << unusedStream.str()
00270           << "\n";
00271       }
00272     }
00273     if (!unscheduledLabels.empty()) {
00274       for (ProductRegistry::ProductList::const_iterator it = preg.productList().begin(),
00275           itEnd = preg.productList().end();
00276           it != itEnd;
00277           ++it) {
00278         if (it->second.produced() &&
00279             it->second.branchType() == InEvent &&
00280             unscheduledLabels.end() != unscheduledLabels.find(it->second.moduleLabel())) {
00281           it->second.setOnDemand();
00282         }
00283       }
00284     }
00285 
00286     std::map<std::string, std::vector<std::pair<std::string, int> > > outputModulePathPositions;
00287     reduceParameterSet(proc_pset, modulesInConfig, modulesInConfigSet, labelsOnTriggerPaths, shouldBeUsedLabels, outputModulePathPositions);
00288 
00289     proc_pset.registerIt();
00290     pset::Registry::instance()->extra().setID(proc_pset.id());
00291     processConfiguration->setParameterSetID(proc_pset.id());
00292 
00293     initializeEarlyDelete(opts,preg,subProcPSet);
00294     
00295     // This is used for a little sanity-check to make sure no code
00296     // modifications alter the number of workers at a later date.
00297     size_t all_workers_count = all_workers_.size();
00298 
00299     for (AllWorkers::iterator i = all_workers_.begin(), e = all_workers_.end();
00300          i != e;
00301          ++i) {
00302 
00303       // All the workers should be in all_workers_ by this point. Thus
00304       // we can now fill all_output_workers_.
00305       OutputWorker* ow = dynamic_cast<OutputWorker*>(*i);
00306       if (ow) {
00307         all_output_workers_.push_back(ow);
00308       }
00309     }
00310     // Now that the output workers are filled in, set any output limits.
00311     limitOutput(proc_pset);
00312 
00313     loadMissingDictionaries();
00314     preg.setFrozen();
00315 
00316     for (AllOutputWorkers::iterator i = all_output_workers_.begin(), e = all_output_workers_.end();
00317          i != e; ++i) {
00318       (*i)->setEventSelectionInfo(outputModulePathPositions, preg.anyProductProduced());
00319     }
00320 
00321     // Sanity check: make sure nobody has added a worker after we've
00322     // already relied on all_workers_ being full.
00323     assert (all_workers_count == all_workers_.size());
00324 
00325     ProcessConfigurationRegistry::instance()->insertMapped(*processConfiguration);
00326     BranchIDListHelper::updateRegistries(preg);
00327     fillProductRegistryTransients(*processConfiguration, preg);
00328   } // Schedule::Schedule
00329 
00330   
00331   void Schedule::initializeEarlyDelete(edm::ParameterSet const& opts, edm::ProductRegistry const& preg, 
00332                                        edm::ParameterSet const* subProcPSet) {
00333     //for now, if have a subProcess, don't allow early delete
00334     // In the future we should use the SubProcess's 'keep list' to decide what can be kept
00335     if(subProcPSet)  return;
00336 
00337     //see if 'canDeleteEarly' was set and if so setup the list with those products actually
00338     // registered for this job
00339     std::multimap<std::string,Worker*> branchToReadingWorker;
00340     initializeBranchToReadingWorker(opts,preg,branchToReadingWorker);
00341     
00342     //If no delete early items have been specified we don't have to do anything
00343     if(branchToReadingWorker.size()==0) {
00344       return;
00345     }
00346     const std::vector<std::string> kEmpty;
00347     std::map<Worker*,unsigned int> reserveSizeForWorker;
00348     unsigned int upperLimitOnReadingWorker =0;
00349     unsigned int upperLimitOnIndicies = 0;
00350     unsigned int nUniqueBranchesToDelete=branchToReadingWorker.size();
00351     for (AllWorkers::iterator i = all_workers_.begin(), e = all_workers_.end();
00352          i != e;
00353          ++i) {
00354       OutputWorker* ow = dynamic_cast<OutputWorker*>(*i);
00355       if (ow) {
00356         if(branchToReadingWorker.size()>0) {
00357           //If an OutputModule needs a product, we can't delete it early
00358           // so we should remove it from our list
00359           SelectionsArray const&kept = ow->keptProducts();
00360           for( auto const& item: kept[InEvent]) {
00361             auto found = branchToReadingWorker.equal_range(item->branchName());
00362             if(found.first !=found.second) {
00363               --nUniqueBranchesToDelete;
00364               branchToReadingWorker.erase(found.first,found.second);
00365             }
00366           }
00367         }
00368       } else {
00369         if(branchToReadingWorker.size()>0) {
00370           //determine if this module could read a branch we want to delete early
00371           auto pset = pset::Registry::instance()->getMapped((*i)->description().parameterSetID());
00372           if(0!=pset) {
00373             auto branches = pset->getUntrackedParameter<std::vector<std::string>>("mightGet",kEmpty);
00374             if(not branches.empty()) {
00375               ++upperLimitOnReadingWorker;
00376             }
00377             for(auto const& branch:branches){ 
00378               auto found = branchToReadingWorker.equal_range(branch);
00379               if(found.first != found.second) {
00380                 ++upperLimitOnIndicies;
00381                 ++reserveSizeForWorker[*i];
00382                 if(nullptr == found.first->second) {
00383                   found.first->second = *i;
00384                 } else {
00385                   branchToReadingWorker.insert(make_pair(found.first->first,*i));
00386                 }
00387               }
00388             }
00389           }
00390         }
00391       }
00392     }
00393     {
00394       auto it = branchToReadingWorker.begin();
00395       std::vector<std::string> unusedBranches;
00396       while(it !=branchToReadingWorker.end()) {
00397         if(it->second == nullptr) {
00398           unusedBranches.push_back(it->first);
00399           //erasing the object invalidates the iterator so must advance it first
00400           auto temp = it;
00401           ++it;
00402           branchToReadingWorker.erase(temp);
00403         } else {
00404           ++it;
00405         }
00406       }
00407       if(not unusedBranches.empty()) {
00408         LogWarning l("UnusedProductsForCanDeleteEarly");
00409         l<<"The following products in the 'canDeleteEarly' list are not used in this job and will be ignored.\n"
00410         " If possible, remove the producer from the job or add the product to the producer's own 'mightGet' list.";
00411         for(auto const& n:unusedBranches){
00412           l<<"\n "<<n;
00413         }
00414       }
00415     }  
00416     if(0!=branchToReadingWorker.size()) {
00417       earlyDeleteHelpers_.reserve(upperLimitOnReadingWorker);
00418       earlyDeleteHelperToBranchIndicies_.resize(upperLimitOnIndicies,0);
00419       earlyDeleteBranchToCount_.reserve(nUniqueBranchesToDelete);
00420       std::map<const Worker*,EarlyDeleteHelper*> alreadySeenWorkers;
00421       std::string lastBranchName;
00422       size_t nextOpenIndex = 0;
00423       unsigned int* beginAddress = &(earlyDeleteHelperToBranchIndicies_.front());
00424       for(auto& branchAndWorker:branchToReadingWorker) {
00425         if(lastBranchName != branchAndWorker.first) {
00426           //have to put back the period we removed earlier in order to get the proper name
00427           BranchID bid(branchAndWorker.first+".");
00428           earlyDeleteBranchToCount_.emplace_back(std::make_pair(bid,0U));
00429           lastBranchName = branchAndWorker.first;
00430         }
00431         auto found = alreadySeenWorkers.find(branchAndWorker.second);
00432         if(alreadySeenWorkers.end() == found) {
00433           //NOTE: we will set aside enough space in earlyDeleteHelperToBranchIndicies_ to accommodate
00434           // all the branches that might be read by this worker. However, initially we will only tell the
00435           // EarlyDeleteHelper about the first one. As additional branches are added via 'appendIndex' the
00436           // EarlyDeleteHelper will automatically advance its internal end pointer.
00437           size_t index = nextOpenIndex;
00438           size_t nIndices = reserveSizeForWorker[branchAndWorker.second];
00439           earlyDeleteHelperToBranchIndicies_[index]=earlyDeleteBranchToCount_.size()-1;
00440           earlyDeleteHelpers_.emplace_back(EarlyDeleteHelper(beginAddress+index,
00441                                                              beginAddress+index+1,
00442                                                              &earlyDeleteBranchToCount_));
00443           branchAndWorker.second->setEarlyDeleteHelper(&(earlyDeleteHelpers_.back()));
00444           alreadySeenWorkers.insert(std::make_pair(branchAndWorker.second,&(earlyDeleteHelpers_.back())));
00445           nextOpenIndex +=nIndices;
00446         } else {
00447           found->second->appendIndex(earlyDeleteBranchToCount_.size()-1);
00448         }
00449       }
00450       
00451       //Now we can compactify the earlyDeleteHelperToBranchIndicies_ since we may have over estimated the
00452       // space needed for each module
00453       auto itLast = earlyDeleteHelpers_.begin();
00454       for(auto it = earlyDeleteHelpers_.begin()+1;it != earlyDeleteHelpers_.end();++it) {
00455         if(itLast->end() != it->begin()) {
00456           //figure the offset for next Worker since it hasn't been moved yet so it has the original address
00457           unsigned int delta = it->begin()- itLast->end();
00458           it->shiftIndexPointers(delta);
00459           
00460           earlyDeleteHelperToBranchIndicies_.erase(earlyDeleteHelperToBranchIndicies_.begin()+
00461                                                    (itLast->end()-beginAddress),
00462                                                    earlyDeleteHelperToBranchIndicies_.begin()+
00463                                                    (it->begin()-beginAddress));
00464         }
00465         itLast = it;
00466       }
00467       earlyDeleteHelperToBranchIndicies_.erase(earlyDeleteHelperToBranchIndicies_.begin()+(itLast->end()-beginAddress),
00468                                                earlyDeleteHelperToBranchIndicies_.end());
00469       
00470       //now tell the paths about the deleters
00471       for(auto& p : trig_paths_) {
00472         p.setEarlyDeleteHelpers(alreadySeenWorkers);
00473       }
00474       for(auto& p : end_paths_) {
00475         p.setEarlyDeleteHelpers(alreadySeenWorkers);
00476       }
00477       resetEarlyDelete();
00478     }
00479   }
00480 
00481   void Schedule::reduceParameterSet(ParameterSet& proc_pset,
00482                                     vstring& modulesInConfig,
00483                                     std::set<std::string> const& modulesInConfigSet,
00484                                     vstring& labelsOnTriggerPaths,
00485                                     vstring& shouldBeUsedLabels,
00486                                     std::map<std::string, std::vector<std::pair<std::string, int> > >& outputModulePathPositions) {
00487 
00488     // Before calculating the ParameterSetID of the top level ParameterSet or
00489     // saving it in the registry drop from the top level ParameterSet all
00490     // OutputModules and EDAnalyzers not on trigger paths. If unscheduled
00491     // production is not enabled also drop all the EDFilters and EDProducers
00492     // that are not scheduled. Drop the ParameterSet used to configure the module
00493     // itself. Also drop the other traces of these labels in the top level
00494     // ParameterSet: Remove that labels from @all_modules and from all the
00495     // end paths. If this makes any end paths empty, then remove the end path
00496     // name from @end_paths, and @paths.
00497 
00498     // First make a list of labels to drop
00499     vstring labelsToBeDropped;
00500     vstring outputModuleLabels;
00501     std::string edmType;
00502     std::string const moduleEdmType("@module_edm_type");
00503     std::string const outputModule("OutputModule");
00504     std::string const edAnalyzer("EDAnalyzer");
00505     std::string const edFilter("EDFilter");
00506     std::string const edProducer("EDProducer");
00507     sort_all(labelsOnTriggerPaths);
00508     vstring::const_iterator iLabelsOnTriggerPaths = labelsOnTriggerPaths.begin();
00509     vstring::const_iterator endLabelsOnTriggerPaths = labelsOnTriggerPaths.end();
00510     sort_all(shouldBeUsedLabels);
00511     vstring::const_iterator iShouldBeUsedLabels = shouldBeUsedLabels.begin();
00512     vstring::const_iterator endShouldBeUsedLabels = shouldBeUsedLabels.end();
00513 
00514     for (std::set<std::string>::const_iterator i = modulesInConfigSet.begin(),
00515            e = modulesInConfigSet.end(); i != e; ++i) {
00516       edmType = proc_pset.getParameterSet(*i).getParameter<std::string>(moduleEdmType);
00517       if (edmType == outputModule) {
00518         labelsToBeDropped.push_back(*i);
00519         outputModuleLabels.push_back(*i);
00520       }
00521       else if (edmType == edAnalyzer) {
00522         while (iLabelsOnTriggerPaths != endLabelsOnTriggerPaths &&
00523                *iLabelsOnTriggerPaths < *i) {
00524           ++iLabelsOnTriggerPaths;
00525         }
00526         if (iLabelsOnTriggerPaths == endLabelsOnTriggerPaths ||
00527             *iLabelsOnTriggerPaths != *i) {
00528           labelsToBeDropped.push_back(*i);
00529         }
00530       }
00531       else if (edmType == edFilter || edmType == edProducer) {
00532         while (iShouldBeUsedLabels != endShouldBeUsedLabels &&
00533                *iShouldBeUsedLabels < *i) {
00534           ++iShouldBeUsedLabels;
00535         }
00536         if (iShouldBeUsedLabels != endShouldBeUsedLabels &&
00537             *iShouldBeUsedLabels == *i) {
00538           labelsToBeDropped.push_back(*i);
00539         }
00540       }
00541     }
00542 
00543     // drop the parameter sets used to configure the modules
00544     for_all(labelsToBeDropped, boost::bind(&ParameterSet::eraseOrSetUntrackedParameterSet, boost::ref(proc_pset), _1));
00545 
00546     // drop the labels from @all_modules
00547     vstring::iterator endAfterRemove = std::remove_if(modulesInConfig.begin(), modulesInConfig.end(), boost::bind(binary_search_string, boost::ref(labelsToBeDropped), _1));
00548     modulesInConfig.erase(endAfterRemove, modulesInConfig.end());
00549     proc_pset.addParameter<vstring>(std::string("@all_modules"), modulesInConfig);
00550 
00551     // drop the labels from all end paths
00552     vstring endPathsToBeDropped;
00553     vstring labels;
00554     for (vstring::iterator iEndPath = end_path_name_list_.begin(), endEndPath = end_path_name_list_.end();
00555          iEndPath != endEndPath;
00556          ++iEndPath) {
00557       labels = proc_pset.getParameter<vstring>(*iEndPath);
00558       vstring::iterator iSave = labels.begin();
00559       vstring::iterator iBegin = labels.begin();
00560 
00561       for (vstring::iterator iLabel = labels.begin(), iEnd = labels.end();
00562            iLabel != iEnd; ++iLabel) {
00563         if (binary_search_string(labelsToBeDropped, *iLabel)) {
00564           if (binary_search_string(outputModuleLabels, *iLabel)) {
00565             outputModulePathPositions[*iLabel].push_back(std::pair<std::string, int>(*iEndPath, iSave - iBegin));
00566           }
00567         } else {
00568           if (iSave != iLabel) {
00569             iSave->swap(*iLabel);
00570           }
00571           ++iSave;
00572         }
00573       }
00574       labels.erase(iSave, labels.end());
00575       if (labels.empty()) {
00576         // remove empty end paths and save their names
00577         proc_pset.eraseSimpleParameter(*iEndPath);
00578         endPathsToBeDropped.push_back(*iEndPath);
00579       } else {
00580         proc_pset.addParameter<vstring>(*iEndPath, labels);
00581       }
00582     }
00583     sort_all(endPathsToBeDropped);
00584     
00585     // remove empty end paths from @paths
00586     vstring scheduledPaths = proc_pset.getParameter<vstring>("@paths");
00587     endAfterRemove = std::remove_if(scheduledPaths.begin(), scheduledPaths.end(), boost::bind(binary_search_string, boost::ref(endPathsToBeDropped), _1));
00588     scheduledPaths.erase(endAfterRemove, scheduledPaths.end());
00589     proc_pset.addParameter<vstring>(std::string("@paths"), scheduledPaths);
00590 
00591     // remove empty end paths from @end_paths
00592     vstring scheduledEndPaths = proc_pset.getParameter<vstring>("@end_paths");
00593     endAfterRemove = std::remove_if(scheduledEndPaths.begin(), scheduledEndPaths.end(), boost::bind(binary_search_string, boost::ref(endPathsToBeDropped), _1));
00594     scheduledEndPaths.erase(endAfterRemove, scheduledEndPaths.end());
00595     proc_pset.addParameter<vstring>(std::string("@end_paths"), scheduledEndPaths);
00596   }
00597 
00598   void
00599   Schedule::limitOutput(ParameterSet const& proc_pset) {
00600     std::string const output("output");
00601 
00602     ParameterSet const& maxEventsPSet = proc_pset.getUntrackedParameterSet("maxEvents", ParameterSet());
00603     int maxEventSpecs = 0;
00604     int maxEventsOut = -1;
00605     ParameterSet const* vMaxEventsOut = 0;
00606     std::vector<std::string> intNamesE = maxEventsPSet.getParameterNamesForType<int>(false);
00607     if (search_all(intNamesE, output)) {
00608       maxEventsOut = maxEventsPSet.getUntrackedParameter<int>(output);
00609       ++maxEventSpecs;
00610     }
00611     std::vector<std::string> psetNamesE;
00612     maxEventsPSet.getParameterSetNames(psetNamesE, false);
00613     if (search_all(psetNamesE, output)) {
00614       vMaxEventsOut = &maxEventsPSet.getUntrackedParameterSet(output);
00615       ++maxEventSpecs;
00616     }
00617 
00618     if (maxEventSpecs > 1) {
00619       throw Exception(errors::Configuration) <<
00620         "\nAt most, one form of 'output' may appear in the 'maxEvents' parameter set";
00621     }
00622 
00623     if (maxEventSpecs == 0) {
00624       return;
00625     }
00626 
00627     for (AllOutputWorkers::const_iterator it = all_output_workers_.begin(), itEnd = all_output_workers_.end();
00628         it != itEnd; ++it) {
00629       OutputModuleDescription desc(maxEventsOut);
00630       if (vMaxEventsOut != 0 && !vMaxEventsOut->empty()) {
00631         std::string moduleLabel = (*it)->description().moduleLabel();
00632         try {
00633           desc.maxEvents_ = vMaxEventsOut->getUntrackedParameter<int>(moduleLabel);
00634         } catch (Exception const&) {
00635           throw Exception(errors::Configuration) <<
00636             "\nNo entry in 'maxEvents' for output module label '" << moduleLabel << "'.\n";
00637         }
00638       }
00639       (*it)->configure(desc);
00640     }
00641   }
00642 
00643   bool Schedule::terminate() const {
00644     if (all_output_workers_.empty()) {
00645       return false;
00646     }
00647     for (AllOutputWorkers::const_iterator it = all_output_workers_.begin(),
00648          itEnd = all_output_workers_.end();
00649          it != itEnd; ++it) {
00650       if (!(*it)->limitReached()) {
00651         // Found an output module that has not reached output event count.
00652         return false;
00653       }
00654     }
00655     LogInfo("SuccessfulTermination")
00656       << "The job is terminating successfully because each output module\n"
00657       << "has reached its configured limit.\n";
00658     return true;
00659   }
00660 
00661   void Schedule::fillWorkers(ParameterSet& proc_pset,
00662                              ProductRegistry& preg,
00663                              boost::shared_ptr<ProcessConfiguration const> processConfiguration,
00664                              std::string const& name,
00665                              bool ignoreFilters,
00666                              PathWorkers& out,
00667                              vstring* labelsOnPaths) {
00668     vstring modnames = proc_pset.getParameter<vstring>(name);
00669     vstring::iterator it(modnames.begin()), ie(modnames.end());
00670     PathWorkers tmpworkers;
00671 
00672     for (; it != ie; ++it) {
00673 
00674       if (labelsOnPaths) labelsOnPaths->push_back(*it);
00675 
00676       WorkerInPath::FilterAction filterAction = WorkerInPath::Normal;
00677       if ((*it)[0] == '!')       filterAction = WorkerInPath::Veto;
00678       else if ((*it)[0] == '-')  filterAction = WorkerInPath::Ignore;
00679 
00680       std::string moduleLabel = *it;
00681       if (filterAction != WorkerInPath::Normal) moduleLabel.erase(0, 1);
00682 
00683       bool isTracked;
00684       ParameterSet* modpset = proc_pset.getPSetForUpdate(moduleLabel, isTracked);
00685       if (modpset == 0) {
00686         std::string pathType("endpath");
00687         if (!search_all(end_path_name_list_, name)) {
00688           pathType = std::string("path");
00689         }
00690         throw Exception(errors::Configuration) <<
00691           "The unknown module label \"" << moduleLabel <<
00692           "\" appears in " << pathType << " \"" << name <<
00693           "\"\n please check spelling or remove that label from the path.";
00694       }
00695       assert(isTracked);
00696 
00697       WorkerParams params(proc_pset, modpset, preg, processConfiguration, *act_table_);
00698       Worker* worker = worker_reg_.getWorker(params, moduleLabel);
00699       if (ignoreFilters && filterAction != WorkerInPath::Ignore && dynamic_cast<WorkerT<EDFilter>*>(worker)) {
00700         // We have a filter on an end path, and the filter is not explicitly ignored.
00701         // See if the filter is allowed.
00702         std::vector<std::string> allowed_filters = proc_pset.getUntrackedParameter<vstring>("@filters_on_endpaths");
00703         if (!search_all(allowed_filters, worker->description().moduleName())) {
00704           // Filter is not allowed. Ignore the result, and issue a warning.
00705           filterAction = WorkerInPath::Ignore;
00706           LogWarning("FilterOnEndPath")
00707             << "The EDFilter '" << worker->description().moduleName() << "' with module label '" << moduleLabel << "' appears on EndPath '" << name << "'.\n"
00708             << "The return value of the filter will be ignored.\n"
00709             << "To suppress this warning, either remove the filter from the endpath,\n"
00710             << "or explicitly ignore it in the configuration by using cms.ignore().\n";
00711         }
00712       }
00713       WorkerInPath w(worker, filterAction);
00714       tmpworkers.push_back(w);
00715     }
00716 
00717     out.swap(tmpworkers);
00718   }
00719 
00720   void Schedule::fillTrigPath(ParameterSet& proc_pset,
00721                               ProductRegistry& preg,
00722                               boost::shared_ptr<ProcessConfiguration const> processConfiguration,
00723                               int bitpos, std::string const& name, TrigResPtr trptr,
00724                               vstring* labelsOnTriggerPaths) {
00725     PathWorkers tmpworkers;
00726     Workers holder;
00727     fillWorkers(proc_pset, preg, processConfiguration, name, false, tmpworkers, labelsOnTriggerPaths);
00728 
00729     for (PathWorkers::iterator wi(tmpworkers.begin()),
00730           we(tmpworkers.end()); wi != we; ++wi) {
00731       holder.push_back(wi->getWorker());
00732     }
00733 
00734     // an empty path will cause an extra bit that is not used
00735     if (!tmpworkers.empty()) {
00736       Path p(bitpos, name, tmpworkers, trptr, *act_table_, actReg_, false);
00737       if (wantSummary_) {
00738         p.useStopwatch();
00739       }
00740       trig_paths_.push_back(p);
00741     }
00742     for_all(holder, boost::bind(&Schedule::addToAllWorkers, this, _1));
00743   }
00744 
00745   void Schedule::fillEndPath(ParameterSet& proc_pset,
00746                              ProductRegistry& preg,
00747                              boost::shared_ptr<ProcessConfiguration const> processConfiguration,
00748                              int bitpos, std::string const& name) {
00749     PathWorkers tmpworkers;
00750     fillWorkers(proc_pset, preg, processConfiguration, name, true, tmpworkers, 0);
00751     Workers holder;
00752 
00753     for (PathWorkers::iterator wi(tmpworkers.begin()), we(tmpworkers.end()); wi != we; ++wi) {
00754       holder.push_back(wi->getWorker());
00755     }
00756 
00757     if (!tmpworkers.empty()) {
00758       Path p(bitpos, name, tmpworkers, endpath_results_, *act_table_, actReg_, true);
00759       if (wantSummary_) {
00760         p.useStopwatch();
00761       }
00762       end_paths_.push_back(p);
00763     }
00764     for_all(holder, boost::bind(&Schedule::addToAllWorkers, this, _1));
00765   }
00766 
00767   void Schedule::endJob(ExceptionCollector & collector) {
00768     bool failure = false;
00769     AllWorkers::iterator ai(workersBegin()), ae(workersEnd());
00770     for (; ai != ae; ++ai) {
00771       try {
00772         try {
00773           (*ai)->endJob();
00774         }
00775         catch (cms::Exception& e) { throw; }
00776         catch (std::bad_alloc& bda) { convertException::badAllocToEDM(); }
00777         catch (std::exception& e) { convertException::stdToEDM(e); }
00778         catch (std::string& s) { convertException::stringToEDM(s); }
00779         catch (char const* c) { convertException::charPtrToEDM(c); }
00780         catch (...) { convertException::unknownToEDM(); }
00781       }      
00782       catch (cms::Exception const& ex) {
00783         collector.addException(ex);
00784         failure = true;
00785       }
00786     }
00787     if (failure) {
00788       return;
00789     }
00790 
00791     if (wantSummary_ == false) return;
00792 
00793     TrigPaths::const_iterator pi, pe;
00794 
00795     // The trigger report (pass/fail etc.):
00796 
00797     LogVerbatim("FwkSummary") << "";
00798     LogVerbatim("FwkSummary") << "TrigReport " << "---------- Event  Summary ------------";
00799     LogVerbatim("FwkSummary") << "TrigReport"
00800                               << " Events total = " << totalEvents()
00801                               << " passed = " << totalEventsPassed()
00802                               << " failed = " << (totalEventsFailed())
00803                               << "";
00804 
00805     LogVerbatim("FwkSummary") << "";
00806     LogVerbatim("FwkSummary") << "TrigReport " << "---------- Path   Summary ------------";
00807     LogVerbatim("FwkSummary") << "TrigReport "
00808                               << std::right << std::setw(10) << "Trig Bit#" << " "
00809                               << std::right << std::setw(10) << "Run" << " "
00810                               << std::right << std::setw(10) << "Passed" << " "
00811                               << std::right << std::setw(10) << "Failed" << " "
00812                               << std::right << std::setw(10) << "Error" << " "
00813                               << "Name" << "";
00814     pi = trig_paths_.begin();
00815     pe = trig_paths_.end();
00816     for (; pi != pe; ++pi) {
00817       LogVerbatim("FwkSummary") << "TrigReport "
00818                                 << std::right << std::setw(5) << 1
00819                                 << std::right << std::setw(5) << pi->bitPosition() << " "
00820                                 << std::right << std::setw(10) << pi->timesRun() << " "
00821                                 << std::right << std::setw(10) << pi->timesPassed() << " "
00822                                 << std::right << std::setw(10) << pi->timesFailed() << " "
00823                                 << std::right << std::setw(10) << pi->timesExcept() << " "
00824                                 << pi->name() << "";
00825     }
00826 
00827     LogVerbatim("FwkSummary") << "";
00828     LogVerbatim("FwkSummary") << "TrigReport " << "-------End-Path   Summary ------------";
00829     LogVerbatim("FwkSummary") << "TrigReport "
00830                               << std::right << std::setw(10) << "Trig Bit#" << " "
00831                               << std::right << std::setw(10) << "Run" << " "
00832                               << std::right << std::setw(10) << "Passed" << " "
00833                               << std::right << std::setw(10) << "Failed" << " "
00834                               << std::right << std::setw(10) << "Error" << " "
00835                               << "Name" << "";
00836     pi = end_paths_.begin();
00837     pe = end_paths_.end();
00838     for (; pi != pe; ++pi) {
00839       LogVerbatim("FwkSummary") << "TrigReport "
00840                                 << std::right << std::setw(5) << 0
00841                                 << std::right << std::setw(5) << pi->bitPosition() << " "
00842                                 << std::right << std::setw(10) << pi->timesRun() << " "
00843                                 << std::right << std::setw(10) << pi->timesPassed() << " "
00844                                 << std::right << std::setw(10) << pi->timesFailed() << " "
00845                                 << std::right << std::setw(10) << pi->timesExcept() << " "
00846                                 << pi->name() << "";
00847     }
00848 
00849     pi = trig_paths_.begin();
00850     pe = trig_paths_.end();
00851     for (; pi != pe; ++pi) {
00852       LogVerbatim("FwkSummary") << "";
00853       LogVerbatim("FwkSummary") << "TrigReport " << "---------- Modules in Path: " << pi->name() << " ------------";
00854       LogVerbatim("FwkSummary") << "TrigReport "
00855                                 << std::right << std::setw(10) << "Trig Bit#" << " "
00856                                 << std::right << std::setw(10) << "Visited" << " "
00857                                 << std::right << std::setw(10) << "Passed" << " "
00858                                 << std::right << std::setw(10) << "Failed" << " "
00859                                 << std::right << std::setw(10) << "Error" << " "
00860                                 << "Name" << "";
00861 
00862       for (unsigned int i = 0; i < pi->size(); ++i) {
00863         LogVerbatim("FwkSummary") << "TrigReport "
00864                                   << std::right << std::setw(5) << 1
00865                                   << std::right << std::setw(5) << pi->bitPosition() << " "
00866                                   << std::right << std::setw(10) << pi->timesVisited(i) << " "
00867                                   << std::right << std::setw(10) << pi->timesPassed(i) << " "
00868                                   << std::right << std::setw(10) << pi->timesFailed(i) << " "
00869                                   << std::right << std::setw(10) << pi->timesExcept(i) << " "
00870                                   << pi->getWorker(i)->description().moduleLabel() << "";
00871       }
00872     }
00873 
00874     pi = end_paths_.begin();
00875     pe = end_paths_.end();
00876     for (; pi != pe; ++pi) {
00877       LogVerbatim("FwkSummary") << "";
00878       LogVerbatim("FwkSummary") << "TrigReport " << "------ Modules in End-Path: " << pi->name() << " ------------";
00879       LogVerbatim("FwkSummary") << "TrigReport "
00880                                 << std::right << std::setw(10) << "Trig Bit#" << " "
00881                                 << std::right << std::setw(10) << "Visited" << " "
00882                                 << std::right << std::setw(10) << "Passed" << " "
00883                                 << std::right << std::setw(10) << "Failed" << " "
00884                                 << std::right << std::setw(10) << "Error" << " "
00885                                 << "Name" << "";
00886 
00887       for (unsigned int i = 0; i < pi->size(); ++i) {
00888         LogVerbatim("FwkSummary") << "TrigReport "
00889                                   << std::right << std::setw(5) << 0
00890                                   << std::right << std::setw(5) << pi->bitPosition() << " "
00891                                   << std::right << std::setw(10) << pi->timesVisited(i) << " "
00892                                   << std::right << std::setw(10) << pi->timesPassed(i) << " "
00893                                   << std::right << std::setw(10) << pi->timesFailed(i) << " "
00894                                   << std::right << std::setw(10) << pi->timesExcept(i) << " "
00895                                   << pi->getWorker(i)->description().moduleLabel() << "";
00896       }
00897     }
00898 
00899     LogVerbatim("FwkSummary") << "";
00900     LogVerbatim("FwkSummary") << "TrigReport " << "---------- Module Summary ------------";
00901     LogVerbatim("FwkSummary") << "TrigReport "
00902                               << std::right << std::setw(10) << "Visited" << " "
00903                               << std::right << std::setw(10) << "Run" << " "
00904                               << std::right << std::setw(10) << "Passed" << " "
00905                               << std::right << std::setw(10) << "Failed" << " "
00906                               << std::right << std::setw(10) << "Error" << " "
00907                               << "Name" << "";
00908     ai = workersBegin();
00909     ae = workersEnd();
00910     for (; ai != ae; ++ai) {
00911       LogVerbatim("FwkSummary") << "TrigReport "
00912                                 << std::right << std::setw(10) << (*ai)->timesVisited() << " "
00913                                 << std::right << std::setw(10) << (*ai)->timesRun() << " "
00914                                 << std::right << std::setw(10) << (*ai)->timesPassed() << " "
00915                                 << std::right << std::setw(10) << (*ai)->timesFailed() << " "
00916                                 << std::right << std::setw(10) << (*ai)->timesExcept() << " "
00917                                 << (*ai)->description().moduleLabel() << "";
00918 
00919     }
00920     LogVerbatim("FwkSummary") << "";
00921 
00922     // The timing report (CPU and Real Time):
00923 
00924     LogVerbatim("FwkSummary") << "TimeReport " << "---------- Event  Summary ---[sec]----";
00925     LogVerbatim("FwkSummary") << "TimeReport"
00926                               << std::setprecision(6) << std::fixed
00927                               << " CPU/event = " << timeCpuReal().first/std::max(1, totalEvents())
00928                               << " Real/event = " << timeCpuReal().second/std::max(1, totalEvents())
00929                               << "";
00930 
00931     LogVerbatim("FwkSummary") << "";
00932     LogVerbatim("FwkSummary") << "TimeReport " << "---------- Path   Summary ---[sec]----";
00933     LogVerbatim("FwkSummary") << "TimeReport "
00934                               << std::right << std::setw(22) << "per event "
00935                               << std::right << std::setw(22) << "per path-run "
00936                               << "";
00937     LogVerbatim("FwkSummary") << "TimeReport "
00938                               << std::right << std::setw(10) << "CPU" << " "
00939                               << std::right << std::setw(10) << "Real" << " "
00940                               << std::right << std::setw(10) << "CPU" << " "
00941                               << std::right << std::setw(10) << "Real" << " "
00942                               << "Name" << "";
00943     pi = trig_paths_.begin();
00944     pe = trig_paths_.end();
00945     for (; pi != pe; ++pi) {
00946       LogVerbatim("FwkSummary") << "TimeReport "
00947                                 << std::setprecision(6) << std::fixed
00948                                 << std::right << std::setw(10) << pi->timeCpuReal().first/std::max(1, totalEvents()) << " "
00949                                 << std::right << std::setw(10) << pi->timeCpuReal().second/std::max(1, totalEvents()) << " "
00950                                 << std::right << std::setw(10) << pi->timeCpuReal().first/std::max(1, pi->timesRun()) << " "
00951                                 << std::right << std::setw(10) << pi->timeCpuReal().second/std::max(1, pi->timesRun()) << " "
00952                                 << pi->name() << "";
00953     }
00954     LogVerbatim("FwkSummary") << "TimeReport "
00955                               << std::right << std::setw(10) << "CPU" << " "
00956                               << std::right << std::setw(10) << "Real" << " "
00957                               << std::right << std::setw(10) << "CPU" << " "
00958                               << std::right << std::setw(10) << "Real" << " "
00959                               << "Name" << "";
00960     LogVerbatim("FwkSummary") << "TimeReport "
00961                               << std::right << std::setw(22) << "per event "
00962                               << std::right << std::setw(22) << "per path-run "
00963                               << "";
00964 
00965     LogVerbatim("FwkSummary") << "";
00966     LogVerbatim("FwkSummary") << "TimeReport " << "-------End-Path   Summary ---[sec]----";
00967     LogVerbatim("FwkSummary") << "TimeReport "
00968                               << std::right << std::setw(22) << "per event "
00969                               << std::right << std::setw(22) << "per endpath-run "
00970                               << "";
00971     LogVerbatim("FwkSummary") << "TimeReport "
00972                               << std::right << std::setw(10) << "CPU" << " "
00973                               << std::right << std::setw(10) << "Real" << " "
00974                               << std::right << std::setw(10) << "CPU" << " "
00975                               << std::right << std::setw(10) << "Real" << " "
00976                               << "Name" << "";
00977     pi = end_paths_.begin();
00978     pe = end_paths_.end();
00979     for (; pi != pe; ++pi) {
00980       LogVerbatim("FwkSummary") << "TimeReport "
00981                                 << std::setprecision(6) << std::fixed
00982                                 << std::right << std::setw(10) << pi->timeCpuReal().first/std::max(1, totalEvents()) << " "
00983                                 << std::right << std::setw(10) << pi->timeCpuReal().second/std::max(1, totalEvents()) << " "
00984                                 << std::right << std::setw(10) << pi->timeCpuReal().first/std::max(1, pi->timesRun()) << " "
00985                                 << std::right << std::setw(10) << pi->timeCpuReal().second/std::max(1, pi->timesRun()) << " "
00986                                 << pi->name() << "";
00987     }
00988     LogVerbatim("FwkSummary") << "TimeReport "
00989                               << std::right << std::setw(10) << "CPU" << " "
00990                               << std::right << std::setw(10) << "Real" << " "
00991                               << std::right << std::setw(10) << "CPU" << " "
00992                               << std::right << std::setw(10) << "Real" << " "
00993                               << "Name" << "";
00994     LogVerbatim("FwkSummary") << "TimeReport "
00995                               << std::right << std::setw(22) << "per event "
00996                               << std::right << std::setw(22) << "per endpath-run "
00997                               << "";
00998 
00999     pi = trig_paths_.begin();
01000     pe = trig_paths_.end();
01001     for (; pi != pe; ++pi) {
01002       LogVerbatim("FwkSummary") << "";
01003       LogVerbatim("FwkSummary") << "TimeReport " << "---------- Modules in Path: " << pi->name() << " ---[sec]----";
01004       LogVerbatim("FwkSummary") << "TimeReport "
01005                                 << std::right << std::setw(22) << "per event "
01006                                 << std::right << std::setw(22) << "per module-visit "
01007                                 << "";
01008       LogVerbatim("FwkSummary") << "TimeReport "
01009                                 << std::right << std::setw(10) << "CPU" << " "
01010                                 << std::right << std::setw(10) << "Real" << " "
01011                                 << std::right << std::setw(10) << "CPU" << " "
01012                                 << std::right << std::setw(10) << "Real" << " "
01013                                 << "Name" << "";
01014       for (unsigned int i = 0; i < pi->size(); ++i) {
01015         LogVerbatim("FwkSummary") << "TimeReport "
01016                                   << std::setprecision(6) << std::fixed
01017                                   << std::right << std::setw(10) << pi->timeCpuReal(i).first/std::max(1, totalEvents()) << " "
01018                                   << std::right << std::setw(10) << pi->timeCpuReal(i).second/std::max(1, totalEvents()) << " "
01019                                   << std::right << std::setw(10) << pi->timeCpuReal(i).first/std::max(1, pi->timesVisited(i)) << " "
01020                                   << std::right << std::setw(10) << pi->timeCpuReal(i).second/std::max(1, pi->timesVisited(i)) << " "
01021                                   << pi->getWorker(i)->description().moduleLabel() << "";
01022       }
01023     }
01024     LogVerbatim("FwkSummary") << "TimeReport "
01025                               << std::right << std::setw(10) << "CPU" << " "
01026                               << std::right << std::setw(10) << "Real" << " "
01027                               << std::right << std::setw(10) << "CPU" << " "
01028                               << std::right << std::setw(10) << "Real" << " "
01029                               << "Name" << "";
01030     LogVerbatim("FwkSummary") << "TimeReport "
01031                               << std::right << std::setw(22) << "per event "
01032                               << std::right << std::setw(22) << "per module-visit "
01033                               << "";
01034 
01035     pi = end_paths_.begin();
01036     pe = end_paths_.end();
01037     for (; pi != pe; ++pi) {
01038       LogVerbatim("FwkSummary") << "";
01039       LogVerbatim("FwkSummary") << "TimeReport " << "------ Modules in End-Path: " << pi->name() << " ---[sec]----";
01040       LogVerbatim("FwkSummary") << "TimeReport "
01041                                 << std::right << std::setw(22) << "per event "
01042                                 << std::right << std::setw(22) << "per module-visit "
01043                                 << "";
01044       LogVerbatim("FwkSummary") << "TimeReport "
01045                                 << std::right << std::setw(10) << "CPU" << " "
01046                                 << std::right << std::setw(10) << "Real" << " "
01047                                 << std::right << std::setw(10) << "CPU" << " "
01048                                 << std::right << std::setw(10) << "Real" << " "
01049                                 << "Name" << "";
01050       for (unsigned int i = 0; i < pi->size(); ++i) {
01051         LogVerbatim("FwkSummary") << "TimeReport "
01052                                   << std::setprecision(6) << std::fixed
01053                                   << std::right << std::setw(10) << pi->timeCpuReal(i).first/std::max(1, totalEvents()) << " "
01054                                   << std::right << std::setw(10) << pi->timeCpuReal(i).second/std::max(1, totalEvents()) << " "
01055                                   << std::right << std::setw(10) << pi->timeCpuReal(i).first/std::max(1, pi->timesVisited(i)) << " "
01056                                   << std::right << std::setw(10) << pi->timeCpuReal(i).second/std::max(1, pi->timesVisited(i)) << " "
01057                                   << pi->getWorker(i)->description().moduleLabel() << "";
01058       }
01059     }
01060     LogVerbatim("FwkSummary") << "TimeReport "
01061                               << std::right << std::setw(10) << "CPU" << " "
01062                               << std::right << std::setw(10) << "Real" << " "
01063                               << std::right << std::setw(10) << "CPU" << " "
01064                               << std::right << std::setw(10) << "Real" << " "
01065                               << "Name" << "";
01066     LogVerbatim("FwkSummary") << "TimeReport "
01067                               << std::right << std::setw(22) << "per event "
01068                               << std::right << std::setw(22) << "per module-visit "
01069                               << "";
01070 
01071     LogVerbatim("FwkSummary") << "";
01072     LogVerbatim("FwkSummary") << "TimeReport " << "---------- Module Summary ---[sec]----";
01073     LogVerbatim("FwkSummary") << "TimeReport "
01074                               << std::right << std::setw(22) << "per event "
01075                               << std::right << std::setw(22) << "per module-run "
01076                               << std::right << std::setw(22) << "per module-visit "
01077                               << "";
01078     LogVerbatim("FwkSummary") << "TimeReport "
01079                               << std::right << std::setw(10) << "CPU" << " "
01080                               << std::right << std::setw(10) << "Real" << " "
01081                               << std::right << std::setw(10) << "CPU" << " "
01082                               << std::right << std::setw(10) << "Real" << " "
01083                               << std::right << std::setw(10) << "CPU" << " "
01084                               << std::right << std::setw(10) << "Real" << " "
01085                               << "Name" << "";
01086     ai = workersBegin();
01087     ae = workersEnd();
01088     for (; ai != ae; ++ai) {
01089       LogVerbatim("FwkSummary") << "TimeReport "
01090                                 << std::setprecision(6) << std::fixed
01091                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().first/std::max(1, totalEvents()) << " "
01092                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().second/std::max(1, totalEvents()) << " "
01093                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().first/std::max(1, (*ai)->timesRun()) << " "
01094                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().second/std::max(1, (*ai)->timesRun()) << " "
01095                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().first/std::max(1, (*ai)->timesVisited()) << " "
01096                                 << std::right << std::setw(10) << (*ai)->timeCpuReal().second/std::max(1, (*ai)->timesVisited()) << " "
01097                                 << (*ai)->description().moduleLabel() << "";
01098     }
01099     LogVerbatim("FwkSummary") << "TimeReport "
01100                               << std::right << std::setw(10) << "CPU" << " "
01101                               << std::right << std::setw(10) << "Real" << " "
01102                               << std::right << std::setw(10) << "CPU" << " "
01103                               << std::right << std::setw(10) << "Real" << " "
01104                               << std::right << std::setw(10) << "CPU" << " "
01105                               << std::right << std::setw(10) << "Real" << " "
01106                               << "Name" << "";
01107     LogVerbatim("FwkSummary") << "TimeReport "
01108                               << std::right << std::setw(22) << "per event "
01109                               << std::right << std::setw(22) << "per module-run "
01110                               << std::right << std::setw(22) << "per module-visit "
01111                               << "";
01112 
01113     LogVerbatim("FwkSummary") << "";
01114     LogVerbatim("FwkSummary") << "T---Report end!" << "";
01115     LogVerbatim("FwkSummary") << "";
01116   }
01117 
01118   void Schedule::closeOutputFiles() {
01119     for_all(all_output_workers_, boost::bind(&OutputWorker::closeFile, _1));
01120   }
01121 
01122   void Schedule::openNewOutputFilesIfNeeded() {
01123     for_all(all_output_workers_, boost::bind(&OutputWorker::openNewFileIfNeeded, _1));
01124   }
01125 
01126   void Schedule::openOutputFiles(FileBlock& fb) {
01127     for_all(all_output_workers_, boost::bind(&OutputWorker::openFile, _1, boost::cref(fb)));
01128   }
01129 
01130   void Schedule::writeRun(RunPrincipal const& rp) {
01131     for_all(all_output_workers_, boost::bind(&OutputWorker::writeRun, _1, boost::cref(rp)));
01132   }
01133 
01134   void Schedule::writeLumi(LuminosityBlockPrincipal const& lbp) {
01135     for_all(all_output_workers_, boost::bind(&OutputWorker::writeLumi, _1, boost::cref(lbp)));
01136   }
01137 
01138   bool Schedule::shouldWeCloseOutput() const {
01139     // Return true iff at least one output module returns true.
01140     return (std::find_if (all_output_workers_.begin(), all_output_workers_.end(),
01141                      boost::bind(&OutputWorker::shouldWeCloseFile, _1))
01142                      != all_output_workers_.end());
01143   }
01144 
01145   void Schedule::respondToOpenInputFile(FileBlock const& fb) {
01146     for_all(all_workers_, boost::bind(&Worker::respondToOpenInputFile, _1, boost::cref(fb)));
01147   }
01148 
01149   void Schedule::respondToCloseInputFile(FileBlock const& fb) {
01150     for_all(all_workers_, boost::bind(&Worker::respondToCloseInputFile, _1, boost::cref(fb)));
01151   }
01152 
01153   void Schedule::respondToOpenOutputFiles(FileBlock const& fb) {
01154     for_all(all_workers_, boost::bind(&Worker::respondToOpenOutputFiles, _1, boost::cref(fb)));
01155   }
01156 
01157   void Schedule::respondToCloseOutputFiles(FileBlock const& fb) {
01158     for_all(all_workers_, boost::bind(&Worker::respondToCloseOutputFiles, _1, boost::cref(fb)));
01159   }
01160 
01161   void Schedule::beginJob() {
01162     for_all(all_workers_, boost::bind(&Worker::beginJob, _1));
01163     loadMissingDictionaries();
01164   }
01165 
01166   void Schedule::preForkReleaseResources() {
01167     for_all(all_workers_, boost::bind(&Worker::preForkReleaseResources, _1));
01168   }
01169   void Schedule::postForkReacquireResources(unsigned int iChildIndex, unsigned int iNumberOfChildren) {
01170     for_all(all_workers_, boost::bind(&Worker::postForkReacquireResources, _1, iChildIndex, iNumberOfChildren));
01171   }
01172 
01173   bool Schedule::changeModule(std::string const& iLabel,
01174                               ParameterSet const& iPSet) {
01175     Worker* found = 0;
01176     for (AllWorkers::const_iterator it=all_workers_.begin(), itEnd=all_workers_.end();
01177         it != itEnd; ++it) {
01178       if ((*it)->description().moduleLabel() == iLabel) {
01179         found = *it;
01180         break;
01181       }
01182     }
01183     if (0 == found) {
01184       return false;
01185     }
01186 
01187     std::auto_ptr<Maker> wm(MakerPluginFactory::get()->create(found->description().moduleName()));
01188     wm->swapModule(found, iPSet);
01189     found->beginJob();
01190     return true;
01191   }
01192 
01193   std::vector<ModuleDescription const*>
01194   Schedule::getAllModuleDescriptions() const {
01195     AllWorkers::const_iterator i(workersBegin());
01196     AllWorkers::const_iterator e(workersEnd());
01197 
01198     std::vector<ModuleDescription const*> result;
01199     result.reserve(all_workers_.size());
01200 
01201     for (; i != e; ++i) {
01202       ModuleDescription const* p = (*i)->descPtr();
01203       result.push_back(p);
01204     }
01205     return result;
01206   }
01207 
01208   void
01209   Schedule::availablePaths(std::vector<std::string>& oLabelsToFill) const {
01210     oLabelsToFill.reserve(trig_paths_.size());
01211     std::transform(trig_paths_.begin(),
01212                    trig_paths_.end(),
01213                    std::back_inserter(oLabelsToFill),
01214                    boost::bind(&Path::name, _1));
01215   }
01216 
01217   void
01218   Schedule::modulesInPath(std::string const& iPathLabel,
01219                           std::vector<std::string>& oLabelsToFill) const {
01220     TrigPaths::const_iterator itFound =
01221     std::find_if (trig_paths_.begin(),
01222                  trig_paths_.end(),
01223                  boost::bind(std::equal_to<std::string>(),
01224                              iPathLabel,
01225                              boost::bind(&Path::name, _1)));
01226     if (itFound!=trig_paths_.end()) {
01227       oLabelsToFill.reserve(itFound->size());
01228       for (size_t i = 0; i < itFound->size(); ++i) {
01229         oLabelsToFill.push_back(itFound->getWorker(i)->description().moduleLabel());
01230       }
01231     }
01232   }
01233 
01234   void
01235   Schedule::enableEndPaths(bool active) {
01236     endpathsAreActive_ = active;
01237   }
01238 
01239   bool
01240   Schedule::endPathsEnabled() const {
01241     return endpathsAreActive_;
01242   }
01243 
01244   void
01245   fillModuleInPathSummary(Path const&, ModuleInPathSummary&) {
01246   }
01247 
01248   void
01249   fillModuleInPathSummary(Path const& path,
01250                           size_t which,
01251                           ModuleInPathSummary& sum) {
01252     sum.timesVisited = path.timesVisited(which);
01253     sum.timesPassed  = path.timesPassed(which);
01254     sum.timesFailed  = path.timesFailed(which);
01255     sum.timesExcept  = path.timesExcept(which);
01256     sum.moduleLabel  = path.getWorker(which)->description().moduleLabel();
01257   }
01258 
01259   void
01260   fillPathSummary(Path const& path, PathSummary& sum) {
01261     sum.name        = path.name();
01262     sum.bitPosition = path.bitPosition();
01263     sum.timesRun    = path.timesRun();
01264     sum.timesPassed = path.timesPassed();
01265     sum.timesFailed = path.timesFailed();
01266     sum.timesExcept = path.timesExcept();
01267 
01268     Path::size_type sz = path.size();
01269     std::vector<ModuleInPathSummary> temp(sz);
01270     for (size_t i = 0; i != sz; ++i) {
01271       fillModuleInPathSummary(path, i, temp[i]);
01272     }
01273     sum.moduleInPathSummaries.swap(temp);
01274   }
01275 
01276   void
01277   fillWorkerSummaryAux(Worker const& w, WorkerSummary& sum) {
01278     sum.timesVisited = w.timesVisited();
01279     sum.timesRun     = w.timesRun();
01280     sum.timesPassed  = w.timesPassed();
01281     sum.timesFailed  = w.timesFailed();
01282     sum.timesExcept  = w.timesExcept();
01283     sum.moduleLabel  = w.description().moduleLabel();
01284   }
01285 
01286   void
01287   fillWorkerSummary(Worker const* pw, WorkerSummary& sum) {
01288     fillWorkerSummaryAux(*pw, sum);
01289   }
01290 
01291   void
01292   Schedule::getTriggerReport(TriggerReport& rep) const {
01293     rep.eventSummary.totalEvents = totalEvents();
01294     rep.eventSummary.totalEventsPassed = totalEventsPassed();
01295     rep.eventSummary.totalEventsFailed = totalEventsFailed();
01296 
01297     fill_summary(trig_paths_,  rep.trigPathSummaries, &fillPathSummary);
01298     fill_summary(end_paths_,   rep.endPathSummaries,  &fillPathSummary);
01299     fill_summary(all_workers_, rep.workerSummaries,   &fillWorkerSummary);
01300   }
01301 
01302   void
01303   Schedule::clearCounters() {
01304     total_events_ = total_passed_ = 0;
01305     for_all(trig_paths_, boost::bind(&Path::clearCounters, _1));
01306     for_all(end_paths_, boost::bind(&Path::clearCounters, _1));
01307     for_all(all_workers_, boost::bind(&Worker::clearCounters, _1));
01308   }
01309 
01310   void
01311   Schedule::resetAll() {
01312     for_all(all_workers_, boost::bind(&Worker::reset, _1));
01313     results_->reset();
01314     endpath_results_->reset();
01315   }
01316 
01317   void
01318   Schedule::addToAllWorkers(Worker* w) {
01319     if (!search_all(all_workers_, w)) {
01320       if (wantSummary_) {
01321         w->useStopwatch();
01322       }
01323       all_workers_.push_back(w);
01324     }
01325   }
01326 
01327   void
01328   Schedule::setupOnDemandSystem(EventPrincipal& ep, EventSetup const& es) {
01329     // NOTE: who owns the productdescrption?  Just copied by value
01330     unscheduled_->setEventSetup(es);
01331     ep.setUnscheduledHandler(unscheduled_);
01332   }
01333   
01334   void 
01335   Schedule::resetEarlyDelete() {
01336     //must be sure we have cleared the count first
01337     for(auto& count:earlyDeleteBranchToCount_) {
01338       count.second = 0;
01339     }
01340     //now reset based on how many helpers use that branch
01341     for(auto& index: earlyDeleteHelperToBranchIndicies_) {
01342       ++(earlyDeleteBranchToCount_[index].second);
01343     }
01344     for(auto& helper: earlyDeleteHelpers_) {
01345       helper.reset();
01346     }
01347   }
01348 
01349 }