Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-22 06:27:20

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     void addProductOrThrow(std::shared_ptr<ProductResolverBase> iResolver,
0066                            std::vector<std::shared_ptr<ProductResolverBase>>& oResolvers,
0067                            ProductRegistry const& iReg) {
0068       assert(bool(iResolver));
0069       ProductDescription const& bd = iResolver->productDescription();
0070       assert(!bd.className().empty());
0071       assert(!bd.friendlyClassName().empty());
0072       assert(!bd.moduleLabel().empty());
0073       assert(!bd.processName().empty());
0074       auto index = iReg.indexFrom(bd.branchID());
0075       if (oResolvers[index]) {
0076         throw Exception(errors::InsertFailure, "AlreadyPresent")
0077             << "Problem found while adding a new ProductResolver, "
0078             << "product already exists for (" << bd.friendlyClassName() << "," << bd.moduleLabel() << ","
0079             << bd.productInstanceName() << "," << bd.processName() << ")\n";
0080       }
0081       oResolvers[index] = std::move(iResolver);
0082     }
0083 
0084     std::shared_ptr<ProductResolverBase> makeForPrimary(ProductDescription const& bd,
0085                                                         ProductRegistry const& iReg,
0086                                                         ProductResolverIndexHelper const& iHelper) {
0087       auto cbd = std::make_shared<ProductDescription const>(bd);
0088       if (bd.produced()) {
0089         using namespace std::literals;
0090         if (bd.moduleLabel() == "source"sv) {
0091           return makeSourceProduct(cbd);
0092         } else if (bd.onDemand()) {
0093           assert(bd.branchType() == InEvent);
0094           if (bd.isTransform()) {
0095             return makeTransformProduct(cbd);
0096           } else {
0097             return makeUnscheduledProduct(cbd);
0098           }
0099         }
0100         return makeScheduledProduct(cbd);
0101       }
0102       /* not produced so comes from source */
0103       if (bd.dropped()) {
0104         //this allows access to provenance for the dropped product
0105         return makeDroppedProduct(cbd);
0106       }
0107       if (bd.onDemand()) {
0108         return makeDelayedReaderInputProduct(cbd);
0109       }
0110       return makePutOnReadInputProduct(cbd);
0111     }
0112     bool isProductMadeAtEnd(edm::BranchIDList const& matchingHolders,
0113                             std::vector<bool> const& ambiguous,
0114                             std::vector<std::shared_ptr<edm::ProductResolverBase>> const& productResolvers) {
0115       for (unsigned int j = 0; j < matchingHolders.size(); ++j) {
0116         if ((not ambiguous[j]) and ProductResolverIndexInvalid != matchingHolders[j] and
0117             productResolvers[matchingHolders[j]]->productDescription().availableOnlyAtEndTransition()) {
0118           return true;
0119         }
0120       }
0121       return false;
0122     }
0123     std::shared_ptr<ProductResolverBase> makeNoProcess(
0124         unsigned int numberOfMatches,
0125         ProductResolverIndex lastMatchIndex,
0126         edm::BranchIDList const& matchingHolders,
0127         std::vector<bool> const& ambiguous,
0128         std::vector<std::shared_ptr<edm::ProductResolverBase>> const& productResolvers) {
0129       if ((numberOfMatches == 1) and (lastMatchIndex != ProductResolverIndexAmbiguous)) {
0130         //only one choice so use a special resolver
0131         return std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
0132       }
0133       //Need to know if the product from this processes is added at end of transition
0134       bool productMadeAtEnd = isProductMadeAtEnd(matchingHolders, ambiguous, productResolvers);
0135       return std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
0136     }
0137 
0138     void addUnspecifiedProcess(ProductResolverIndexHelper const& iHelper,
0139                                std::vector<std::shared_ptr<ProductResolverBase>>& productResolvers) {
0140       // Now create the ProductResolvers that search in reverse process
0141       // order and are used for queries where the process name is the
0142       // empty string
0143       std::vector<std::string> const& lookupProcessNames = iHelper.lookupProcessNames();
0144       std::vector<ProductResolverIndex> matchingHolders(lookupProcessNames.size(), ProductResolverIndexInvalid);
0145       std::vector<bool> ambiguous(lookupProcessNames.size(), false);
0146       unsigned int beginElements = iHelper.beginElements();
0147       std::vector<TypeID> const& sortedTypeIDs = iHelper.sortedTypeIDs();
0148       std::vector<ProductResolverIndexHelper::Range> const& ranges = iHelper.ranges();
0149       std::vector<ProductResolverIndexHelper::IndexAndNames> const& indexAndNames = iHelper.indexAndNames();
0150       std::vector<char> const& processNamesCharArray = iHelper.processNames();
0151 
0152       unsigned int numberOfMatches = 0;
0153       ProductResolverIndex lastMatchIndex = ProductResolverIndexInvalid;
0154       if (!sortedTypeIDs.empty()) {
0155         ProductResolverIndex productResolverIndex = ProductResolverIndexInvalid;
0156         for (unsigned int k = 0, kEnd = sortedTypeIDs.size(); k < kEnd; ++k) {
0157           ProductResolverIndexHelper::Range const& range = ranges.at(k);
0158           for (unsigned int i = range.begin(); i < range.end(); ++i) {
0159             ProductResolverIndexHelper::IndexAndNames const& product = indexAndNames.at(i);
0160             if (product.startInProcessNames() == 0) {
0161               if (productResolverIndex != ProductResolverIndexInvalid) {
0162                 productResolvers.at(productResolverIndex) =
0163                     makeNoProcess(numberOfMatches, lastMatchIndex, matchingHolders, ambiguous, productResolvers);
0164                 matchingHolders.assign(lookupProcessNames.size(), ProductResolverIndexInvalid);
0165                 ambiguous.assign(lookupProcessNames.size(), false);
0166                 numberOfMatches = 0;
0167                 lastMatchIndex = ProductResolverIndexInvalid;
0168               }
0169               productResolverIndex = product.index();
0170             } else {
0171               const std::string_view process(&processNamesCharArray.at(product.startInProcessNames()));
0172               auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), process);
0173               assert(iter != lookupProcessNames.end());
0174               ProductResolverIndex iMatchingIndex = product.index();
0175               lastMatchIndex = iMatchingIndex;
0176               assert(iMatchingIndex != ProductResolverIndexInvalid);
0177               ++numberOfMatches;
0178               if (iMatchingIndex == ProductResolverIndexAmbiguous) {
0179                 assert(k >= beginElements);
0180                 ambiguous.at(iter - lookupProcessNames.begin()) = true;
0181               } else {
0182                 matchingHolders.at(iter - lookupProcessNames.begin()) = iMatchingIndex;
0183               }
0184             }
0185           }
0186         }
0187         productResolvers.at(productResolverIndex) =
0188             makeNoProcess(numberOfMatches, lastMatchIndex, matchingHolders, ambiguous, productResolvers);
0189       }
0190     }
0191   }  // namespace
0192 
0193   std::vector<std::shared_ptr<ProductResolverBase>> make(BranchType bt,
0194                                                          std::string_view iProcessName,
0195                                                          ProductRegistry const& iReg) {
0196     auto const& helper = iReg.productLookup(bt);
0197     std::vector<std::shared_ptr<ProductResolverBase>> productResolvers(iReg.getNextIndexValue(bt));
0198     ProductRegistry::ProductList const& prodsList = iReg.productList();
0199     // The constructor of an alias product holder takes as an argument the product holder for which it is an alias.
0200     // So, the non-alias product holders must be created first.
0201     // Therefore, on this first pass, skip current EDAliases.
0202     bool hasAliases = false;
0203     bool hasSwitchAliases = false;
0204     for (auto const& prod : prodsList) {
0205       ProductDescription const& bd = prod.second;
0206       if (bd.branchType() == bt) {
0207         if (bd.isAlias()) {
0208           hasAliases = true;
0209         } else if (bd.isSwitchAlias()) {
0210           hasSwitchAliases = true;
0211         } else {
0212           addProductOrThrow(makeForPrimary(bd, iReg, *helper), productResolvers, iReg);
0213         }
0214       }
0215     }
0216     // Now process any EDAliases
0217     if (hasAliases) {
0218       for (auto const& prod : prodsList) {
0219         ProductDescription const& bd = prod.second;
0220         if (bd.isAlias() && bd.branchType() == bt) {
0221           addProductOrThrow(makeAliasedProduct(std::make_shared<ProductDescription const>(bd), iReg, productResolvers),
0222                             productResolvers,
0223                             iReg);
0224         }
0225       }
0226     }
0227     // Finally process any SwitchProducer aliases
0228     if (hasSwitchAliases) {
0229       for (auto const& prod : prodsList) {
0230         ProductDescription const& bd = prod.second;
0231         if (bd.isSwitchAlias() && bd.branchType() == bt) {
0232           assert(bt == InEvent);
0233           auto cbd = std::make_shared<ProductDescription const>(bd);
0234           // Need different implementation for SwitchProducers not
0235           // in any Path (onDemand) and for those in a Path in order
0236           // to prevent the switch-aliased-for EDProducers from
0237           // being run when the SwitchProducer is in a Path after a
0238           // failing EDFilter.
0239           if (bd.onDemand()) {
0240             addProductOrThrow(makeSwitchAliasProduct(cbd, iReg, productResolvers), productResolvers, iReg);
0241           } else {
0242             addProductOrThrow(makeSwitchProducerProduct(cbd, iReg, productResolvers), productResolvers, iReg);
0243           }
0244         }
0245       }
0246     }
0247 
0248     addUnspecifiedProcess(*helper, productResolvers);
0249 
0250     return productResolvers;
0251   }
0252 }  // namespace edm::productResolversFactory