Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-31 02:19:24

0001 /*----------------------------------------------------------------------
0002 
0003 ----------------------------------------------------------------------*/
0004 
0005 #include "FWCore/Framework/interface/ProductRegistryHelper.h"
0006 #include "DataFormats/Common/interface/setIsMergeable.h"
0007 #include "DataFormats/Provenance/interface/ProductRegistry.h"
0008 #include "DataFormats/Provenance/interface/ProductDescription.h"
0009 #include "DataFormats/Provenance/interface/ModuleDescription.h"
0010 #include "FWCore/Reflection/interface/DictionaryTools.h"
0011 #include "FWCore/Utilities/interface/EDMException.h"
0012 #include "FWCore/Reflection/interface/TypeWithDict.h"
0013 
0014 #include <vector>
0015 #include <typeindex>
0016 
0017 namespace edm {
0018   ProductRegistryHelper::~ProductRegistryHelper() noexcept(false) {}
0019 
0020   ProductRegistryHelper::TypeLabelList const& ProductRegistryHelper::typeLabelList() const { return typeLabelList_; }
0021 
0022   namespace {
0023     void throwProducesWithoutAbility(const char* transitionName, std::string const& productTypeName) {
0024       throw edm::Exception(edm::errors::LogicError)
0025           << "Module declares it can produce a product of type \'" << productTypeName << "\'\nin a " << transitionName
0026           << ", but does not have the ability to produce in " << transitionName << "s.\n"
0027           << "You must add a template parameter of type " << transitionName << "Producer\n"
0028           << "or " << transitionName << "Producer to the EDProducer or EDFilter base class\n"
0029           << "of the module. Or you could remove the call to the function \'produces\'\n"
0030           << "(Note legacy modules are not ever allowed to produce in Runs or Lumis)\n";
0031     }
0032   }  // namespace
0033 
0034   void ProductRegistryHelper::addToRegistry(TypeLabelList::const_iterator const& iBegin,
0035                                             TypeLabelList::const_iterator const& iEnd,
0036                                             ModuleDescription const& iDesc,
0037                                             ProductRegistry& iReg,
0038                                             ProductRegistryHelper* iProd,
0039                                             bool iIsListener) {
0040     std::vector<std::string> missingDictionaries;
0041     std::vector<std::string> producedTypes;
0042     std::set<std::tuple<BranchType, std::type_index, std::string>> registeredProducts;
0043 
0044     for (TypeLabelList::const_iterator p = iBegin; p != iEnd; ++p) {
0045       if (p->transition_ == Transition::BeginRun && not iProd->hasAbilityToProduceInBeginRuns()) {
0046         throwProducesWithoutAbility("BeginRun", p->typeID_.userClassName());
0047       } else if (p->transition_ == Transition::EndRun && not iProd->hasAbilityToProduceInEndRuns()) {
0048         throwProducesWithoutAbility("EndRun", p->typeID_.userClassName());
0049       } else if (p->transition_ == Transition::BeginLuminosityBlock && not iProd->hasAbilityToProduceInBeginLumis()) {
0050         throwProducesWithoutAbility("BeginLuminosityBlock", p->typeID_.userClassName());
0051       } else if (p->transition_ == Transition::EndLuminosityBlock && not iProd->hasAbilityToProduceInEndLumis()) {
0052         throwProducesWithoutAbility("EndLuminosityBlock", p->typeID_.userClassName());
0053       } else if (p->transition_ == Transition::BeginProcessBlock &&
0054                  not iProd->hasAbilityToProduceInBeginProcessBlocks()) {
0055         throwProducesWithoutAbility("BeginProcessBlock", p->typeID_.userClassName());
0056       } else if (p->transition_ == Transition::EndProcessBlock && not iProd->hasAbilityToProduceInEndProcessBlocks()) {
0057         throwProducesWithoutAbility("EndProcessBlock", p->typeID_.userClassName());
0058       }
0059       if (!checkDictionary(missingDictionaries, p->typeID_)) {
0060         checkDictionaryOfWrappedType(missingDictionaries, p->typeID_);
0061         producedTypes.emplace_back(p->typeID_.className());
0062         continue;
0063       }
0064       auto branchType = convertToBranchType(p->transition_);
0065       if (branchType != InEvent) {
0066         std::tuple<BranchType, std::type_index, std::string> entry{
0067             branchType, p->typeID_.typeInfo(), p->productInstanceName_};
0068         if (registeredProducts.end() != registeredProducts.find(entry)) {
0069           //ignore registration of items if in both begin and end transitions for now
0070           // This is to work around ExternalLHEProducer
0071           continue;
0072         } else {
0073           registeredProducts.insert(entry);
0074         }
0075       }
0076 
0077       TypeWithDict type(p->typeID_.typeInfo());
0078       ProductDescription pdesc(branchType,
0079                                iDesc.moduleLabel(),
0080                                iDesc.processName(),
0081                                p->typeID_.userClassName(),
0082                                p->typeID_.friendlyClassName(),
0083                                p->productInstanceName_,
0084                                type,
0085                                true,
0086                                isEndTransition(p->transition_));
0087       if (p->aliasType_ == TypeLabelItem::AliasType::kSwitchAlias) {
0088         if (p->branchAlias_.empty()) {
0089           throw edm::Exception(edm::errors::LogicError)
0090               << "Branch alias type has been set to SwitchAlias, but the alias content is empty.\n"
0091               << "Please report this error to the FWCore developers";
0092         }
0093         pdesc.setSwitchAliasModuleLabel(p->branchAlias_);
0094       }
0095       if (p->isTransform_) {
0096         pdesc.setOnDemand(true);
0097         pdesc.setIsTransform(true);
0098       }
0099       setIsMergeable(pdesc);
0100 
0101       if (pdesc.transient()) {
0102         if (!checkDictionary(missingDictionaries, pdesc.wrappedName(), pdesc.wrappedType())) {
0103           // It is should be impossible to get here, because the only way to
0104           // make it transient is in the line that causes the wrapped dictionary
0105           // to be created. Just to be safe I leave this check here ...
0106           producedTypes.emplace_back(pdesc.className());
0107           continue;
0108         }
0109       } else {
0110         // also check constituents of wrapped types if it is not transient
0111         if (!checkClassDictionaries(missingDictionaries, pdesc.wrappedName(), pdesc.wrappedType())) {
0112           producedTypes.emplace_back(pdesc.className());
0113           continue;
0114         }
0115       }
0116       if (!p->branchAlias_.empty())
0117         pdesc.insertBranchAlias(p->branchAlias_);
0118       iReg.addProduct(pdesc, iIsListener);
0119     }
0120 
0121     if (!missingDictionaries.empty()) {
0122       std::string context("Calling ProductRegistryHelper::addToRegistry, checking dictionaries for produced types");
0123       throwMissingDictionariesException(missingDictionaries, context, producedTypes);
0124     }
0125   }
0126 }  // namespace edm