Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:12:08

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/ESRecordsToProductResolverIndices.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   m_tokenInfo.shrink_to_fit();
0140 
0141   itemsToGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
0142   if (iPrefetchMayGet) {
0143     itemsMayGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
0144   }
0145 }
0146 
0147 void EDConsumerBase::updateLookup(eventsetup::ESRecordsToProductResolverIndices const& iPI) {
0148   // temporarily unfreeze to allow late EventSetup consumes registration
0149   frozen_ = false;
0150   registerLateConsumes(iPI);
0151   frozen_ = true;
0152 
0153   unsigned int index = 0;
0154   for (auto it = m_esTokenInfo.begin<kESLookupInfo>(); it != m_esTokenInfo.end<kESLookupInfo>(); ++it, ++index) {
0155     auto indexInRecord = iPI.indexInRecord(it->m_record, it->m_key);
0156     if (indexInRecord != eventsetup::ESRecordsToProductResolverIndices::missingResolverIndex()) {
0157       const char* componentName = &(m_tokenLabels[it->m_startOfComponentName]);
0158       if (*componentName) {
0159         auto component = iPI.component(it->m_record, it->m_key);
0160         if (component->label_.empty()) {
0161           if (component->type_ != componentName) {
0162             indexInRecord = eventsetup::ESRecordsToProductResolverIndices::missingResolverIndex();
0163           }
0164         } else if (component->label_ != componentName) {
0165           indexInRecord = eventsetup::ESRecordsToProductResolverIndices::missingResolverIndex();
0166         }
0167       }
0168     }
0169     m_esTokenInfo.get<kESResolverIndex>(index) = indexInRecord;
0170 
0171     int negIndex = -1 * (index + 1);
0172     for (auto& items : esItemsToGetFromTransition_) {
0173       for (auto& itemIndex : items) {
0174         if (itemIndex.value() == negIndex) {
0175           itemIndex = indexInRecord;
0176           esRecordsToGetFromTransition_[&items - &esItemsToGetFromTransition_.front()][&itemIndex - &items.front()] =
0177               iPI.recordIndexFor(it->m_record);
0178           negIndex = 1;
0179           break;
0180         }
0181       }
0182       if (negIndex > 0) {
0183         break;
0184       }
0185     }
0186   }
0187 }
0188 
0189 ESTokenIndex EDConsumerBase::recordESConsumes(Transition iTrans,
0190                                               eventsetup::EventSetupRecordKey const& iRecord,
0191                                               eventsetup::heterocontainer::HCTypeTag const& iDataType,
0192                                               edm::ESInputTag const& iTag) {
0193   if (frozen_) {
0194     throwESConsumesCallAfterFrozen(iRecord, iDataType, iTag);
0195   }
0196 
0197   //m_tokenLabels first entry is a null. Since most ES data requests have
0198   // empty labels we will assume we can reuse the first entry
0199   unsigned int startOfComponentName = 0;
0200   if (not iTag.module().empty()) {
0201     startOfComponentName = m_tokenLabels.size();
0202 
0203     m_tokenLabels.reserve(m_tokenLabels.size() + iTag.module().size() + 1);
0204     {
0205       const std::string& m = iTag.module();
0206       m_tokenLabels.insert(m_tokenLabels.end(), m.begin(), m.end());
0207       m_tokenLabels.push_back('\0');
0208     }
0209   }
0210 
0211   auto index = static_cast<ESResolverIndex::Value_t>(m_esTokenInfo.size());
0212   m_esTokenInfo.emplace_back(
0213       ESTokenLookupInfo{iRecord, eventsetup::DataKey{iDataType, iTag.data().c_str()}, startOfComponentName},
0214       ESResolverIndex{-1});
0215   if (iTrans >= edm::Transition::NumberOfEventSetupTransitions) {
0216     throwESConsumesInProcessBlock();
0217   }
0218   auto indexForToken = esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)].size();
0219   esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)].emplace_back(-1 * (index + 1));
0220   esRecordsToGetFromTransition_[static_cast<unsigned int>(iTrans)].emplace_back();
0221   return ESTokenIndex{static_cast<ESTokenIndex::Value_t>(indexForToken)};
0222 }
0223 
0224 //
0225 // const member functions
0226 //
0227 ProductResolverIndexAndSkipBit EDConsumerBase::indexFrom(EDGetToken iToken,
0228                                                          BranchType iBranch,
0229                                                          TypeID const& iType) const {
0230   if (UNLIKELY(iToken.index() >= m_tokenInfo.size())) {
0231     throwBadToken(iType, iToken);
0232   }
0233   const auto& info = m_tokenInfo.get<kLookupInfo>(iToken.index());
0234   if (LIKELY(iBranch == info.m_branchType)) {
0235     if (LIKELY(iType == info.m_type)) {
0236       return info.m_index;
0237     } else {
0238       throwTypeMismatch(iType, iToken);
0239     }
0240   } else {
0241     throwBranchMismatch(iBranch, iToken);
0242   }
0243   return ProductResolverIndexAndSkipBit(edm::ProductResolverIndexInvalid, false);
0244 }
0245 
0246 ProductResolverIndexAndSkipBit EDConsumerBase::uncheckedIndexFrom(EDGetToken iToken) const {
0247   return m_tokenInfo.get<kLookupInfo>(iToken.index()).m_index;
0248 }
0249 
0250 void EDConsumerBase::itemsToGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const {
0251   //how many are we adding?
0252   unsigned int count = 0;
0253   {
0254     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0255     for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0256          ++it, ++itAlwaysGet) {
0257       if (iBranch == it->m_branchType) {
0258         if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0259           if (*itAlwaysGet) {
0260             ++count;
0261           }
0262         }
0263       }
0264     }
0265   }
0266   oIndices.reserve(oIndices.size() + count);
0267   {
0268     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0269     for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0270          ++it, ++itAlwaysGet) {
0271       if (iBranch == it->m_branchType) {
0272         if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0273           if (*itAlwaysGet) {
0274             oIndices.push_back(it->m_index);
0275           }
0276         }
0277       }
0278     }
0279   }
0280 }
0281 
0282 void EDConsumerBase::itemsMayGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const {
0283   //how many are we adding?
0284   unsigned int count = 0;
0285   {
0286     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0287     for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0288          ++it, ++itAlwaysGet) {
0289       if (iBranch == it->m_branchType) {
0290         if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0291           if (not *itAlwaysGet) {
0292             ++count;
0293           }
0294         }
0295       }
0296     }
0297   }
0298   oIndices.reserve(oIndices.size() + count);
0299   {
0300     auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0301     for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0302          ++it, ++itAlwaysGet) {
0303       if (iBranch == it->m_branchType) {
0304         if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0305           if (not *itAlwaysGet) {
0306             oIndices.push_back(it->m_index);
0307           }
0308         }
0309       }
0310     }
0311   }
0312 }
0313 
0314 void EDConsumerBase::labelsForToken(EDGetToken iToken, Labels& oLabels) const {
0315   unsigned int index = iToken.index();
0316   auto labels = m_tokenInfo.get<kLabels>(index);
0317   unsigned int start = labels.m_startOfModuleLabel;
0318   oLabels.module = &(m_tokenLabels[start]);
0319   oLabels.productInstance = oLabels.module + labels.m_deltaToProductInstance;
0320   oLabels.process = oLabels.module + labels.m_deltaToProcessName;
0321 }
0322 
0323 bool EDConsumerBase::registeredToConsume(ProductResolverIndex iIndex,
0324                                          bool skipCurrentProcess,
0325                                          BranchType iBranch) const {
0326   for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd; ++it) {
0327     if (it->m_index.productResolverIndex() == iIndex and it->m_index.skipCurrentProcess() == skipCurrentProcess and
0328         it->m_branchType == iBranch) {
0329       return true;
0330     }
0331   }
0332   return false;
0333 }
0334 
0335 void EDConsumerBase::throwTypeMismatch(edm::TypeID const& iType, EDGetToken iToken) const {
0336   throw cms::Exception("TypeMismatch") << "A get using a EDGetToken used the C++ type '" << iType.className()
0337                                        << "' but the consumes call was for type '"
0338                                        << m_tokenInfo.get<kLookupInfo>(iToken.index()).m_type.className()
0339                                        << "'.\n Please modify either the consumes or get call so the types match.";
0340 }
0341 void EDConsumerBase::throwBranchMismatch(BranchType iBranch, EDGetToken iToken) const {
0342   throw cms::Exception("BranchTypeMismatch")
0343       << "A get using a EDGetToken was done in " << BranchTypeToString(iBranch) << " but the consumes call was for "
0344       << BranchTypeToString(m_tokenInfo.get<kLookupInfo>(iToken.index()).m_branchType)
0345       << ".\n Please modify the consumes call to use the correct branch type.";
0346 }
0347 
0348 void EDConsumerBase::throwBadToken(edm::TypeID const& iType, EDGetToken iToken) const {
0349   if (iToken.isUninitialized()) {
0350     throw cms::Exception("BadToken") << "A get using a EDGetToken with the C++ type '" << iType.className()
0351                                      << "' was made using an uninitialized token.\n Please check that the variable is "
0352                                         "being initialized from a 'consumes' call.";
0353   }
0354   throw cms::Exception("BadToken")
0355       << "A get using a EDGetToken with the C++ type '" << iType.className() << "' was made using a token with a value "
0356       << iToken.index()
0357       << " which is beyond the range used by this module.\n Please check that the variable is being initialized from a "
0358          "'consumes' call from this module.\n You can not share EDGetToken values between modules.";
0359 }
0360 
0361 void EDConsumerBase::throwConsumesCallAfterFrozen(TypeToGet const& typeToGet, InputTag const& inputTag) const {
0362   throw cms::Exception("LogicError") << "A module declared it consumes a product after its constructor.\n"
0363                                      << "This must be done in the contructor\n"
0364                                      << "The product type was: " << typeToGet.type() << "\n"
0365                                      << "and " << inputTag << "\n";
0366 }
0367 
0368 void EDConsumerBase::throwESConsumesCallAfterFrozen(eventsetup::EventSetupRecordKey const& iRecord,
0369                                                     eventsetup::heterocontainer::HCTypeTag const& iDataType,
0370                                                     edm::ESInputTag const& iTag) const {
0371   throw cms::Exception("LogicError") << "A module declared it consumes an EventSetup product after its constructor.\n"
0372                                      << "This must be done in the contructor\n"
0373                                      << "The product type was: " << iDataType.name() << " in record "
0374                                      << iRecord.type().name() << "\n"
0375                                      << "and ESInputTag was " << iTag << "\n";
0376 }
0377 
0378 void EDConsumerBase::throwESConsumesInProcessBlock() const {
0379   throw cms::Exception("LogicError")
0380       << "A module declared it consumes an EventSetup product during a ProcessBlock transition.\n"
0381       << "EventSetup products can only be consumed in Event, Lumi, or Run transitions.\n";
0382 }
0383 
0384 void EDConsumerBase::doSelectInputProcessBlocks(ProductRegistry const&, ProcessBlockHelperBase const&) {}
0385 
0386 namespace {
0387   struct CharStarComp {
0388     bool operator()(const char* iLHS, const char* iRHS) const { return strcmp(iLHS, iRHS) < 0; }
0389   };
0390 }  // namespace
0391 
0392 namespace {
0393   void insertFoundModuleLabel(edm::KindOfType consumedTypeKind,
0394                               edm::TypeID consumedType,
0395                               const char* consumedModuleLabel,
0396                               const char* consumedProductInstance,
0397                               std::vector<ModuleDescription const*>& modules,
0398                               std::set<std::string>& alreadyFound,
0399                               std::map<std::string, ModuleDescription const*> const& labelsToDesc,
0400                               ProductRegistry const& preg) {
0401     // Convert from label string to module description, eliminate duplicates,
0402     // then insert into the vector of modules
0403     if (auto it = labelsToDesc.find(consumedModuleLabel); it != labelsToDesc.end()) {
0404       if (alreadyFound.insert(consumedModuleLabel).second) {
0405         modules.push_back(it->second);
0406       }
0407       return;
0408     }
0409     // Deal with EDAlias's by converting to the original module label first
0410     if (auto aliasToModuleLabels =
0411             preg.aliasToModules(consumedTypeKind, consumedType, consumedModuleLabel, consumedProductInstance);
0412         not aliasToModuleLabels.empty()) {
0413       bool foundInLabelsToDesc = false;
0414       for (auto const& label : aliasToModuleLabels) {
0415         if (auto it = labelsToDesc.find(label); it != labelsToDesc.end()) {
0416           if (alreadyFound.insert(label).second) {
0417             modules.push_back(it->second);
0418           }
0419           foundInLabelsToDesc = true;
0420         } else {
0421           if (label == "source") {
0422             foundInLabelsToDesc = true;
0423           }
0424         }
0425       }
0426       if (foundInLabelsToDesc) {
0427         return;
0428       }
0429     }
0430     // Ignore the source products, we are only interested in module products.
0431     // As far as I know, it should never be anything else so throw if something
0432     // unknown gets passed in.
0433     if (std::string_view(consumedModuleLabel) != "source") {
0434       throw cms::Exception("EDConsumerBase", "insertFoundModuleLabel")
0435           << "Couldn't find ModuleDescription for the consumed product type: '" << consumedType.className()
0436           << "' module label: '" << consumedModuleLabel << "' product instance name: '" << consumedProductInstance
0437           << "'";
0438     }
0439   }
0440 }  // namespace
0441 
0442 void EDConsumerBase::modulesWhoseProductsAreConsumed(
0443     std::array<std::vector<ModuleDescription const*>*, NumBranchTypes>& modulesAll,
0444     std::vector<ModuleProcessName>& modulesInPreviousProcesses,
0445     ProductRegistry const& preg,
0446     std::map<std::string, ModuleDescription const*> const& labelsToDesc,
0447     std::string const& processName) const {
0448   std::set<std::string> alreadyFound;
0449 
0450   auto modulesInPreviousProcessesEmplace = [&modulesInPreviousProcesses](std::string_view module,
0451                                                                          std::string_view process) {
0452     auto it = std::lower_bound(
0453         modulesInPreviousProcesses.begin(), modulesInPreviousProcesses.end(), ModuleProcessName(module, process));
0454     modulesInPreviousProcesses.emplace(it, module, process);
0455   };
0456 
0457   auto itKind = m_tokenInfo.begin<kKind>();
0458   auto itLabels = m_tokenInfo.begin<kLabels>();
0459   for (auto itInfo = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); itInfo != itEnd;
0460        ++itInfo, ++itKind, ++itLabels) {
0461     ProductResolverIndexHelper const& helper = *preg.productLookup(itInfo->m_branchType);
0462     std::vector<ModuleDescription const*>& modules = *modulesAll[itInfo->m_branchType];
0463 
0464     const unsigned int labelStart = itLabels->m_startOfModuleLabel;
0465     const char* const consumedModuleLabel = &(m_tokenLabels[labelStart]);
0466     const char* const consumedProductInstance = consumedModuleLabel + itLabels->m_deltaToProductInstance;
0467     const char* const consumedProcessName = consumedModuleLabel + itLabels->m_deltaToProcessName;
0468 
0469     if (not itInfo->m_index.skipCurrentProcess()) {
0470       assert(*consumedModuleLabel != '\0');  // consumesMany used to create empty labels before we removed consumesMany
0471       if (*consumedProcessName != '\0') {    // process name is specified in consumes call
0472         if (helper.index(*itKind, itInfo->m_type, consumedModuleLabel, consumedProductInstance, consumedProcessName) !=
0473             ProductResolverIndexInvalid) {
0474           if (processName == consumedProcessName) {
0475             insertFoundModuleLabel(*itKind,
0476                                    itInfo->m_type,
0477                                    consumedModuleLabel,
0478                                    consumedProductInstance,
0479                                    modules,
0480                                    alreadyFound,
0481                                    labelsToDesc,
0482                                    preg);
0483           } else {
0484             // Product explicitly from different process than the current process, so must refer to an earlier process (unless it ends up "not found")
0485             modulesInPreviousProcessesEmplace(consumedModuleLabel, consumedProcessName);
0486           }
0487         }
0488       } else {  // process name was empty
0489         auto matches = helper.relatedIndexes(*itKind, itInfo->m_type, consumedModuleLabel, consumedProductInstance);
0490         for (unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
0491           if (processName == matches.processName(j)) {
0492             insertFoundModuleLabel(*itKind,
0493                                    itInfo->m_type,
0494                                    consumedModuleLabel,
0495                                    consumedProductInstance,
0496                                    modules,
0497                                    alreadyFound,
0498                                    labelsToDesc,
0499                                    preg);
0500           } else {
0501             // Product did not match to current process, so must refer to an earlier process (unless it ends up "not found")
0502             // Recall that empty process name means "in the latest process" that can change event-by-event
0503             modulesInPreviousProcessesEmplace(consumedModuleLabel, matches.processName(j));
0504           }
0505         }
0506       }
0507     } else {
0508       // The skipCurrentProcess means the same as empty process name,
0509       // except the current process is skipped. Therefore need to do
0510       // the same matching as above.
0511       auto matches = helper.relatedIndexes(*itKind, itInfo->m_type, consumedModuleLabel, consumedProductInstance);
0512       for (unsigned int j = 0; j < matches.numberOfMatches(); ++j) {
0513         if (processName != matches.processName(j)) {
0514           modulesInPreviousProcessesEmplace(matches.moduleLabel(j), matches.processName(j));
0515         }
0516       }
0517     }
0518   }
0519 }
0520 
0521 void EDConsumerBase::convertCurrentProcessAlias(std::string const& processName) {
0522   frozen_ = true;
0523 
0524   if (containsCurrentProcessAlias_) {
0525     containsCurrentProcessAlias_ = false;
0526 
0527     auto newTokenLabels = makeEmptyTokenLabels();
0528 
0529     // first calculate the size of the new vector and reserve memory for it
0530     std::vector<char>::size_type newSize = newTokenLabels.size();
0531     std::string newProcessName;
0532     for (auto iter = m_tokenInfo.begin<kLabels>(), itEnd = m_tokenInfo.end<kLabels>(); iter != itEnd; ++iter) {
0533       newProcessName = &m_tokenLabels[iter->m_startOfModuleLabel + iter->m_deltaToProcessName];
0534       if (newProcessName == InputTag::kCurrentProcess) {
0535         newProcessName = processName;
0536       }
0537       newSize += (iter->m_deltaToProcessName + newProcessName.size() + 1);
0538     }
0539     newTokenLabels.reserve(newSize);
0540 
0541     unsigned int newStartOfModuleLabel = newTokenLabels.size();
0542     for (auto iter = m_tokenInfo.begin<kLabels>(), itEnd = m_tokenInfo.end<kLabels>(); iter != itEnd; ++iter) {
0543       unsigned int startOfModuleLabel = iter->m_startOfModuleLabel;
0544       unsigned short deltaToProcessName = iter->m_deltaToProcessName;
0545 
0546       iter->m_startOfModuleLabel = newStartOfModuleLabel;
0547 
0548       newProcessName = &m_tokenLabels[startOfModuleLabel + deltaToProcessName];
0549       if (newProcessName == InputTag::kCurrentProcess) {
0550         newProcessName = processName;
0551       }
0552 
0553       newStartOfModuleLabel += (deltaToProcessName + newProcessName.size() + 1);
0554 
0555       // Copy in both the module label and instance, they are the same
0556       newTokenLabels.insert(newTokenLabels.end(),
0557                             m_tokenLabels.begin() + startOfModuleLabel,
0558                             m_tokenLabels.begin() + (startOfModuleLabel + deltaToProcessName));
0559 
0560       newTokenLabels.insert(newTokenLabels.end(), newProcessName.begin(), newProcessName.end());
0561       newTokenLabels.push_back('\0');
0562     }
0563     m_tokenLabels = std::move(newTokenLabels);
0564   }
0565 }
0566 
0567 std::vector<ConsumesInfo> EDConsumerBase::consumesInfo() const {
0568   std::vector<ConsumesInfo> result;
0569   auto itAlways = m_tokenInfo.begin<kAlwaysGets>();
0570   auto itKind = m_tokenInfo.begin<kKind>();
0571   auto itLabels = m_tokenInfo.begin<kLabels>();
0572   for (auto itInfo = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); itInfo != itEnd;
0573        ++itInfo, ++itKind, ++itLabels, ++itAlways) {
0574     const unsigned int labelStart = itLabels->m_startOfModuleLabel;
0575     const char* consumedModuleLabel = &(m_tokenLabels[labelStart]);
0576     const char* consumedInstance = consumedModuleLabel + itLabels->m_deltaToProductInstance;
0577     const char* consumedProcessName = consumedModuleLabel + itLabels->m_deltaToProcessName;
0578 
0579     assert(*consumedModuleLabel != '\0');
0580 
0581     // Just copy the information into the ConsumesInfo data structure
0582     result.emplace_back(itInfo->m_type,
0583                         consumedModuleLabel,
0584                         consumedInstance,
0585                         consumedProcessName,
0586                         itInfo->m_branchType,
0587                         *itKind,
0588                         *itAlways,
0589                         itInfo->m_index.skipCurrentProcess());
0590   }
0591   return result;
0592 }
0593 
0594 const char* EDConsumerBase::labelFor(ESTokenIndex iIndex) const {
0595   return m_esTokenInfo.get<kESLookupInfo>(iIndex.value()).m_key.name().value();
0596 }