Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-14 02:38:40

0001 #include "FWCore/Framework/interface/ProductResolversFactory.h"
0002 #include "FWCore/Framework/interface/ProductResolverBase.h"
0003 #include "DataFormats/Provenance/interface/ProductResolverIndexHelper.h"
0004 #include "ProductResolvers.h"
0005 
0006 #include <memory>
0007 
0008 namespace edm::productResolversFactory {
0009   namespace {
0010     std::shared_ptr<ProductResolverBase> makeScheduledProduct(std::shared_ptr<BranchDescription const> bd) {
0011       return std::make_shared<PuttableProductResolver>(std::move(bd));
0012     }
0013     std::shared_ptr<ProductResolverBase> makeSourceProduct(std::shared_ptr<BranchDescription const> bd) {
0014       return std::make_shared<PuttableProductResolver>(std::move(bd));
0015     }
0016     std::shared_ptr<ProductResolverBase> makeDelayedReaderInputProduct(std::shared_ptr<BranchDescription const> bd) {
0017       return std::make_shared<DelayedReaderInputProductResolver>(std::move(bd));
0018     }
0019     std::shared_ptr<ProductResolverBase> makePutOnReadInputProduct(std::shared_ptr<BranchDescription const> bd) {
0020       return std::make_shared<PutOnReadInputProductResolver>(std::move(bd));
0021     }
0022     std::shared_ptr<ProductResolverBase> makeUnscheduledProduct(std::shared_ptr<BranchDescription const> bd) {
0023       return std::make_shared<UnscheduledProductResolver>(std::move(bd));
0024     }
0025     std::shared_ptr<ProductResolverBase> makeTransformProduct(std::shared_ptr<BranchDescription const> bd) {
0026       return std::make_shared<TransformingProductResolver>(std::move(bd));
0027     }
0028     std::shared_ptr<ProductResolverBase> makeAliasedProduct(
0029         std::shared_ptr<BranchDescription const> bd,
0030         ProductRegistry const& iReg,
0031         std::vector<std::shared_ptr<ProductResolverBase>> const& iResolvers) {
0032       ProductResolverIndex index = iReg.indexFrom(bd->originalBranchID());
0033       assert(index != ProductResolverIndexInvalid);
0034       return std::make_shared<AliasProductResolver>(
0035           std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*iResolvers[index]));
0036     }
0037     std::shared_ptr<ProductResolverBase> makeSwitchProducerProduct(
0038         std::shared_ptr<BranchDescription const> bd,
0039         ProductRegistry const& iReg,
0040         std::vector<std::shared_ptr<ProductResolverBase>> const& iResolvers) {
0041       ProductResolverIndex index = iReg.indexFrom(bd->switchAliasForBranchID());
0042       assert(index != ProductResolverIndexInvalid);
0043 
0044       return std::make_shared<SwitchProducerProductResolver>(
0045           std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*iResolvers[index]));
0046     }
0047 
0048     std::shared_ptr<ProductResolverBase> makeSwitchAliasProduct(
0049         std::shared_ptr<BranchDescription const> bd,
0050         ProductRegistry const& iReg,
0051         std::vector<std::shared_ptr<ProductResolverBase>> const& iResolvers) {
0052       ProductResolverIndex index = iReg.indexFrom(bd->switchAliasForBranchID());
0053       assert(index != ProductResolverIndexInvalid);
0054 
0055       return std::make_shared<SwitchAliasProductResolver>(
0056           std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*iResolvers[index]));
0057     }
0058 
0059     std::shared_ptr<ProductResolverBase> makeParentProcessProduct(std::shared_ptr<BranchDescription const> bd) {
0060       return std::make_shared<ParentProcessProductResolver>(std::move(bd));
0061     }
0062 
0063     void addProductOrThrow(std::shared_ptr<ProductResolverBase> iResolver,
0064                            std::vector<std::shared_ptr<ProductResolverBase>>& oResolvers,
0065                            ProductRegistry const& iReg) {
0066       assert(bool(iResolver));
0067       BranchDescription const& bd = iResolver->branchDescription();
0068       assert(!bd.className().empty());
0069       assert(!bd.friendlyClassName().empty());
0070       assert(!bd.moduleLabel().empty());
0071       assert(!bd.processName().empty());
0072       auto index = iReg.indexFrom(bd.branchID());
0073       if (oResolvers[index]) {
0074         throw Exception(errors::InsertFailure, "AlreadyPresent")
0075             << "Problem found while adding a new ProductResolver, "
0076             << "product already exists for (" << bd.friendlyClassName() << "," << bd.moduleLabel() << ","
0077             << bd.productInstanceName() << "," << bd.processName() << ")\n";
0078       }
0079       oResolvers[index] = std::move(iResolver);
0080     }
0081 
0082     std::shared_ptr<ProductResolverBase> makeForPrimary(BranchDescription const& bd,
0083                                                         ProductRegistry const& iReg,
0084                                                         ProductResolverIndexHelper const& iHelper) {
0085       auto cbd = std::make_shared<BranchDescription const>(bd);
0086       if (bd.produced()) {
0087         using namespace std::literals;
0088         if (bd.moduleLabel() == "source"sv) {
0089           return makeSourceProduct(cbd);
0090         } else if (bd.onDemand()) {
0091           assert(bd.branchType() == InEvent);
0092           if (bd.isTransform()) {
0093             return makeTransformProduct(cbd);
0094           } else {
0095             return makeUnscheduledProduct(cbd);
0096           }
0097         }
0098         return makeScheduledProduct(cbd);
0099       }
0100       /* not produced so comes from source */
0101       if (bd.onDemand()) {
0102         return makeDelayedReaderInputProduct(cbd);
0103       }
0104       return makePutOnReadInputProduct(cbd);
0105     }
0106     bool isProductMadeAtEnd(edm::BranchIDList const& matchingHolders,
0107                             std::vector<bool> const& ambiguous,
0108                             std::vector<std::shared_ptr<edm::ProductResolverBase>> const& productResolvers) {
0109       for (unsigned int j = 0; j < matchingHolders.size(); ++j) {
0110         if ((not ambiguous[j]) and ProductResolverIndexInvalid != matchingHolders[j] and
0111             productResolvers[matchingHolders[j]]->branchDescription().availableOnlyAtEndTransition()) {
0112           return true;
0113         }
0114       }
0115       return false;
0116     }
0117     std::shared_ptr<ProductResolverBase> makeNoProcess(
0118         unsigned int numberOfMatches,
0119         ProductResolverIndex lastMatchIndex,
0120         edm::BranchIDList const& matchingHolders,
0121         std::vector<bool> const& ambiguous,
0122         std::vector<std::shared_ptr<edm::ProductResolverBase>> const& productResolvers) {
0123       if ((numberOfMatches == 1) and (lastMatchIndex != ProductResolverIndexAmbiguous)) {
0124         //only one choice so use a special resolver
0125         return std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
0126       }
0127       //Need to know if the product from this processes is added at end of transition
0128       bool productMadeAtEnd = isProductMadeAtEnd(matchingHolders, ambiguous, productResolvers);
0129       return std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
0130     }
0131 
0132     void addUnspecifiedProcess(ProductResolverIndexHelper const& iHelper,
0133                                std::vector<std::shared_ptr<ProductResolverBase>>& productResolvers) {
0134       // Now create the ProductResolvers that search in reverse process
0135       // order and are used for queries where the process name is the
0136       // empty string
0137       std::vector<std::string> const& lookupProcessNames = iHelper.lookupProcessNames();
0138       std::vector<ProductResolverIndex> matchingHolders(lookupProcessNames.size(), ProductResolverIndexInvalid);
0139       std::vector<bool> ambiguous(lookupProcessNames.size(), false);
0140       unsigned int beginElements = iHelper.beginElements();
0141       std::vector<TypeID> const& sortedTypeIDs = iHelper.sortedTypeIDs();
0142       std::vector<ProductResolverIndexHelper::Range> const& ranges = iHelper.ranges();
0143       std::vector<ProductResolverIndexHelper::IndexAndNames> const& indexAndNames = iHelper.indexAndNames();
0144       std::vector<char> const& processNamesCharArray = iHelper.processNames();
0145 
0146       unsigned int numberOfMatches = 0;
0147       ProductResolverIndex lastMatchIndex = ProductResolverIndexInvalid;
0148       if (!sortedTypeIDs.empty()) {
0149         ProductResolverIndex productResolverIndex = ProductResolverIndexInvalid;
0150         for (unsigned int k = 0, kEnd = sortedTypeIDs.size(); k < kEnd; ++k) {
0151           ProductResolverIndexHelper::Range const& range = ranges.at(k);
0152           for (unsigned int i = range.begin(); i < range.end(); ++i) {
0153             ProductResolverIndexHelper::IndexAndNames const& product = indexAndNames.at(i);
0154             if (product.startInProcessNames() == 0) {
0155               if (productResolverIndex != ProductResolverIndexInvalid) {
0156                 productResolvers.at(productResolverIndex) =
0157                     makeNoProcess(numberOfMatches, lastMatchIndex, matchingHolders, ambiguous, productResolvers);
0158                 matchingHolders.assign(lookupProcessNames.size(), ProductResolverIndexInvalid);
0159                 ambiguous.assign(lookupProcessNames.size(), false);
0160                 numberOfMatches = 0;
0161                 lastMatchIndex = ProductResolverIndexInvalid;
0162               }
0163               productResolverIndex = product.index();
0164             } else {
0165               const std::string_view process(&processNamesCharArray.at(product.startInProcessNames()));
0166               auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), process);
0167               assert(iter != lookupProcessNames.end());
0168               ProductResolverIndex iMatchingIndex = product.index();
0169               lastMatchIndex = iMatchingIndex;
0170               assert(iMatchingIndex != ProductResolverIndexInvalid);
0171               ++numberOfMatches;
0172               if (iMatchingIndex == ProductResolverIndexAmbiguous) {
0173                 assert(k >= beginElements);
0174                 ambiguous.at(iter - lookupProcessNames.begin()) = true;
0175               } else {
0176                 matchingHolders.at(iter - lookupProcessNames.begin()) = iMatchingIndex;
0177               }
0178             }
0179           }
0180         }
0181         productResolvers.at(productResolverIndex) =
0182             makeNoProcess(numberOfMatches, lastMatchIndex, matchingHolders, ambiguous, productResolvers);
0183       }
0184     }
0185   }  // namespace
0186 
0187   std::vector<std::shared_ptr<ProductResolverBase>> make(BranchType bt,
0188                                                          std::string_view iProcessName,
0189                                                          ProductRegistry const& iReg,
0190                                                          bool isForPrimaryProcess) {
0191     auto const& helper = iReg.productLookup(bt);
0192     std::vector<std::shared_ptr<ProductResolverBase>> productResolvers(iReg.getNextIndexValue(bt));
0193     ProductRegistry::ProductList const& prodsList = iReg.productList();
0194     // The constructor of an alias product holder takes as an argument the product holder for which it is an alias.
0195     // So, the non-alias product holders must be created first.
0196     // Therefore, on this first pass, skip current EDAliases.
0197     bool hasAliases = false;
0198     bool hasSwitchAliases = false;
0199     for (auto const& prod : prodsList) {
0200       BranchDescription const& bd = prod.second;
0201       if (bd.branchType() == bt) {
0202         if (isForPrimaryProcess or bd.processName() == iProcessName) {
0203           if (bd.isAlias()) {
0204             hasAliases = true;
0205           } else if (bd.isSwitchAlias()) {
0206             hasSwitchAliases = true;
0207           } else {
0208             addProductOrThrow(makeForPrimary(bd, iReg, *helper), productResolvers, iReg);
0209           }
0210         } else {
0211           //We are in a SubProcess and this branch is from the parent
0212           auto cbd = std::make_shared<BranchDescription const>(bd);
0213           addProductOrThrow(makeParentProcessProduct(cbd), productResolvers, iReg);
0214         }
0215       }
0216     }
0217     // Now process any EDAliases
0218     if (hasAliases) {
0219       for (auto const& prod : prodsList) {
0220         BranchDescription const& bd = prod.second;
0221         if (bd.isAlias() && bd.branchType() == bt) {
0222           addProductOrThrow(makeAliasedProduct(std::make_shared<BranchDescription const>(bd), iReg, productResolvers),
0223                             productResolvers,
0224                             iReg);
0225         }
0226       }
0227     }
0228     // Finally process any SwitchProducer aliases
0229     if (hasSwitchAliases) {
0230       for (auto const& prod : prodsList) {
0231         BranchDescription const& bd = prod.second;
0232         if (bd.isSwitchAlias() && bd.branchType() == bt) {
0233           assert(bt == InEvent);
0234           auto cbd = std::make_shared<BranchDescription const>(bd);
0235           // Need different implementation for SwitchProducers not
0236           // in any Path (onDemand) and for those in a Path in order
0237           // to prevent the switch-aliased-for EDProducers from
0238           // being run when the SwitchProducer is in a Path after a
0239           // failing EDFilter.
0240           if (bd.onDemand()) {
0241             addProductOrThrow(makeSwitchAliasProduct(cbd, iReg, productResolvers), productResolvers, iReg);
0242           } else {
0243             addProductOrThrow(makeSwitchProducerProduct(cbd, iReg, productResolvers), productResolvers, iReg);
0244           }
0245         }
0246       }
0247     }
0248 
0249     addUnspecifiedProcess(*helper, productResolvers);
0250 
0251     return productResolvers;
0252   }
0253 }  // namespace edm::productResolversFactory