CMS 3D CMS Logo

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