Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:28:01

0001 #include <algorithm>
0002 #include <iterator>
0003 #include <ostream>
0004 #include <cctype>
0005 
0006 #include "DataFormats/Provenance/interface/BranchDescription.h"
0007 #include "DataFormats/Provenance/interface/ProductRegistry.h"
0008 #include "FWCore/Framework/interface/ProductSelector.h"
0009 #include "FWCore/Framework/interface/ProductSelectorRules.h"
0010 #include "FWCore/Utilities/interface/EDMException.h"
0011 #include "FWCore/Utilities/interface/Algorithms.h"
0012 
0013 namespace edm {
0014   // The following typedef is used only in this implementation file, in
0015   // order to shorten several lines of code.
0016   typedef std::vector<edm::BranchDescription const*> VCBDP;
0017 
0018   ProductSelector::ProductSelector() : productsToSelect_(), initialized_(false) {}
0019 
0020   void ProductSelector::initialize(ProductSelectorRules const& rules, VCBDP const& branchDescriptions) {
0021     typedef ProductSelectorRules::BranchSelectState BranchSelectState;
0022 
0023     // Get a BranchSelectState for each branch, containing the branch
0024     // name, with its 'select bit' set to false.
0025     std::vector<BranchSelectState> branchstates;
0026     {
0027       branchstates.reserve(branchDescriptions.size());
0028 
0029       VCBDP::const_iterator it = branchDescriptions.begin();
0030       VCBDP::const_iterator end = branchDescriptions.end();
0031       for (; it != end; ++it)
0032         branchstates.emplace_back(*it);
0033     }
0034 
0035     // Now  apply the rules to  the branchstates, in order.  Each rule
0036     // can override any previous rule, or all previous rules.
0037     rules.applyToAll(branchstates);
0038 
0039     // For each of the BranchSelectStates that indicates the branch is
0040     // to be selected, remember the branch name.  The list of branch
0041     // names must be sorted, for the implementation of 'selected' to
0042     // work.
0043     {
0044       std::vector<BranchSelectState>::const_iterator it = branchstates.begin();
0045       std::vector<BranchSelectState>::const_iterator end = branchstates.end();
0046       for (; it != end; ++it) {
0047         if (it->selectMe)
0048           productsToSelect_.push_back(it->desc->branchName());
0049       }
0050       sort_all(productsToSelect_);
0051     }
0052     initialized_ = true;
0053   }
0054 
0055   bool ProductSelector::selected(BranchDescription const& desc) const {
0056     if (!initialized_) {
0057       throw edm::Exception(edm::errors::LogicError) << "ProductSelector::selected() called prematurely\n"
0058                                                     << "before the product registry has been frozen.\n";
0059     }
0060     // We are to select this 'branch' if its name is one of the ones we
0061     // have been told to select.
0062     return binary_search_all(productsToSelect_, desc.branchName());
0063   }
0064 
0065   void ProductSelector::print(std::ostream& os) const {
0066     os << "ProductSelector at: " << static_cast<void const*>(this) << " has " << productsToSelect_.size()
0067        << " products to select:\n";
0068     copy_all(productsToSelect_, std::ostream_iterator<std::string>(os, "\n"));
0069   }
0070 
0071   void ProductSelector::checkForDuplicateKeptBranch(
0072       BranchDescription const& desc, std::map<BranchID, BranchDescription const*>& trueBranchIDToKeptBranchDesc) {
0073     // Check if an equivalent branch has already been selected due to an EDAlias.
0074     // We only need the check for products produced in this process.
0075     if (desc.produced()) {
0076       auto check = [&](BranchID const& branchID) {
0077         auto iter = trueBranchIDToKeptBranchDesc.find(branchID);
0078         if (iter != trueBranchIDToKeptBranchDesc.end()) {
0079           throw edm::Exception(errors::Configuration, "Duplicate Output Selection")
0080               << "Two (or more) equivalent branches have been selected for output.\n"
0081               << "#1: " << BranchKey(desc) << "\n"
0082               << "#2: " << BranchKey(*iter->second) << "\n"
0083               << "Please drop at least one of them.\n";
0084         }
0085       };
0086       BranchID const& trueBranchID = desc.originalBranchID();
0087       check(trueBranchID);
0088       // In case of SwitchProducer, we have to check also the
0089       // aliased-for BranchID for the case that the chosen case is an EDAlias
0090       if (desc.isSwitchAlias()) {
0091         check(desc.switchAliasForBranchID());
0092       }
0093 
0094       trueBranchIDToKeptBranchDesc.insert(std::make_pair(trueBranchID, &desc));
0095     }
0096   }
0097 
0098   // Fills in a mapping needed in the case that a branch was dropped while its EDAlias was kept.
0099   void ProductSelector::fillDroppedToKept(
0100       ProductRegistry const& preg,
0101       std::map<BranchID, BranchDescription const*> const& trueBranchIDToKeptBranchDesc,
0102       std::map<BranchID::value_type, BranchID::value_type>& droppedBranchIDToKeptBranchID_) {
0103     for (auto const& it : preg.productList()) {
0104       BranchDescription const& desc = it.second;
0105       if (!desc.produced() || desc.isAlias())
0106         continue;
0107       BranchID const& branchID = desc.branchID();
0108       std::map<BranchID, BranchDescription const*>::const_iterator iter = trueBranchIDToKeptBranchDesc.find(branchID);
0109       if (iter != trueBranchIDToKeptBranchDesc.end()) {
0110         // This branch, produced in this process, or an alias of it, was persisted.
0111         BranchID const& keptBranchID = iter->second->branchID();
0112         if (keptBranchID != branchID) {
0113           // An EDAlias branch was persisted.
0114           droppedBranchIDToKeptBranchID_.insert(std::make_pair(branchID.id(), keptBranchID.id()));
0115         }
0116       }
0117     }
0118   }
0119 
0120   //--------------------------------------------------
0121   //
0122   // Associated free functions
0123   //
0124   std::ostream& operator<<(std::ostream& os, const ProductSelector& gs) {
0125     gs.print(os);
0126     return os;
0127   }
0128 
0129 }  // namespace edm