Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-07-19 01:43:27

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::setUnscheduledProducts(std::set<std::string> const& unscheduledLabels) {
0222     throwIfFrozen();
0223 
0224     bool hasAliases = false;
0225     std::vector<BranchID> onDemandIDs;
0226     for (auto& prod : productList_) {
0227       if (prod.second.produced() && prod.second.branchType() == InEvent &&
0228           unscheduledLabels.end() != unscheduledLabels.find(prod.second.moduleLabel())) {
0229         prod.second.setOnDemand(true);
0230         onDemandIDs.push_back(prod.second.branchID());
0231       }
0232       if (prod.second.produced() && prod.second.isAlias()) {
0233         hasAliases = true;
0234       }
0235     }
0236 
0237     // Need to loop over EDAliases to set their on-demand flag based on the pointed-to branch
0238     if (hasAliases) {
0239       std::sort(onDemandIDs.begin(), onDemandIDs.end());
0240       for (auto& prod : productList_) {
0241         if (prod.second.isAlias()) {
0242           if (std::binary_search(onDemandIDs.begin(), onDemandIDs.end(), prod.second.aliasForBranchID())) {
0243             prod.second.setOnDemand(true);
0244           }
0245         }
0246       }
0247     }
0248   }
0249 
0250   std::string ProductRegistry::merge(ProductRegistry const& other,
0251                                      std::string const& fileName,
0252                                      BranchDescription::MatchMode branchesMustMatch) {
0253     std::ostringstream differences;
0254 
0255     ProductRegistry::ProductList::iterator j = productList_.begin();
0256     ProductRegistry::ProductList::iterator s = productList_.end();
0257     ProductRegistry::ProductList::const_iterator i = other.productList().begin();
0258     ProductRegistry::ProductList::const_iterator e = other.productList().end();
0259 
0260     // Loop over entries in the main product registry.
0261     while (j != s || i != e) {
0262       if (j != s && j->second.produced()) {
0263         // Ignore branches just produced (i.e. not in input file).
0264         ++j;
0265       } else if (j == s || (i != e && i->first < j->first)) {
0266         if (i->second.present()) {
0267           differences << "Branch '" << i->second.branchName() << "' is in file '" << fileName << "'\n";
0268           differences << "    but not in previous files.\n";
0269         } else {
0270           productList_.insert(*i);
0271           transient_.branchIDToIndex_[i->second.branchID()] = getNextIndexValue(i->second.branchType());
0272           ++nextIndexValue(i->second.branchType());
0273         }
0274         ++i;
0275       } else if (i == e || (j != s && j->first < i->first)) {
0276         if (j->second.present() &&
0277             (branchesMustMatch == BranchDescription::Strict || j->second.branchType() == InProcess)) {
0278           differences << "Branch '" << j->second.branchName() << "' is in previous files\n";
0279           differences << "    but not in file '" << fileName << "'.\n";
0280         }
0281         ++j;
0282       } else {
0283         std::string difs = match(j->second, i->second, fileName);
0284         if (difs.empty()) {
0285           j->second.merge(i->second);
0286         } else {
0287           differences << difs;
0288         }
0289         ++i;
0290         ++j;
0291       }
0292     }
0293     return differences.str();
0294   }
0295 
0296   void ProductRegistry::initializeLookupTables(std::set<TypeID> const* productTypesConsumed,
0297                                                std::set<TypeID> const* elementTypesConsumed,
0298                                                std::string const* processName) {
0299     std::map<TypeID, TypeID> containedTypeMap;
0300     std::map<TypeID, std::vector<TypeWithDict>> containedTypeToBaseTypesMap;
0301 
0302     std::vector<std::string> missingDictionaries;
0303     std::vector<std::string> branchNamesForMissing;
0304     std::vector<std::string> producedTypes;
0305 
0306     transient_.branchIDToIndex_.clear();
0307 
0308     for (auto const& product : productList_) {
0309       auto const& desc = product.second;
0310 
0311       checkForDuplicateProcessName(desc, processName);
0312 
0313       if (desc.produced() && !desc.transient()) {
0314         setProductProduced(desc.branchType());
0315       }
0316 
0317       //only do the following if the data is supposed to be available in the event
0318       if (desc.present()) {
0319         // Check dictionaries (we already checked for the produced ones earlier somewhere else).
0320         // We have to have the dictionaries to properly setup the lookup tables for support of
0321         // Views. Also we need them to determine which present products are declared to be
0322         // consumed in the case where the consumed type is a View<T>.
0323         if (!desc.produced()) {
0324           if (!checkDictionary(missingDictionaries, desc.className(), desc.unwrappedType())) {
0325             checkDictionaryOfWrappedType(missingDictionaries, desc.className());
0326             branchNamesForMissing.emplace_back(desc.branchName());
0327             producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
0328             continue;
0329           }
0330         }
0331         TypeID typeID(desc.unwrappedType().typeInfo());
0332 
0333         auto iterContainedType = containedTypeMap.find(typeID);
0334         bool alreadySawThisType = (iterContainedType != containedTypeMap.end());
0335 
0336         if (!desc.produced() && !alreadySawThisType) {
0337           if (!checkDictionary(missingDictionaries, desc.wrappedName(), desc.wrappedType())) {
0338             branchNamesForMissing.emplace_back(desc.branchName());
0339             producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
0340             continue;
0341           }
0342         }
0343 
0344         TypeID wrappedTypeID(desc.wrappedType().typeInfo());
0345 
0346         TypeID containedTypeID;
0347         if (alreadySawThisType) {
0348           containedTypeID = iterContainedType->second;
0349         } else {
0350           containedTypeID = productholderindexhelper::getContainedTypeFromWrapper(wrappedTypeID, typeID.className());
0351         }
0352         bool hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
0353 
0354         std::vector<TypeWithDict>* baseTypesOfContainedType = nullptr;
0355 
0356         if (!alreadySawThisType) {
0357           bool alreadyCheckedConstituents = desc.produced() && !desc.transient();
0358           if (!alreadyCheckedConstituents && !desc.transient()) {
0359             // This checks dictionaries of the wrapped class and all its constituent classes
0360             if (!checkClassDictionaries(missingDictionaries, desc.wrappedName(), desc.wrappedType())) {
0361               branchNamesForMissing.emplace_back(desc.branchName());
0362               producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
0363               continue;
0364             }
0365           }
0366 
0367           if (hasContainedType) {
0368             auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
0369             if (iterBaseTypes == containedTypeToBaseTypesMap.end()) {
0370               std::vector<TypeWithDict> baseTypes;
0371               if (!public_base_classes(missingDictionaries, containedTypeID, baseTypes)) {
0372                 branchNamesForMissing.emplace_back(desc.branchName());
0373                 if (desc.produced()) {
0374                   producedTypes.emplace_back(desc.className() + std::string(" (produced in current process)"));
0375                 } else {
0376                   producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
0377                 }
0378                 continue;
0379               }
0380               iterBaseTypes = containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, baseTypes)).first;
0381             }
0382             baseTypesOfContainedType = &iterBaseTypes->second;
0383           }
0384 
0385           // Do this after the dictionary checks of constituents so the list of branch names for missing types
0386           // is complete
0387           containedTypeMap.emplace(typeID, containedTypeID);
0388         } else {
0389           if (hasContainedType) {
0390             auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
0391             if (iterBaseTypes != containedTypeToBaseTypesMap.end()) {
0392               baseTypesOfContainedType = &iterBaseTypes->second;
0393             }
0394           }
0395         }
0396 
0397         if (productTypesConsumed != nullptr && !desc.produced()) {
0398           bool mainTypeConsumed = (productTypesConsumed->find(typeID) != productTypesConsumed->end());
0399           bool containedTypeConsumed =
0400               hasContainedType && (elementTypesConsumed->find(containedTypeID) != elementTypesConsumed->end());
0401           if (hasContainedType && !containedTypeConsumed && baseTypesOfContainedType != nullptr) {
0402             for (TypeWithDict const& baseType : *baseTypesOfContainedType) {
0403               if (elementTypesConsumed->find(TypeID(baseType.typeInfo())) != elementTypesConsumed->end()) {
0404                 containedTypeConsumed = true;
0405                 break;
0406               }
0407             }
0408           }
0409           if (!containedTypeConsumed) {
0410             if (mainTypeConsumed) {
0411               // The main type is consumed, but either
0412               // there is no contained type, or if there is,
0413               // neither it nor any of its base classes are consumed.
0414               // Set the contained type, if there is one, to void,
0415               if (hasContainedType) {
0416                 containedTypeID = TypeID(typeid(void));
0417               }
0418             } else {
0419               // The main type is not consumed, and either
0420               // there is no contained type, or if there is,
0421               // neither it nor any of its base classes are consumed.
0422               // Don't insert anything in the lookup tables.
0423               continue;
0424             }
0425           }
0426         }
0427         ProductResolverIndex index = productLookup(desc.branchType())
0428                                          ->insert(typeID,
0429                                                   desc.moduleLabel().c_str(),
0430                                                   desc.productInstanceName().c_str(),
0431                                                   desc.processName().c_str(),
0432                                                   containedTypeID,
0433                                                   baseTypesOfContainedType);
0434 
0435         transient_.branchIDToIndex_[desc.branchID()] = index;
0436       }
0437     }
0438     if (!missingDictionaries.empty()) {
0439       std::string context("Calling ProductRegistry::initializeLookupTables");
0440       throwMissingDictionariesException(missingDictionaries, context, producedTypes, branchNamesForMissing);
0441     }
0442 
0443     for (auto& iterProductLookup : transient_.productLookups_) {
0444       iterProductLookup->setFrozen();
0445     }
0446 
0447     unsigned int indexIntoNextIndexValue = 0;
0448     for (auto const& iterProductLookup : transient_.productLookups_) {
0449       transient_.nextIndexValues_[indexIntoNextIndexValue] = iterProductLookup->nextIndexValue();
0450       ++indexIntoNextIndexValue;
0451     }
0452 
0453     for (auto const& product : productList_) {
0454       auto const& desc = product.second;
0455       if (transient_.branchIDToIndex_.find(desc.branchID()) == transient_.branchIDToIndex_.end()) {
0456         transient_.branchIDToIndex_[desc.branchID()] = getNextIndexValue(desc.branchType());
0457         ++nextIndexValue(desc.branchType());
0458       }
0459     }
0460     checkDictionariesOfConsumedTypes(
0461         productTypesConsumed, elementTypesConsumed, containedTypeMap, containedTypeToBaseTypesMap);
0462 
0463     addElementTypesForAliases(elementTypesConsumed, containedTypeMap, containedTypeToBaseTypesMap);
0464   }
0465 
0466   void ProductRegistry::addElementTypesForAliases(
0467       std::set<TypeID> const* elementTypesConsumed,
0468       std::map<TypeID, TypeID> const& containedTypeMap,
0469       std::map<TypeID, std::vector<TypeWithDict>> const& containedTypeToBaseTypesMap) {
0470     Transients::AliasToOriginalVector elementAliases;
0471     for (auto& item : transient_.aliasToOriginal_) {
0472       auto iterContainedType = containedTypeMap.find(std::get<Transients::kType>(item));
0473       if (iterContainedType == containedTypeMap.end()) {
0474         edm::Exception ex(errors::LogicError);
0475         ex << "containedTypeMap did not contain " << std::get<Transients::kType>(item).className()
0476            << " that is used in EDAlias " << std::get<Transients::kModuleLabel>(item)
0477            << ".\nThis should not happen, contact framework developers";
0478         ex.addContext("Calling ProductRegistry::initializeLookupTables()");
0479         throw ex;
0480       }
0481       auto const& containedTypeID = iterContainedType->second;
0482       bool const hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
0483       if (not hasContainedType) {
0484         continue;
0485       }
0486 
0487       if (elementTypesConsumed->find(containedTypeID) != elementTypesConsumed->end()) {
0488         elementAliases.emplace_back(ELEMENT_TYPE,
0489                                     containedTypeID,
0490                                     std::get<Transients::kModuleLabel>(item),
0491                                     std::get<Transients::kProductInstanceName>(item),
0492                                     std::get<Transients::kAliasForModuleLabel>(item));
0493       }
0494 
0495       auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
0496       if (iterBaseTypes == containedTypeToBaseTypesMap.end()) {
0497         continue;
0498       }
0499       for (TypeWithDict const& baseType : iterBaseTypes->second) {
0500         TypeID baseTypeID(baseType.typeInfo());
0501         if (elementTypesConsumed->find(baseTypeID) != elementTypesConsumed->end()) {
0502           elementAliases.emplace_back(ELEMENT_TYPE,
0503                                       baseTypeID,
0504                                       std::get<Transients::kModuleLabel>(item),
0505                                       std::get<Transients::kProductInstanceName>(item),
0506                                       std::get<Transients::kAliasForModuleLabel>(item));
0507         }
0508       }
0509     }
0510     transient_.aliasToOriginal_.insert(transient_.aliasToOriginal_.end(),
0511                                        std::make_move_iterator(elementAliases.begin()),
0512                                        std::make_move_iterator(elementAliases.end()));
0513   }
0514 
0515   void ProductRegistry::checkDictionariesOfConsumedTypes(
0516       std::set<TypeID> const* productTypesConsumed,
0517       std::set<TypeID> const* elementTypesConsumed,
0518       std::map<TypeID, TypeID> const& containedTypeMap,
0519       std::map<TypeID, std::vector<TypeWithDict>>& containedTypeToBaseTypesMap) {
0520     std::vector<std::string> missingDictionaries;
0521     std::set<std::string> consumedTypesWithMissingDictionaries;
0522 
0523     if (productTypesConsumed) {
0524       // Check dictionaries for all classes declared to be consumed
0525       for (auto const& consumedTypeID : *productTypesConsumed) {
0526         // We use the containedTypeMap to see which types have already
0527         // had their dictionaries checked. We do not waste time rechecking
0528         // those dictionaries.
0529         if (containedTypeMap.find(consumedTypeID) == containedTypeMap.end()) {
0530           std::string wrappedName = wrappedClassName(consumedTypeID.className());
0531           TypeWithDict wrappedType = TypeWithDict::byName(wrappedName);
0532           if (!checkDictionary(missingDictionaries, wrappedName, wrappedType)) {
0533             checkDictionary(missingDictionaries, consumedTypeID);
0534             consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0535             continue;
0536           }
0537           bool transient = false;
0538           TDictAttributeMap* wp = wrappedType.getClass()->GetAttributeMap();
0539           if (wp && wp->HasKey("persistent") && !strcmp(wp->GetPropertyAsString("persistent"), "false")) {
0540             transient = true;
0541           }
0542           if (transient) {
0543             if (!checkDictionary(missingDictionaries, consumedTypeID)) {
0544               consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0545             }
0546 
0547             TypeID containedTypeID = productholderindexhelper::getContainedTypeFromWrapper(
0548                 TypeID(wrappedType.typeInfo()), consumedTypeID.className());
0549             bool hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
0550             if (hasContainedType) {
0551               if (containedTypeToBaseTypesMap.find(containedTypeID) == containedTypeToBaseTypesMap.end()) {
0552                 std::vector<TypeWithDict> bases;
0553                 // Run this to check for missing dictionaries, bases is not really used
0554                 if (!public_base_classes(missingDictionaries, containedTypeID, bases)) {
0555                   consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0556                 }
0557                 containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, bases));
0558               }
0559             }
0560           } else {
0561             if (!checkClassDictionaries(missingDictionaries, wrappedName, wrappedType)) {
0562               consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0563             }
0564           }
0565         }
0566       }
0567       if (!missingDictionaries.empty()) {
0568         std::string context(
0569             "Calling ProductRegistry::initializeLookupTables, checking dictionaries for consumed products");
0570         throwMissingDictionariesException(missingDictionaries, context, consumedTypesWithMissingDictionaries, false);
0571       }
0572     }
0573 
0574     if (elementTypesConsumed) {
0575       missingDictionaries.clear();
0576       consumedTypesWithMissingDictionaries.clear();
0577       for (auto const& consumedTypeID : *elementTypesConsumed) {
0578         if (containedTypeToBaseTypesMap.find(consumedTypeID) == containedTypeToBaseTypesMap.end()) {
0579           std::vector<TypeWithDict> bases;
0580           // Run this to check for missing dictionaries, bases is not really used
0581           if (!public_base_classes(missingDictionaries, consumedTypeID, bases)) {
0582             consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
0583           }
0584         }
0585       }
0586       if (!missingDictionaries.empty()) {
0587         std::string context(
0588             "Calling ProductRegistry::initializeLookupTables, checking dictionaries for elements of products consumed "
0589             "using View");
0590         throwMissingDictionariesException(missingDictionaries, context, consumedTypesWithMissingDictionaries, true);
0591       }
0592     }
0593   }
0594 
0595   void ProductRegistry::checkForDuplicateProcessName(BranchDescription const& desc,
0596                                                      std::string const* processName) const {
0597     if (processName && !desc.produced() && (*processName == desc.processName())) {
0598       throw Exception(errors::Configuration, "Duplicate Process Name.\n")
0599           << "The process name " << *processName << " was previously used for products in the input.\n"
0600           << "Please modify the configuration file to use a distinct process name.\n"
0601           << "Alternately, drop all input products using that process name and the\n"
0602           << "descendants of those products.\n";
0603     }
0604   }
0605 
0606   ProductResolverIndex ProductRegistry::indexFrom(BranchID const& iID) const {
0607     std::map<BranchID, ProductResolverIndex>::const_iterator itFind = transient_.branchIDToIndex_.find(iID);
0608     if (itFind == transient_.branchIDToIndex_.end()) {
0609       return ProductResolverIndexInvalid;
0610     }
0611     return itFind->second;
0612   }
0613 
0614   std::vector<std::string> ProductRegistry::aliasToModules(KindOfType kindOfType,
0615                                                            TypeID const& type,
0616                                                            std::string_view moduleLabel,
0617                                                            std::string_view productInstanceName) const {
0618     auto aliasFields = [](auto const& item) {
0619       return std::tie(std::get<Transients::kKind>(item),
0620                       std::get<Transients::kType>(item),
0621                       std::get<Transients::kModuleLabel>(item),
0622                       std::get<Transients::kProductInstanceName>(item));
0623     };
0624     auto const target = std::tuple(kindOfType, type, moduleLabel, productInstanceName);
0625     auto found =
0626         std::lower_bound(transient_.aliasToOriginal_.begin(),
0627                          transient_.aliasToOriginal_.end(),
0628                          target,
0629                          [aliasFields](auto const& item, auto const& target) { return aliasFields(item) < target; });
0630     std::vector<std::string> ret;
0631     for (; found != transient_.aliasToOriginal_.end() and aliasFields(*found) == target; ++found) {
0632       ret.emplace_back(std::get<Transients::kAliasForModuleLabel>(*found));
0633     }
0634     return ret;
0635   }
0636 
0637   void ProductRegistry::print(std::ostream& os) const {
0638     for (auto const& product : productList_) {
0639       os << product.second << "\n-----\n";
0640     }
0641   }
0642 
0643   ProductResolverIndex const& ProductRegistry::getNextIndexValue(BranchType branchType) const {
0644     return transient_.nextIndexValues_[branchType];
0645   }
0646 
0647   ProductResolverIndex& ProductRegistry::nextIndexValue(BranchType branchType) {
0648     return transient_.nextIndexValues_[branchType];
0649   }
0650 }  // namespace edm