Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-09-11 22:29:32

0001 // -*- C++ -*-
0002 //
0003 // Package:     FWCore/Framework
0004 // Class  :     EDConsumerBase
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Tue, 02 Apr 2013 21:36:06 GMT
0011 //
0012 
0013 // system include files
0014 #include <array>
0015 #include <algorithm>
0016 #include <cassert>
0017 #include <cstring>
0018 #include <set>
0019 #include <utility>
0020 
0021 // user include files
0022 #include "FWCore/Framework/interface/EDConsumerBase.h"
0023 #include "FWCore/Framework/interface/ConsumesCollector.h"
0024 #include "FWCore/Framework/interface/ESRecordsToProxyIndices.h"
0025 #include "FWCore/Framework/interface/ComponentDescription.h"
0026 #include "FWCore/Framework/interface/ModuleProcessName.h"
0027 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0028 #include "FWCore/Utilities/interface/BranchType.h"
0029 #include "FWCore/Utilities/interface/Likely.h"
0030 #include "FWCore/Utilities/interface/Exception.h"
0031 #include "DataFormats/Provenance/interface/ProductResolverIndexHelper.h"
0032 #include "DataFormats/Provenance/interface/ProductRegistry.h"
0033 
0034 using namespace edm;
0035 
0036 namespace {
0037   std::vector<char> makeEmptyTokenLabels() { return std::vector<char>{'\0'}; }
0038 }  // namespace
0039 
0040 EDConsumerBase::EDConsumerBase()
0041     : m_tokenLabels{makeEmptyTokenLabels()}, frozen_(false), containsCurrentProcessAlias_(false) {}
0042 
0043 EDConsumerBase::~EDConsumerBase() noexcept(false) {}
0044 
0045 //
0046 // member functions
0047 //
0048 ConsumesCollector EDConsumerBase::consumesCollector() {
0049   ConsumesCollector c{this};
0050   return c;
0051 }
0052 
0053 static const edm::InputTag kWasEmpty("@EmptyLabel@");
0054 
0055 edm::InputTag const& EDConsumerBase::checkIfEmpty(edm::InputTag const& iTag) {
0056   if (iTag.label().empty()) {
0057     return kWasEmpty;
0058   }
0059   return iTag;
0060 }
0061 
0062 unsigned int EDConsumerBase::recordConsumes(BranchType iBranch,
0063                                             TypeToGet const& iType,
0064                                             edm::InputTag const& iTag,
0065                                             bool iAlwaysGets) {
0066   if (frozen_) {
0067     throwConsumesCallAfterFrozen(iType, iTag);
0068   }
0069 
0070   unsigned int index = m_tokenInfo.size();
0071 
0072   bool skipCurrentProcess = iTag.willSkipCurrentProcess();
0073 
0074   const size_t labelSize = iTag.label().size();
0075   const size_t productInstanceSize = iTag.instance().size();
0076   unsigned int labelStart = m_tokenLabels.size();
0077   unsigned short delta1 = labelSize + 1;
0078   unsigned short delta2 = labelSize + 2 + productInstanceSize;
0079   m_tokenInfo.emplace_back(TokenLookupInfo{iType.type(), ProductResolverIndexInvalid, skipCurrentProcess, iBranch},
0080                            iAlwaysGets,
0081                            LabelPlacement{labelStart, delta1, delta2},
0082                            iType.kind());
0083 
0084   const size_t additionalSize = skipCurrentProcess ? labelSize + productInstanceSize + 3
0085                                                    : labelSize + productInstanceSize + iTag.process().size() + 3;
0086 
0087   m_tokenLabels.reserve(m_tokenLabels.size() + additionalSize);
0088   {
0089     const std::string& m = iTag.label();
0090     m_tokenLabels.insert(m_tokenLabels.end(), m.begin(), m.end());
0091     m_tokenLabels.push_back('\0');
0092   }
0093   {
0094     const std::string& m = iTag.instance();
0095     m_tokenLabels.insert(m_tokenLabels.end(), m.begin(), m.end());
0096     m_tokenLabels.push_back('\0');
0097   }
0098   {
0099     const std::string& m = iTag.process();
0100     if (m == InputTag::kCurrentProcess) {
0101       containsCurrentProcessAlias_ = true;
0102     }
0103     if (!skipCurrentProcess) {
0104       m_tokenLabels.insert(m_tokenLabels.end(), m.begin(), m.end());
0105       m_tokenLabels.push_back('\0');
0106     } else {
0107       m_tokenLabels.push_back('\0');
0108     }
0109   }
0110   return index;
0111 }
0112 
0113 void EDConsumerBase::extendUpdateLookup(BranchType, ProductResolverIndexHelper const&) {}
0114 
0115 void EDConsumerBase::updateLookup(BranchType iBranchType,
0116                                   ProductResolverIndexHelper const& iHelper,
0117                                   bool iPrefetchMayGet) {
0118   frozen_ = true;
0119   assert(!containsCurrentProcessAlias_);
0120   extendUpdateLookup(iBranchType, iHelper);
0121   {
0122     auto itKind = m_tokenInfo.begin<kKind>();
0123     auto itLabels = m_tokenInfo.begin<kLabels>();
0124     for (auto itInfo = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); itInfo != itEnd;
0125          ++itInfo, ++itKind, ++itLabels) {
0126       if (itInfo->m_branchType == iBranchType) {
0127         const unsigned int labelStart = itLabels->m_startOfModuleLabel;
0128         const char* moduleLabel = &(m_tokenLabels[labelStart]);
0129         itInfo->m_index = ProductResolverIndexAndSkipBit(iHelper.index(*itKind,
0130                                                                        itInfo->m_type,
0131                                                                        moduleLabel,
0132                                                                        moduleLabel + itLabels->m_deltaToProductInstance,
0133                                                                        moduleLabel + itLabels->m_deltaToProcessName),
0134                                                          itInfo->m_index.skipCurrentProcess());
0135       }
0136     }
0137   }
0138 
0139   //now add resolved requests to get many to the end of our list
0140   // a get many will have an empty module label
0141   for (size_t i = 0, iEnd = m_tokenInfo.size(); i != iEnd; ++i) {
0142     //need to copy since pointer could be invalidated by emplace_back
0143     auto const info = m_tokenInfo.get<kLookupInfo>(i);
0144     if (info.m_branchType == iBranchType && info.m_index.productResolverIndex() == ProductResolverIndexInvalid &&
0145         m_tokenLabels[m_tokenInfo.get<kLabels>(i).m_startOfModuleLabel] == '\0') {
0146       //find all matching types
0147       const auto kind = m_tokenInfo.get<kKind>(i);
0148       auto matches = iHelper.relatedIndexes(kind, info.m_type);
0149 
0150       //NOTE: This could be changed to contain the true labels for what is being
0151       // requested but for now I want to remember these are part of a get many
0152       const LabelPlacement labels = m_tokenInfo.get<kLabels>(i);
0153       bool alwaysGet = m_tokenInfo.get<kAlwaysGets>(i);
0154       for (unsigned int j = 0; j != matches.numberOfMatches(); ++j) {
0155         //only keep the ones that are for a specific data item and not a collection
0156         if (matches.isFullyResolved(j)) {
0157           auto index = matches.index(j);
0158           m_tokenInfo.emplace_back(
0159               TokenLookupInfo{info.m_type, index, info.m_index.skipCurrentProcess(), info.m_branchType},
0160               alwaysGet,
0161               labels,
0162               kind);
0163         }
0164       }
0165     }
0166   }
0167   m_tokenInfo.shrink_to_fit();
0168 
0169   itemsToGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
0170   if (iPrefetchMayGet) {
0171     itemsMayGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
0172   }
0173 }
0174 
0175 void EDConsumerBase::updateLookup(eventsetup::ESRecordsToProxyIndices const& iPI) {
0176   // temporarily unfreeze to allow late EventSetup consumes registration
0177   frozen_ = false;
0178   registerLateConsumes(iPI);
0179   frozen_ = true;
0180 
0181   unsigned int index = 0;
0182   for (auto it = m_esTokenInfo.begin<kESLookupInfo>(); it != m_esTokenInfo.end<kESLookupInfo>(); ++it, ++index) {
0183     auto indexInRecord = iPI.indexInRecord(it->m_record, it->m_key);
0184     if (indexInRecord != eventsetup::ESRecordsToProxyIndices::missingProxyIndex()) {
0185       const char* componentName = &(m_tokenLabels[it->m_startOfComponentName]);
0186       if (*componentName) {
0187         auto component = iPI.component(it->m_record, it->m_key);
0188         if (component->label_.empty()) {
0189           if (component->type_ != componentName) {
0190             indexInRecord = eventsetup::ESRecordsToProxyIndices::missingProxyIndex();
0191           }
0192         } else if (component->label_ != componentName) {
0193           indexInRecord = eventsetup::ESRecordsToProxyIndices::missingProxyIndex();
0194         }
0195       }
0196     }
0197     m_esTokenInfo.get<kESProxyIndex>(index) = indexInRecord;
0198 
0199     int negIndex = -1 * (index + 1);
0200     for (auto& items : esItemsToGetFromTransition_) {
0201       for (auto& itemIndex : items) {
0202         if (itemIndex.value() == negIndex) {
0203           itemIndex = indexInRecord;
0204           esRecordsToGetFromTransition_[&items - &esItemsToGetFromTransition_.front()][&itemIndex - &items.front()] =
0205               iPI.recordIndexFor(it->m_record);
0206           negIndex = 1;
0207           break;
0208         }
0209       }
0210       if (negIndex > 0) {
0211         break;
0212       }
0213     }
0214   }
0215 }
0216 
0217 ESTokenIndex EDConsumerBase::recordESConsumes(Transition iTrans,
0218                                               eventsetup::EventSetupRecordKey const& iRecord,
0219                                               eventsetup::heterocontainer::HCTypeTag const& iDataType,
0220                                               edm::ESInputTag const& iTag) {
0221   if (frozen_) {
0222     throwESConsumesCallAfterFrozen(iRecord, iDataType, iTag);
0223   }
0224 
0225   //m_tokenLabels first entry is a null. Since most ES data requests have
0226   // empty labels we will assume we can reuse the first entry
0227   unsigned int startOfComponentName = 0;
0228   if (not iTag.module().empty()) {
0229     startOfComponentName = m_tokenLabels.size();
0230 
0231     m_tokenLabels.reserve(m_tokenLabels.size() + iTag.module().size() + 1);
0232     {
0233       const std::string& m = iTag.module();
0234       m_tokenLabels.insert(m_tokenLabels.end(), m.begin(), m.end());
0235       m_tokenLabels.push_back('\0');
0236     }
0237   }
0238 
0239   auto index = static_cast<ESProxyIndex::Value_t>(m_esTokenInfo.size());
0240   m_esTokenInfo.emplace_back(
0241       ESTokenLookupInfo{iRecord, eventsetup::DataKey{iDataType, iTag.data().c_str()}, startOfComponentName},
0242       ESProxyIndex{-1});
0243   if (iTrans >= edm::Transition::NumberOfEventSetupTransitions) {
0244     throwESConsumesInProcessBlock();
0245   }
0246   auto indexForToken = esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)].size();
0247   esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)].emplace_back(-1 * (index + 1));
0248   esRecordsToGetFromTransition_[static_cast<unsigned int>(iTrans)].emplace_back();
0249   return ESTokenIndex{static_cast<ESTokenIndex::Value_t>(indexForToken)};
0250 }
0251 
0252 //
0253 // const member functions
0254 //
0255 ProductResolverIndexAndSkipBit EDConsumerBase::indexFrom(EDGetToken iToken,
0256                                                          BranchType iBranch,
0257                                                          TypeID const& iType) const {
0258   if (UNLIKELY(iToken.index() >= m_tokenInfo.size())) {
0259     throwBadToken(iType, iToken);
0260   }
0261   const auto& info = m_tokenInfo.get<kLookupInfo>(iToken.index());
0262   if (LIKELY(iBranch == info.m_branchType)) {
0263     if (LIKELY(iType == info.m_type)) {
0264       return info.m_index;
0265     } else {
0266       throwTypeMismatch(iType, iToken);
0267     }
0268   } else {
0269     throwBranchMismatch(iBranch, iToken);
0270   }
0271   return ProductResolverIndexAndSkipBit(edm::ProductResolverIndexInvalid, false);
0272 }
0273 
0274 ProductResolverIndexAndSkipBit EDConsumerBase::uncheckedIndexFrom(EDGetToken iToken) const {
0275   return m_tokenInfo.get<kLookupInfo>(iToken.index()).m_index;
0276 }
0277 
0278 void EDConsumerBase::itemsToGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const {
0279   //how many are we adding?
0280   unsigned int count = 0;
0281   {
0282     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0283     for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0284          ++it, ++itAlwaysGet) {
0285       if (iBranch == it->m_branchType) {
0286         if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0287           if (*itAlwaysGet) {
0288             ++count;
0289           }
0290         }
0291       }
0292     }
0293   }
0294   oIndices.reserve(oIndices.size() + count);
0295   {
0296     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0297     for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0298          ++it, ++itAlwaysGet) {
0299       if (iBranch == it->m_branchType) {
0300         if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0301           if (*itAlwaysGet) {
0302             oIndices.push_back(it->m_index);
0303           }
0304         }
0305       }
0306     }
0307   }
0308 }
0309 
0310 void EDConsumerBase::itemsMayGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const {
0311   //how many are we adding?
0312   unsigned int count = 0;
0313   {
0314     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0315     for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0316          ++it, ++itAlwaysGet) {
0317       if (iBranch == it->m_branchType) {
0318         if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0319           if (not *itAlwaysGet) {
0320             ++count;
0321           }
0322         }
0323       }
0324     }
0325   }
0326   oIndices.reserve(oIndices.size() + count);
0327   {
0328     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0329     for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0330          ++it, ++itAlwaysGet) {
0331       if (iBranch == it->m_branchType) {
0332         if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0333           if (not *itAlwaysGet) {
0334             oIndices.push_back(it->m_index);
0335           }
0336         }
0337       }
0338     }
0339   }
0340 }
0341 
0342 void EDConsumerBase::labelsForToken(EDGetToken iToken, Labels& oLabels) const {
0343   unsigned int index = iToken.index();
0344   auto labels = m_tokenInfo.get<kLabels>(index);
0345   unsigned int start = labels.m_startOfModuleLabel;
0346   oLabels.module = &(m_tokenLabels[start]);
0347   oLabels.productInstance = oLabels.module + labels.m_deltaToProductInstance;
0348   oLabels.process = oLabels.module + labels.m_deltaToProcessName;
0349 }
0350 
0351 bool EDConsumerBase::registeredToConsume(ProductResolverIndex iIndex,
0352                                          bool skipCurrentProcess,
0353                                          BranchType iBranch) const {
0354   for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd; ++it) {
0355     if (it->m_index.productResolverIndex() == iIndex and it->m_index.skipCurrentProcess() == skipCurrentProcess and
0356         it->m_branchType == iBranch) {
0357       return true;
0358     }
0359   }
0360   return false;
0361 }
0362 
0363 bool EDConsumerBase::registeredToConsumeMany(TypeID const& iType, BranchType iBranch) const {
0364   for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd; ++it) {
0365     //consumesMany entries do not have their index resolved
0366     if (it->m_index.productResolverIndex() == ProductResolverIndexInvalid and it->m_type == iType and
0367         it->m_branchType == iBranch) {
0368       return true;
0369     }
0370   }
0371   return false;
0372 }
0373 
0374 void EDConsumerBase::throwTypeMismatch(edm::TypeID const& iType, EDGetToken iToken) const {
0375   throw cms::Exception("TypeMismatch") << "A get using a EDGetToken used the C++ type '" << iType.className()
0376                                        << "' but the consumes call was for type '"
0377                                        << m_tokenInfo.get<kLookupInfo>(iToken.index()).m_type.className()
0378                                        << "'.\n Please modify either the consumes or get call so the types match.";
0379 }
0380 void EDConsumerBase::throwBranchMismatch(BranchType iBranch, EDGetToken iToken) const {
0381   throw cms::Exception("BranchTypeMismatch")
0382       << "A get using a EDGetToken was done in " << BranchTypeToString(iBranch) << " but the consumes call was for "
0383       << BranchTypeToString(m_tokenInfo.get<kLookupInfo>(iToken.index()).m_branchType)
0384       << ".\n Please modify the consumes call to use the correct branch type.";
0385 }
0386 
0387 void EDConsumerBase::throwBadToken(edm::TypeID const& iType, EDGetToken iToken) const {
0388   if (iToken.isUninitialized()) {
0389     throw cms::Exception("BadToken") << "A get using a EDGetToken with the C++ type '" << iType.className()
0390                                      << "' was made using an uninitialized token.\n Please check that the variable is "
0391                                         "being initialized from a 'consumes' call.";
0392   }
0393   throw cms::Exception("BadToken")
0394       << "A get using a EDGetToken with the C++ type '" << iType.className() << "' was made using a token with a value "
0395       << iToken.index()
0396       << " which is beyond the range used by this module.\n Please check that the variable is being initialized from a "
0397          "'consumes' call from this module.\n You can not share EDGetToken values between modules.";
0398 }
0399 
0400 void EDConsumerBase::throwConsumesCallAfterFrozen(TypeToGet const& typeToGet, InputTag const& inputTag) const {
0401   throw cms::Exception("LogicError") << "A module declared it consumes a product after its constructor.\n"
0402                                      << "This must be done in the contructor\n"
0403                                      << "The product type was: " << typeToGet.type() << "\n"
0404                                      << "and " << inputTag << "\n";
0405 }
0406 
0407 void EDConsumerBase::throwESConsumesCallAfterFrozen(eventsetup::EventSetupRecordKey const& iRecord,
0408                                                     eventsetup::heterocontainer::HCTypeTag const& iDataType,
0409                                                     edm::ESInputTag const& iTag) const {
0410   throw cms::Exception("LogicError") << "A module declared it consumes an EventSetup product after its constructor.\n"
0411                                      << "This must be done in the contructor\n"
0412                                      << "The product type was: " << iDataType.name() << " in record "
0413                                      << iRecord.type().name() << "\n"
0414                                      << "and ESInputTag was " << iTag << "\n";
0415 }
0416 
0417 void EDConsumerBase::throwESConsumesInProcessBlock() const {
0418   throw cms::Exception("LogicError")
0419       << "A module declared it consumes an EventSetup product during a ProcessBlock transition.\n"
0420       << "EventSetup products can only be consumed in Event, Lumi, or Run transitions.\n";
0421 }
0422 
0423 void EDConsumerBase::doSelectInputProcessBlocks(ProductRegistry const&, ProcessBlockHelperBase const&) {}
0424 
0425 namespace {
0426   struct CharStarComp {
0427     bool operator()(const char* iLHS, const char* iRHS) const { return strcmp(iLHS, iRHS) < 0; }
0428   };
0429 }  // namespace
0430 
0431 namespace {
0432   void insertFoundModuleLabel(edm::KindOfType consumedTypeKind,
0433                               edm::TypeID consumedType,
0434                               const char* consumedModuleLabel,
0435                               const char* consumedProductInstance,
0436                               std::vector<ModuleDescription const*>& modules,
0437                               std::set<std::string>& alreadyFound,
0438                               std::map<std::string, ModuleDescription const*> const& labelsToDesc,
0439                               ProductRegistry const& preg) {
0440     // Convert from label string to module description, eliminate duplicates,
0441     // then insert into the vector of modules
0442     if (auto it = labelsToDesc.find(consumedModuleLabel); it != labelsToDesc.end()) {
0443       if (alreadyFound.insert(consumedModuleLabel).second) {
0444         modules.push_back(it->second);
0445       }
0446       return;
0447     }
0448     // Deal with EDAlias's by converting to the original module label first
0449     if (auto aliasToModuleLabels =
0450             preg.aliasToModules(consumedTypeKind, consumedType, consumedModuleLabel, consumedProductInstance);
0451         not aliasToModuleLabels.empty()) {
0452       bool foundInLabelsToDesc = false;
0453       for (auto const& label : aliasToModuleLabels) {
0454         if (auto it = labelsToDesc.find(label); it != labelsToDesc.end()) {
0455           if (alreadyFound.insert(label).second) {
0456             modules.push_back(it->second);
0457           }
0458           foundInLabelsToDesc = true;
0459         } else {
0460           if (label == "source") {
0461             foundInLabelsToDesc = true;
0462           }
0463         }
0464       }
0465       if (foundInLabelsToDesc) {
0466         return;
0467       }
0468     }
0469     // Ignore the source products, we are only interested in module products.
0470     // As far as I know, it should never be anything else so throw if something
0471     // unknown gets passed in.
0472     if (std::string_view(consumedModuleLabel) != "source") {
0473       throw cms::Exception("EDConsumerBase", "insertFoundModuleLabel")
0474           << "Couldn't find ModuleDescription for the consumed product type: '" << consumedType.className()
0475           << "' module label: '" << consumedModuleLabel << "' product instance name: '" << consumedProductInstance
0476           << "'";
0477     }
0478   }
0479 }  // namespace
0480 
0481 void EDConsumerBase::modulesWhoseProductsAreConsumed(
0482     std::array<std::vector<ModuleDescription const*>*, NumBranchTypes>& modulesAll,
0483     std::vector<ModuleProcessName>& modulesInPreviousProcesses,
0484     ProductRegistry const& preg,
0485     std::map<std::string, ModuleDescription const*> const& labelsToDesc,
0486     std::string const& processName) const {
0487   std::set<std::string> alreadyFound;
0488 
0489   auto modulesInPreviousProcessesEmplace = [&modulesInPreviousProcesses](std::string_view module,
0490                                                                          std::string_view process) {
0491     auto it = std::lower_bound(
0492         modulesInPreviousProcesses.begin(), modulesInPreviousProcesses.end(), ModuleProcessName(module, process));
0493     modulesInPreviousProcesses.emplace(it, module, process);
0494   };
0495 
0496   auto itKind = m_tokenInfo.begin<kKind>();
0497   auto itLabels = m_tokenInfo.begin<kLabels>();
0498   for (auto itInfo = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); itInfo != itEnd;
0499        ++itInfo, ++itKind, ++itLabels) {
0500     ProductResolverIndexHelper const& helper = *preg.productLookup(itInfo->m_branchType);
0501     std::vector<ModuleDescription const*>& modules = *modulesAll[itInfo->m_branchType];
0502 
0503     const unsigned int labelStart = itLabels->m_startOfModuleLabel;
0504     const char* const consumedModuleLabel = &(m_tokenLabels[labelStart]);
0505     const char* const consumedProductInstance = consumedModuleLabel + itLabels->m_deltaToProductInstance;
0506     const char* const consumedProcessName = consumedModuleLabel + itLabels->m_deltaToProcessName;
0507 
0508     if (not itInfo->m_index.skipCurrentProcess()) {
0509       if (*consumedModuleLabel != '\0') {    // not a consumesMany
0510         if (*consumedProcessName != '\0') {  // process name is specified in consumes call
0511           if (helper.index(
0512                   *itKind, itInfo->m_type, consumedModuleLabel, consumedProductInstance, consumedProcessName) !=
0513               ProductResolverIndexInvalid) {
0514             if (processName == consumedProcessName) {
0515               insertFoundModuleLabel(*itKind,
0516                                      itInfo->m_type,
0517                                      consumedModuleLabel,
0518                                      consumedProductInstance,
0519                                      modules,
0520                                      alreadyFound,
0521                                      labelsToDesc,
0522                                      preg);
0523             } else {
0524               // Product explicitly from different process than the current process, so must refer to an earlier process (unless it ends up "not found")
0525               modulesInPreviousProcessesEmplace(consumedModuleLabel, consumedProcessName);
0526             }
0527           }
0528         } else {  // process name was empty
0529           auto matches = helper.relatedIndexes(*itKind, itInfo->m_type, consumedModuleLabel, consumedProductInstance);
0530           for (unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
0531             if (processName == matches.processName(j)) {
0532               insertFoundModuleLabel(*itKind,
0533                                      itInfo->m_type,
0534                                      consumedModuleLabel,
0535                                      consumedProductInstance,
0536                                      modules,
0537                                      alreadyFound,
0538                                      labelsToDesc,
0539                                      preg);
0540             } else {
0541               // Product did not match to current process, so must refer to an earlier process (unless it ends up "not found")
0542               // Recall that empty process name means "in the latest process" that can change event-by-event
0543               modulesInPreviousProcessesEmplace(consumedModuleLabel, matches.processName(j));
0544             }
0545           }
0546         }
0547         // consumesMany case
0548       } else if (itInfo->m_index.productResolverIndex() == ProductResolverIndexInvalid) {
0549         auto matches = helper.relatedIndexes(*itKind, itInfo->m_type);
0550         for (unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
0551           if (processName == matches.processName(j)) {
0552             insertFoundModuleLabel(*itKind,
0553                                    itInfo->m_type,
0554                                    matches.moduleLabel(j),
0555                                    matches.productInstanceName(j),
0556                                    modules,
0557                                    alreadyFound,
0558                                    labelsToDesc,
0559                                    preg);
0560           } else {
0561             modulesInPreviousProcessesEmplace(matches.moduleLabel(j), matches.processName(j));
0562           }
0563         }
0564       }
0565     } else {
0566       // The skipCurrentProcess means the same as empty process name,
0567       // except the current process is skipped. Therefore need to do
0568       // the same matching as above. There is no consumesMany branch
0569       // in this case.
0570       auto matches = helper.relatedIndexes(*itKind, itInfo->m_type, consumedModuleLabel, consumedProductInstance);
0571       for (unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
0572         if (processName != matches.processName(j)) {
0573           modulesInPreviousProcessesEmplace(matches.moduleLabel(j), matches.processName(j));
0574         }
0575       }
0576     }
0577   }
0578 }
0579 
0580 void EDConsumerBase::convertCurrentProcessAlias(std::string const& processName) {
0581   frozen_ = true;
0582 
0583   if (containsCurrentProcessAlias_) {
0584     containsCurrentProcessAlias_ = false;
0585 
0586     auto newTokenLabels = makeEmptyTokenLabels();
0587 
0588     // first calculate the size of the new vector and reserve memory for it
0589     std::vector<char>::size_type newSize = newTokenLabels.size();
0590     std::string newProcessName;
0591     for (auto iter = m_tokenInfo.begin<kLabels>(), itEnd = m_tokenInfo.end<kLabels>(); iter != itEnd; ++iter) {
0592       newProcessName = &m_tokenLabels[iter->m_startOfModuleLabel + iter->m_deltaToProcessName];
0593       if (newProcessName == InputTag::kCurrentProcess) {
0594         newProcessName = processName;
0595       }
0596       newSize += (iter->m_deltaToProcessName + newProcessName.size() + 1);
0597     }
0598     newTokenLabels.reserve(newSize);
0599 
0600     unsigned int newStartOfModuleLabel = newTokenLabels.size();
0601     for (auto iter = m_tokenInfo.begin<kLabels>(), itEnd = m_tokenInfo.end<kLabels>(); iter != itEnd; ++iter) {
0602       unsigned int startOfModuleLabel = iter->m_startOfModuleLabel;
0603       unsigned short deltaToProcessName = iter->m_deltaToProcessName;
0604 
0605       iter->m_startOfModuleLabel = newStartOfModuleLabel;
0606 
0607       newProcessName = &m_tokenLabels[startOfModuleLabel + deltaToProcessName];
0608       if (newProcessName == InputTag::kCurrentProcess) {
0609         newProcessName = processName;
0610       }
0611 
0612       newStartOfModuleLabel += (deltaToProcessName + newProcessName.size() + 1);
0613 
0614       // Copy in both the module label and instance, they are the same
0615       newTokenLabels.insert(newTokenLabels.end(),
0616                             m_tokenLabels.begin() + startOfModuleLabel,
0617                             m_tokenLabels.begin() + (startOfModuleLabel + deltaToProcessName));
0618 
0619       newTokenLabels.insert(newTokenLabels.end(), newProcessName.begin(), newProcessName.end());
0620       newTokenLabels.push_back('\0');
0621     }
0622     m_tokenLabels = std::move(newTokenLabels);
0623   }
0624 }
0625 
0626 std::vector<ConsumesInfo> EDConsumerBase::consumesInfo() const {
0627   // Use this to eliminate duplicate entries related
0628   // to consumesMany items where only the type was specified
0629   // and the there are multiple matches. In these cases the
0630   // label, instance, and process will be empty.
0631   std::set<edm::TypeID> alreadySeenTypes;
0632 
0633   std::vector<ConsumesInfo> result;
0634   auto itAlways = m_tokenInfo.begin<kAlwaysGets>();
0635   auto itKind = m_tokenInfo.begin<kKind>();
0636   auto itLabels = m_tokenInfo.begin<kLabels>();
0637   for (auto itInfo = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); itInfo != itEnd;
0638        ++itInfo, ++itKind, ++itLabels, ++itAlways) {
0639     const unsigned int labelStart = itLabels->m_startOfModuleLabel;
0640     const char* consumedModuleLabel = &(m_tokenLabels[labelStart]);
0641     const char* consumedInstance = consumedModuleLabel + itLabels->m_deltaToProductInstance;
0642     const char* consumedProcessName = consumedModuleLabel + itLabels->m_deltaToProcessName;
0643 
0644     // consumesMany case
0645     if (*consumedModuleLabel == '\0') {
0646       if (!alreadySeenTypes.insert(itInfo->m_type).second) {
0647         continue;
0648       }
0649     }
0650 
0651     // Just copy the information into the ConsumesInfo data structure
0652     result.emplace_back(itInfo->m_type,
0653                         consumedModuleLabel,
0654                         consumedInstance,
0655                         consumedProcessName,
0656                         itInfo->m_branchType,
0657                         *itKind,
0658                         *itAlways,
0659                         itInfo->m_index.skipCurrentProcess());
0660   }
0661   return result;
0662 }
0663 
0664 const char* EDConsumerBase::labelFor(ESTokenIndex iIndex) const {
0665   return m_esTokenInfo.get<kESLookupInfo>(iIndex.value()).m_key.name().value();
0666 }