Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-03-13 02:31:32

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