Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:28:00

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/BranchDescription.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       BranchDescription pdesc(branchType,
0079                               iDesc.moduleLabel(),
0080                               iDesc.processName(),
0081                               p->typeID_.userClassName(),
0082                               p->typeID_.friendlyClassName(),
0083                               p->productInstanceName_,
0084                               iDesc.moduleName(),
0085                               iDesc.parameterSetID(),
0086                               type,
0087                               true,
0088                               isEndTransition(p->transition_));
0089       if (p->aliasType_ == TypeLabelItem::AliasType::kSwitchAlias) {
0090         if (p->branchAlias_.empty()) {
0091           throw edm::Exception(edm::errors::LogicError)
0092               << "Branch alias type has been set to SwitchAlias, but the alias content is empty.\n"
0093               << "Please report this error to the FWCore developers";
0094         }
0095         pdesc.setSwitchAliasModuleLabel(p->branchAlias_);
0096       }
0097       setIsMergeable(pdesc);
0098 
0099       if (pdesc.transient()) {
0100         if (!checkDictionary(missingDictionaries, pdesc.wrappedName(), pdesc.wrappedType())) {
0101           // It is should be impossible to get here, because the only way to
0102           // make it transient is in the line that causes the wrapped dictionary
0103           // to be created. Just to be safe I leave this check here ...
0104           producedTypes.emplace_back(pdesc.className());
0105           continue;
0106         }
0107       } else {
0108         // also check constituents of wrapped types if it is not transient
0109         if (!checkClassDictionaries(missingDictionaries, pdesc.wrappedName(), pdesc.wrappedType())) {
0110           producedTypes.emplace_back(pdesc.className());
0111           continue;
0112         }
0113       }
0114       if (!p->branchAlias_.empty())
0115         pdesc.insertBranchAlias(p->branchAlias_);
0116       iReg.addProduct(pdesc, iIsListener);
0117     }
0118 
0119     if (!missingDictionaries.empty()) {
0120       std::string context("Calling ProductRegistryHelper::addToRegistry, checking dictionaries for produced types");
0121       throwMissingDictionariesException(missingDictionaries, context, producedTypes);
0122     }
0123   }
0124 }  // namespace edm