CMS 3D CMS Logo

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