Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-03-14 23:36:16

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