Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:05:04

0001 /**
0002    \file
0003    class impl
0004 
0005    \Original author Stefano ARGIRO
0006    \Current author Bill Tanenbaum
0007    \date 19 Jul 2005
0008 */
0009 
0010 #include "DataFormats/Provenance/interface/ProductRegistry.h"
0011 
0012 #include "DataFormats/Provenance/interface/ProductResolverIndexHelper.h"
0013 
0014 #include "FWCore/Utilities/interface/Algorithms.h"
0015 #include "FWCore/Utilities/interface/EDMException.h"
0016 #include "FWCore/Reflection/interface/DictionaryTools.h"
0017 #include "FWCore/Utilities/interface/TypeID.h"
0018 #include "FWCore/Reflection/interface/TypeWithDict.h"
0019 #include "FWCore/Utilities/interface/WrappedClassName.h"
0020 
0021 #include "TDictAttributeMap.h"
0022 
0023 #include <cassert>
0024 #include <iterator>
0025 #include <limits>
0026 #include <set>
0027 #include <sstream>
0028 #include <ostream>
0029 
0030 namespace edm {
0031 
0032   ProductRegistry::ProductRegistry() : productList_(), transient_() {}
0033 
0034   ProductRegistry::Transients::Transients()
0035       : frozen_(false),
0036         productProduced_(),
0037         anyProductProduced_(false),
0038         productLookups_{{std::make_unique<ProductResolverIndexHelper>(),
0039                          std::make_unique<ProductResolverIndexHelper>(),
0040                          std::make_unique<ProductResolverIndexHelper>(),
0041                          std::make_unique<ProductResolverIndexHelper>()}},
0042         nextIndexValues_(),
0043         branchIDToIndex_() {
0044     for (bool& isProduced : productProduced_)
0045       isProduced = false;
0046   }
0047 
0048   void ProductRegistry::Transients::reset() {
0049     frozen_ = false;
0050     for (bool& isProduced : productProduced_)
0051       isProduced = false;
0052     anyProductProduced_ = false;
0053 
0054     // propagate_const<T> has no reset() function
0055     for (auto& iterProductLookup : productLookups_) {
0056       iterProductLookup = std::make_unique<ProductResolverIndexHelper>();
0057     }
0058     nextIndexValues_.fill(0);
0059 
0060     branchIDToIndex_.clear();
0061   }
0062 
0063   ProductRegistry::ProductRegistry(ProductList const& productList, bool toBeFrozen)
0064       : productList_(productList), transient_() {
0065     freezeIt(toBeFrozen);
0066   }
0067 
0068   void ProductRegistry::addProduct(BranchDescription const& productDesc, bool fromListener) {
0069     assert(productDesc.produced());
0070     throwIfFrozen();
0071     std::pair<ProductList::iterator, bool> ret =
0072         productList_.insert(std::make_pair(BranchKey(productDesc), productDesc));
0073     if (!ret.second) {
0074       auto const& previous = *productList_.find(BranchKey(productDesc));
0075       if (previous.second.produced()) {
0076         // Duplicate registration in current process
0077         throw Exception(errors::LogicError, "Duplicate Product Identifier")
0078             << "\nThe Framework requires a unique branch name for each product\n"
0079             << "which consists of four parts: a friendly class name, module label,\n"
0080             << "product instance name, and process name. A product has been\n"
0081             << "registered with a duplicate branch name. The most common way\n"
0082             << "to fix this error is to modify the product instance name in\n"
0083             << "one of the offending 'produces' function calls. Another fix\n"
0084             << "would be to delete one of them if they are for the same product.\n\n"
0085             << "    friendly class name = " << previous.second.friendlyClassName() << "\n"
0086             << "    module label = " << previous.second.moduleLabel() << "\n"
0087             << "    product instance name = " << previous.second.productInstanceName() << "\n"
0088             << "    process name = " << previous.second.processName() << "\n\n"
0089             << "The following additional information is not used as part of\n"
0090             << "the unique branch identifier.\n\n"
0091             << "    branch types = " << previous.second.branchType() << "  " << productDesc.branchType() << "\n"
0092             << "    class name = " << previous.second.fullClassName() << "\n\n"
0093             << "Note that if the four parts of the branch name are the same,\n"
0094             << "then this error will occur even if the branch types differ!\n\n";
0095       } else {
0096         // Duplicate registration in previous process
0097         throw Exception(errors::Configuration, "Duplicate Process Name.\n")
0098             << "The process name " << productDesc.processName() << " was previously used for products in the input.\n"
0099             << "This has caused branch name conflicts between input products and new products.\n"
0100             << "Please modify the configuration file to use a distinct process name.\n"
0101             << "Alternately, drop all input products using that process name and the\n"
0102             << "descendants of those products.\n";
0103       }
0104     }
0105     addCalled(productDesc, fromListener);
0106   }
0107 
0108   void ProductRegistry::addLabelAlias(BranchDescription const& productDesc,
0109                                       std::string const& labelAlias,
0110                                       std::string const& instanceAlias) {
0111     assert(productDesc.produced());
0112     assert(productDesc.branchID().isValid());
0113     throwIfFrozen();
0114     BranchDescription bd(productDesc, labelAlias, instanceAlias);
0115     std::pair<ProductList::iterator, bool> ret = productList_.insert(std::make_pair(BranchKey(bd), bd));
0116     assert(ret.second);
0117     transient_.aliasToOriginal_.emplace_back(
0118         PRODUCT_TYPE, productDesc.unwrappedTypeID(), labelAlias, instanceAlias, productDesc.moduleLabel());
0119     addCalled(bd, false);
0120   }
0121 
0122   void ProductRegistry::copyProduct(BranchDescription const& productDesc) {
0123     assert(!productDesc.produced());
0124     throwIfFrozen();
0125     BranchKey k = BranchKey(productDesc);
0126     ProductList::iterator iter = productList_.find(k);
0127     if (iter == productList_.end()) {
0128       productList_.insert(std::make_pair(k, productDesc));
0129     } else {
0130       assert(combinable(iter->second, productDesc));
0131       iter->second.merge(productDesc);
0132     }
0133   }
0134 
0135   bool ProductRegistry::anyProducts(BranchType brType) const {
0136     throwIfNotFrozen();
0137     for (ProductList::const_iterator it = productList_.begin(), itEnd = productList_.end(); it != itEnd; ++it) {
0138       if (it->second.branchType() == brType) {
0139         return true;
0140       }
0141     }
0142     return false;
0143   }
0144 
0145   std::shared_ptr<ProductResolverIndexHelper const> ProductRegistry::productLookup(BranchType branchType) const {
0146     return get_underlying_safe(transient_.productLookups_[branchType]);
0147   }
0148 
0149   std::shared_ptr<ProductResolverIndexHelper> ProductRegistry::productLookup(BranchType branchType) {
0150     return get_underlying_safe(transient_.productLookups_[branchType]);
0151   }
0152 
0153   void ProductRegistry::setFrozen(bool initializeLookupInfo) {
0154     if (frozen())
0155       return;
0156     freezeIt();
0157     if (initializeLookupInfo) {
0158       initializeLookupTables(nullptr, nullptr, nullptr);
0159     }
0160     sort_all(transient_.aliasToOriginal_);
0161   }
0162 
0163   void ProductRegistry::setFrozen(std::set<TypeID> const& productTypesConsumed,
0164                                   std::set<TypeID> const& elementTypesConsumed,
0165                                   std::string const& processName) {
0166     if (frozen())
0167       return;
0168     freezeIt();
0169     initializeLookupTables(&productTypesConsumed, &elementTypesConsumed, &processName);
0170     sort_all(transient_.aliasToOriginal_);
0171   }
0172 
0173   void ProductRegistry::throwIfFrozen() const {
0174     if (frozen()) {
0175       throw cms::Exception("ProductRegistry", "throwIfFrozen")
0176           << "cannot modify the ProductRegistry because it is frozen\n";
0177     }
0178   }
0179 
0180   void ProductRegistry::throwIfNotFrozen() const {
0181     if (!frozen()) {
0182       throw cms::Exception("ProductRegistry", "throwIfNotFrozen")
0183           << "cannot read the ProductRegistry because it is not yet frozen\n";
0184     }
0185   }
0186 
0187   void ProductRegistry::addCalled(BranchDescription const&, bool) {}
0188 
0189   std::vector<std::string> ProductRegistry::allBranchNames() const {
0190     std::vector<std::string> result;
0191     result.reserve(productList().size());
0192 
0193     for (auto const& product : productList()) {
0194       result.push_back(product.second.branchName());
0195     }
0196     return result;
0197   }
0198 
0199   std::vector<BranchDescription const*> ProductRegistry::allBranchDescriptions() const {
0200     std::vector<BranchDescription const*> result;
0201     result.reserve(productList().size());
0202 
0203     for (auto const& product : productList()) {
0204       result.push_back(&product.second);
0205     }
0206     return result;
0207   }
0208 
0209   void ProductRegistry::updateFromInput(ProductList const& other) {
0210     for (auto const& product : other) {
0211       copyProduct(product.second);
0212     }
0213   }
0214 
0215   void ProductRegistry::updateFromInput(std::vector<BranchDescription> const& other) {
0216     for (BranchDescription const& branchDescription : other) {
0217       copyProduct(branchDescription);
0218     }
0219   }
0220 
0221   void ProductRegistry::addFromInput(edm::ProductRegistry const& other) {
0222     throwIfFrozen();
0223     for (auto const& prod : other.productList_) {
0224       ProductList::iterator iter = productList_.find(prod.first);
0225       if (iter == productList_.end()) {
0226         productList_.insert(std::make_pair(prod.first, prod.second));
0227         addCalled(prod.second, false);
0228       } else {
0229         assert(combinable(iter->second, prod.second));
0230         iter->second.merge(prod.second);
0231       }
0232     }
0233   }
0234 
0235   void ProductRegistry::setUnscheduledProducts(std::set<std::string> const& unscheduledLabels) {
0236     throwIfFrozen();
0237 
0238     bool hasAliases = false;
0239     std::vector<BranchID> onDemandIDs;
0240     for (auto& prod : productList_) {
0241       if (prod.second.produced() && prod.second.branchType() == InEvent &&
0242           unscheduledLabels.end() != unscheduledLabels.find(prod.second.moduleLabel())) {
0243         prod.second.setOnDemand(true);
0244         onDemandIDs.push_back(prod.second.branchID());
0245       }
0246       if (prod.second.produced() && prod.second.isAlias()) {
0247         hasAliases = true;
0248       }
0249     }
0250 
0251     // Need to loop over EDAliases to set their on-demand flag based on the pointed-to branch
0252     if (hasAliases) {
0253       std::sort(onDemandIDs.begin(), onDemandIDs.end());
0254       for (auto& prod : productList_) {
0255         if (prod.second.isAlias()) {
0256           if (std::binary_search(onDemandIDs.begin(), onDemandIDs.end(), prod.second.aliasForBranchID())) {
0257             prod.second.setOnDemand(true);
0258           }
0259         }
0260       }
0261     }
0262   }
0263 
0264   std::string ProductRegistry::merge(ProductRegistry const& other,
0265                                      std::string const& fileName,
0266                                      BranchDescription::MatchMode branchesMustMatch) {
0267     std::ostringstream differences;
0268 
0269     ProductRegistry::ProductList::iterator j = productList_.begin();
0270     ProductRegistry::ProductList::iterator s = productList_.end();
0271     ProductRegistry::ProductList::const_iterator i = other.productList().begin();
0272     ProductRegistry::ProductList::const_iterator e = other.productList().end();
0273 
0274     // Loop over entries in the main product registry.
0275     while (j != s || i != e) {
0276       if (j != s && j->second.produced()) {
0277         // Ignore branches just produced (i.e. not in input file).
0278         ++j;
0279       } else if (j == s || (i != e && i->first < j->first)) {
0280         if (i->second.present()) {
0281           differences << "Branch '" << i->second.branchName() << "' is in file '" << fileName << "'\n";
0282           differences << "    but not in previous files.\n";
0283         } else {
0284           productList_.insert(*i);
0285           transient_.branchIDToIndex_[i->second.branchID()] = getNextIndexValue(i->second.branchType());
0286           ++nextIndexValue(i->second.branchType());
0287         }
0288         ++i;
0289       } else if (i == e || (j != s && j->first < i->first)) {
0290         if (j->second.present() &&
0291             (branchesMustMatch == BranchDescription::Strict || j->second.branchType() == InProcess)) {
0292           differences << "Branch '" << j->second.branchName() << "' is in previous files\n";
0293           differences << "    but not in file '" << fileName << "'.\n";
0294         }
0295         ++j;
0296       } else {
0297         std::string difs = match(j->second, i->second, fileName);
0298         if (difs.empty()) {
0299           j->second.merge(i->second);
0300         } else {
0301           differences << difs;
0302         }
0303         ++i;
0304         ++j;
0305       }
0306     }
0307     return differences.str();
0308   }
0309 
0310   void ProductRegistry::initializeLookupTables(std::set<TypeID> const* productTypesConsumed,
0311                                                std::set<TypeID> const* elementTypesConsumed,
0312                                                std::string const* processName) {
0313     std::map<TypeID, TypeID> containedTypeMap;
0314     std::map<TypeID, std::vector<TypeID>> containedTypeToBaseTypesMap;
0315 
0316     std::vector<std::string> missingDictionaries;
0317     std::vector<std::string> branchNamesForMissing;
0318     std::vector<std::string> producedTypes;
0319 
0320     transient_.branchIDToIndex_.clear();
0321 
0322     for (auto const& product : productList_) {
0323       auto const& desc = product.second;
0324 
0325       checkForDuplicateProcessName(desc, processName);
0326 
0327       if (desc.produced() && !desc.transient()) {
0328         setProductProduced(desc.branchType());
0329       }
0330 
0331       //only do the following if the data is supposed to be available in the event
0332       if (desc.present()) {
0333         // Check dictionaries (we already checked for the produced ones earlier somewhere else).
0334         // We have to have the dictionaries to properly setup the lookup tables for support of
0335         // Views. Also we need them to determine which present products are declared to be
0336         // consumed in the case where the consumed type is a View<T>.
0337         if (!desc.produced()) {
0338           if (!checkDictionary(missingDictionaries, desc.className(), desc.unwrappedType())) {
0339             checkDictionaryOfWrappedType(missingDictionaries, desc.className());
0340             branchNamesForMissing.emplace_back(desc.branchName());
0341             producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
0342             continue;
0343           }
0344         }
0345         TypeID typeID(desc.unwrappedType().typeInfo());
0346 
0347         auto iterContainedType = containedTypeMap.find(typeID);
0348         bool alreadySawThisType = (iterContainedType != containedTypeMap.end());
0349 
0350         if (!desc.produced() && !alreadySawThisType) {
0351           if (!checkDictionary(missingDictionaries, desc.wrappedName(), desc.wrappedType())) {
0352             branchNamesForMissing.emplace_back(desc.branchName());
0353             producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
0354             continue;
0355           }
0356         }
0357 
0358         TypeID wrappedTypeID(desc.wrappedType().typeInfo());
0359 
0360         TypeID containedTypeID;
0361         if (alreadySawThisType) {
0362           containedTypeID = iterContainedType->second;
0363         } else {
0364           containedTypeID = productholderindexhelper::getContainedTypeFromWrapper(wrappedTypeID, typeID.className());
0365         }
0366         bool hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
0367 
0368         std::vector<TypeID>* baseTypesOfContainedType = nullptr;
0369 
0370         if (!alreadySawThisType) {
0371           bool alreadyCheckedConstituents = desc.produced() && !desc.transient();
0372           if (!alreadyCheckedConstituents && !desc.transient()) {
0373             // This checks dictionaries of the wrapped class and all its constituent classes
0374             if (!checkClassDictionaries(missingDictionaries, desc.wrappedName(), desc.wrappedType())) {
0375               branchNamesForMissing.emplace_back(desc.branchName());
0376               producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
0377               continue;
0378             }
0379           }
0380 
0381           if (hasContainedType) {
0382             auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
0383             if (iterBaseTypes == containedTypeToBaseTypesMap.end()) {
0384               std::vector<TypeID> baseTypes;
0385               if (!public_base_classes(missingDictionaries, containedTypeID, baseTypes)) {
0386                 branchNamesForMissing.emplace_back(desc.branchName());
0387                 if (desc.produced()) {
0388                   producedTypes.emplace_back(desc.className() + std::string(" (produced in current process)"));
0389                 } else {
0390                   producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
0391                 }
0392                 continue;
0393               }
0394               iterBaseTypes = containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, baseTypes)).first;
0395             }
0396             baseTypesOfContainedType = &iterBaseTypes->second;
0397           }
0398 
0399           // Do this after the dictionary checks of constituents so the list of branch names for missing types
0400           // is complete
0401           containedTypeMap.emplace(typeID, containedTypeID);
0402         } else {
0403           if (hasContainedType) {
0404             auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
0405             if (iterBaseTypes != containedTypeToBaseTypesMap.end()) {
0406               baseTypesOfContainedType = &iterBaseTypes->second;
0407             }
0408           }
0409         }
0410 
0411         if (productTypesConsumed != nullptr && !desc.produced()) {
0412           bool mainTypeConsumed = (productTypesConsumed->find(typeID) != productTypesConsumed->end());
0413           bool containedTypeConsumed =
0414               hasContainedType && (elementTypesConsumed->find(containedTypeID) != elementTypesConsumed->end());
0415           if (hasContainedType && !containedTypeConsumed && baseTypesOfContainedType != nullptr) {
0416             for (TypeID const& baseType : *baseTypesOfContainedType) {
0417               if (elementTypesConsumed->find(TypeID(baseType.typeInfo())) != elementTypesConsumed->end()) {
0418                 containedTypeConsumed = true;
0419                 break;
0420               }
0421             }
0422           }
0423           if (!containedTypeConsumed) {
0424             if (mainTypeConsumed) {
0425               // The main type is consumed, but either
0426               // there is no contained type, or if there is,
0427               // neither it nor any of its base classes are consumed.
0428               // Set the contained type, if there is one, to void,
0429               if (hasContainedType) {
0430                 containedTypeID = TypeID(typeid(void));
0431               }
0432             } else {
0433               // The main type is not consumed, and either
0434               // there is no contained type, or if there is,
0435               // neither it nor any of its base classes are consumed.
0436               // Don't insert anything in the lookup tables.
0437               continue;
0438             }
0439           }
0440         }
0441         ProductResolverIndex index = productLookup(desc.branchType())
0442                                          ->insert(typeID,
0443                                                   desc.moduleLabel().c_str(),
0444                                                   desc.productInstanceName().c_str(),
0445                                                   desc.processName().c_str(),
0446                                                   containedTypeID,
0447                                                   baseTypesOfContainedType);
0448 
0449         transient_.branchIDToIndex_[desc.branchID()] = index;
0450       }
0451     }
0452     if (!missingDictionaries.empty()) {
0453       std::string context("Calling ProductRegistry::initializeLookupTables");
0454       throwMissingDictionariesException(missingDictionaries, context, producedTypes, branchNamesForMissing);
0455     }
0456 
0457     for (auto& iterProductLookup : transient_.productLookups_) {
0458       iterProductLookup->setFrozen();
0459     }
0460 
0461     unsigned int indexIntoNextIndexValue = 0;
0462     for (auto const& iterProductLookup : transient_.productLookups_) {
0463       transient_.nextIndexValues_[indexIntoNextIndexValue] = iterProductLookup->nextIndexValue();
0464       ++indexIntoNextIndexValue;
0465     }
0466 
0467     for (auto const& product : productList_) {
0468       auto const& desc = product.second;
0469       if (transient_.branchIDToIndex_.find(desc.branchID()) == transient_.branchIDToIndex_.end()) {
0470         transient_.branchIDToIndex_[desc.branchID()] = getNextIndexValue(desc.branchType());
0471         ++nextIndexValue(desc.branchType());
0472       }
0473     }
0474     checkDictionariesOfConsumedTypes(
0475         productTypesConsumed, elementTypesConsumed, containedTypeMap, containedTypeToBaseTypesMap);
0476 
0477     addElementTypesForAliases(elementTypesConsumed, containedTypeMap, containedTypeToBaseTypesMap);
0478   }
0479 
0480   void ProductRegistry::addElementTypesForAliases(
0481       std::set<TypeID> const* elementTypesConsumed,
0482       std::map<TypeID, TypeID> const& containedTypeMap,
0483       std::map<TypeID, std::vector<TypeID>> const& containedTypeToBaseTypesMap) {
0484     Transients::AliasToOriginalVector elementAliases;
0485     for (auto& item : transient_.aliasToOriginal_) {
0486       auto iterContainedType = containedTypeMap.find(std::get<Transients::kType>(item));
0487       if (iterContainedType == containedTypeMap.end()) {
0488         edm::Exception ex(errors::LogicError);
0489         ex << "containedTypeMap did not contain " << std::get<Transients::kType>(item).className()
0490            << " that is used in EDAlias " << std::get<Transients::kModuleLabel>(item)
0491            << ".\nThis should not happen, contact framework developers";
0492         ex.addContext("Calling ProductRegistry::initializeLookupTables()");
0493         throw ex;
0494       }
0495       auto const& containedTypeID = iterContainedType->second;
0496       bool const hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
0497       if (not hasContainedType) {
0498         continue;
0499       }
0500 
0501       if (elementTypesConsumed->find(containedTypeID) != elementTypesConsumed->end()) {
0502         elementAliases.emplace_back(ELEMENT_TYPE,
0503                                     containedTypeID,
0504                                     std::get<Transients::kModuleLabel>(item),
0505                                     std::get<Transients::kProductInstanceName>(item),
0506                                     std::get<Transients::kAliasForModuleLabel>(item));
0507       }
0508 
0509       auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
0510       if (iterBaseTypes == containedTypeToBaseTypesMap.end()) {
0511         continue;
0512       }
0513       for (TypeID const& baseTypeID : iterBaseTypes->second) {
0514         if (elementTypesConsumed->find(baseTypeID) != elementTypesConsumed->end()) {
0515           elementAliases.emplace_back(ELEMENT_TYPE,
0516                                       baseTypeID,
0517                                       std::get<Transients::kModuleLabel>(item),
0518                                       std::get<Transients::kProductInstanceName>(item),
0519                                       std::get<Transients::kAliasForModuleLabel>(item));
0520         }
0521       }
0522     }
0523     transient_.aliasToOriginal_.insert(transient_.aliasToOriginal_.end(),
0524                                        std::make_move_iterator(elementAliases.begin()),
0525                                        std::make_move_iterator(elementAliases.end()));
0526   }
0527 
0528   void ProductRegistry::checkDictionariesOfConsumedTypes(
0529       std::set<TypeID> const* productTypesConsumed,
0530       std::set<TypeID> const* elementTypesConsumed,
0531       std::map<TypeID, TypeID> const& containedTypeMap,
0532       std::map<TypeID, std::vector<TypeID>>& containedTypeToBaseTypesMap) {
0533     std::vector<std::string> missingDictionaries;
0534     std::set<std::string> consumedTypesWithMissingDictionaries;
0535 
0536     if (productTypesConsumed) {
0537       // Check dictionaries for all classes declared to be consumed
0538       for (auto const& consumedTypeID : *productTypesConsumed) {
0539         // We use the containedTypeMap to see which types have already
0540         // had their dictionaries checked. We do not waste time rechecking
0541         // those dictionaries.
0542         if (containedTypeMap.find(consumedTypeID) == containedTypeMap.end()) {
0543           std::string wrappedName = wrappedClassName(consumedTypeID.className());
0544           TypeWithDict wrappedType = TypeWithDict::byName(wrappedName);
0545           if (!checkDictionary(missingDictionaries, wrappedName, wrappedType)) {
0546             checkDictionary(missingDictionaries, consumedTypeID);
0547             consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0548             continue;
0549           }
0550           bool transient = false;
0551           TDictAttributeMap* wp = wrappedType.getClass()->GetAttributeMap();
0552           if (wp && wp->HasKey("persistent") && !strcmp(wp->GetPropertyAsString("persistent"), "false")) {
0553             transient = true;
0554           }
0555           if (transient) {
0556             if (!checkDictionary(missingDictionaries, consumedTypeID)) {
0557               consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0558             }
0559 
0560             TypeID containedTypeID = productholderindexhelper::getContainedTypeFromWrapper(
0561                 TypeID(wrappedType.typeInfo()), consumedTypeID.className());
0562             bool hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
0563             if (hasContainedType) {
0564               if (containedTypeToBaseTypesMap.find(containedTypeID) == containedTypeToBaseTypesMap.end()) {
0565                 std::vector<TypeID> bases;
0566                 // Run this to check for missing dictionaries, bases is not really used
0567                 if (!public_base_classes(missingDictionaries, containedTypeID, bases)) {
0568                   consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0569                 }
0570                 containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, bases));
0571               }
0572             }
0573           } else {
0574             if (!checkClassDictionaries(missingDictionaries, wrappedName, wrappedType)) {
0575               consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0576             }
0577           }
0578         }
0579       }
0580       if (!missingDictionaries.empty()) {
0581         std::string context(
0582             "Calling ProductRegistry::initializeLookupTables, checking dictionaries for consumed products");
0583         throwMissingDictionariesException(missingDictionaries, context, consumedTypesWithMissingDictionaries, false);
0584       }
0585     }
0586 
0587     if (elementTypesConsumed) {
0588       missingDictionaries.clear();
0589       consumedTypesWithMissingDictionaries.clear();
0590       for (auto const& consumedTypeID : *elementTypesConsumed) {
0591         if (containedTypeToBaseTypesMap.find(consumedTypeID) == containedTypeToBaseTypesMap.end()) {
0592           std::vector<TypeID> bases;
0593           // Run this to check for missing dictionaries, bases is not really used
0594           if (!public_base_classes(missingDictionaries, consumedTypeID, bases)) {
0595             consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0596           }
0597         }
0598       }
0599       if (!missingDictionaries.empty()) {
0600         std::string context(
0601             "Calling ProductRegistry::initializeLookupTables, checking dictionaries for elements of products consumed "
0602             "using View");
0603         throwMissingDictionariesException(missingDictionaries, context, consumedTypesWithMissingDictionaries, true);
0604       }
0605     }
0606   }
0607 
0608   void ProductRegistry::checkForDuplicateProcessName(BranchDescription const& desc,
0609                                                      std::string const* processName) const {
0610     if (processName && !desc.produced() && (*processName == desc.processName())) {
0611       throw Exception(errors::Configuration, "Duplicate Process Name.\n")
0612           << "The process name " << *processName << " was previously used for products in the input.\n"
0613           << "Please modify the configuration file to use a distinct process name.\n"
0614           << "Alternately, drop all input products using that process name and the\n"
0615           << "descendants of those products.\n";
0616     }
0617   }
0618 
0619   ProductResolverIndex ProductRegistry::indexFrom(BranchID const& iID) const {
0620     std::map<BranchID, ProductResolverIndex>::const_iterator itFind = transient_.branchIDToIndex_.find(iID);
0621     if (itFind == transient_.branchIDToIndex_.end()) {
0622       return ProductResolverIndexInvalid;
0623     }
0624     return itFind->second;
0625   }
0626 
0627   std::vector<std::string> ProductRegistry::aliasToModules(KindOfType kindOfType,
0628                                                            TypeID const& type,
0629                                                            std::string_view moduleLabel,
0630                                                            std::string_view productInstanceName) const {
0631     auto aliasFields = [](auto const& item) {
0632       return std::tie(std::get<Transients::kKind>(item),
0633                       std::get<Transients::kType>(item),
0634                       std::get<Transients::kModuleLabel>(item),
0635                       std::get<Transients::kProductInstanceName>(item));
0636     };
0637     auto const target = std::tuple(kindOfType, type, moduleLabel, productInstanceName);
0638     auto found =
0639         std::lower_bound(transient_.aliasToOriginal_.begin(),
0640                          transient_.aliasToOriginal_.end(),
0641                          target,
0642                          [aliasFields](auto const& item, auto const& target) { return aliasFields(item) < target; });
0643     std::vector<std::string> ret;
0644     for (; found != transient_.aliasToOriginal_.end() and aliasFields(*found) == target; ++found) {
0645       ret.emplace_back(std::get<Transients::kAliasForModuleLabel>(*found));
0646     }
0647     return ret;
0648   }
0649 
0650   void ProductRegistry::print(std::ostream& os) const {
0651     for (auto const& product : productList_) {
0652       os << product.second << "\n-----\n";
0653     }
0654   }
0655 
0656   ProductResolverIndex const& ProductRegistry::getNextIndexValue(BranchType branchType) const {
0657     return transient_.nextIndexValues_[branchType];
0658   }
0659 
0660   ProductResolverIndex& ProductRegistry::nextIndexValue(BranchType branchType) {
0661     return transient_.nextIndexValues_[branchType];
0662   }
0663 }  // namespace edm