File indexing completed on 2025-04-30 22:24:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <algorithm>
0015 #include <cstring>
0016 #include <set>
0017 #include <string_view>
0018
0019
0020 #include "DataFormats/Provenance/interface/BranchType.h"
0021 #include "FWCore/Framework/interface/EDConsumerBase.h"
0022 #include "FWCore/Framework/interface/ConsumesCollector.h"
0023 #include "FWCore/Framework/interface/ESRecordsToProductResolverIndices.h"
0024 #include "FWCore/Framework/interface/ComponentDescription.h"
0025 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0026 #include "FWCore/ServiceRegistry/interface/ModuleConsumesInfo.h"
0027 #include "FWCore/Utilities/interface/Likely.h"
0028 #include "FWCore/Utilities/interface/Exception.h"
0029 #include "DataFormats/Provenance/interface/ProductResolverIndexHelper.h"
0030 #include "DataFormats/Provenance/interface/ProductRegistry.h"
0031
0032 using namespace edm;
0033
0034 namespace {
0035 std::vector<char> makeEmptyTokenLabels() { return std::vector<char>{'\0'}; }
0036 }
0037
0038 EDConsumerBase::EDConsumerBase()
0039 : m_tokenLabels{makeEmptyTokenLabels()},
0040 esDataThatCanBeDeletedEarly_(std::make_unique<ESDataThatCanBeDeletedEarly>()),
0041 frozen_(false),
0042 containsCurrentProcessAlias_(false) {}
0043
0044 EDConsumerBase::~EDConsumerBase() noexcept(false) {}
0045
0046
0047
0048
0049 ConsumesCollector EDConsumerBase::consumesCollector() {
0050 ConsumesCollector c{this};
0051 return c;
0052 }
0053
0054 static const edm::InputTag kWasEmpty("@EmptyLabel@");
0055
0056 edm::InputTag const& EDConsumerBase::checkIfEmpty(edm::InputTag const& iTag) {
0057 if (iTag.label().empty()) {
0058 return kWasEmpty;
0059 }
0060 return iTag;
0061 }
0062
0063 unsigned int EDConsumerBase::recordConsumes(BranchType iBranch,
0064 TypeToGet const& iType,
0065 edm::InputTag const& iTag,
0066 bool iAlwaysGets) {
0067 if (frozen_) {
0068 throwConsumesCallAfterFrozen(iType, iTag);
0069 }
0070
0071 unsigned int index = m_tokenInfo.size();
0072
0073 bool skipCurrentProcess = iTag.willSkipCurrentProcess();
0074
0075 const size_t labelSize = iTag.label().size();
0076 const size_t productInstanceSize = iTag.instance().size();
0077 unsigned int labelStart = m_tokenLabels.size();
0078 unsigned short delta1 = labelSize + 1;
0079 unsigned short delta2 = labelSize + 2 + productInstanceSize;
0080 m_tokenInfo.emplace_back(TokenLookupInfo{iType.type(), ProductResolverIndexInvalid, skipCurrentProcess, iBranch},
0081 iAlwaysGets,
0082 LabelPlacement{labelStart, delta1, delta2},
0083 iType.kind());
0084
0085 const size_t additionalSize = skipCurrentProcess ? labelSize + productInstanceSize + 3
0086 : labelSize + productInstanceSize + iTag.process().size() + 3;
0087
0088 m_tokenLabels.reserve(m_tokenLabels.size() + additionalSize);
0089 {
0090 const std::string& m = iTag.label();
0091 m_tokenLabels.insert(m_tokenLabels.end(), m.begin(), m.end());
0092 m_tokenLabels.push_back('\0');
0093 }
0094 {
0095 const std::string& m = iTag.instance();
0096 m_tokenLabels.insert(m_tokenLabels.end(), m.begin(), m.end());
0097 m_tokenLabels.push_back('\0');
0098 }
0099 {
0100 const std::string& m = iTag.process();
0101 if (m == InputTag::kCurrentProcess) {
0102 containsCurrentProcessAlias_ = true;
0103 }
0104 if (!skipCurrentProcess) {
0105 m_tokenLabels.insert(m_tokenLabels.end(), m.begin(), m.end());
0106 m_tokenLabels.push_back('\0');
0107 } else {
0108 m_tokenLabels.push_back('\0');
0109 }
0110 }
0111 return index;
0112 }
0113
0114 void EDConsumerBase::extendUpdateLookup(BranchType, ProductResolverIndexHelper const&) {}
0115
0116 void EDConsumerBase::updateLookup(BranchType iBranchType,
0117 ProductResolverIndexHelper const& iHelper,
0118 bool iPrefetchMayGet) {
0119 frozen_ = true;
0120 assert(!containsCurrentProcessAlias_);
0121 extendUpdateLookup(iBranchType, iHelper);
0122 {
0123 auto itKind = m_tokenInfo.begin<kKind>();
0124 auto itLabels = m_tokenInfo.begin<kLabels>();
0125 for (auto itInfo = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); itInfo != itEnd;
0126 ++itInfo, ++itKind, ++itLabels) {
0127 if (itInfo->m_branchType == iBranchType) {
0128 const unsigned int labelStart = itLabels->m_startOfModuleLabel;
0129 const char* moduleLabel = &(m_tokenLabels[labelStart]);
0130 itInfo->m_index = ProductResolverIndexAndSkipBit(iHelper.index(*itKind,
0131 itInfo->m_type,
0132 moduleLabel,
0133 moduleLabel + itLabels->m_deltaToProductInstance,
0134 moduleLabel + itLabels->m_deltaToProcessName),
0135 itInfo->m_index.skipCurrentProcess());
0136 }
0137 }
0138 }
0139
0140 m_tokenInfo.shrink_to_fit();
0141
0142 itemsToGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
0143 if (iPrefetchMayGet) {
0144 itemsMayGet(iBranchType, itemsToGetFromBranch_[iBranchType]);
0145 }
0146 }
0147
0148 void EDConsumerBase::updateLookup(eventsetup::ESRecordsToProductResolverIndices const& iPI) {
0149
0150 frozen_ = false;
0151 registerLateConsumes(iPI);
0152 frozen_ = true;
0153
0154 unsigned int index = 0;
0155 for (auto it = esTokenLookupInfoContainer().begin<kESLookupInfo>();
0156 it != esTokenLookupInfoContainer().end<kESLookupInfo>();
0157 ++it, ++index) {
0158 auto indexInRecord = iPI.indexInRecord(it->m_record, it->m_key);
0159 if (indexInRecord != ESResolverIndex::noResolverConfigured()) {
0160 const char* componentName = &(m_tokenLabels[it->m_startOfComponentName]);
0161 if (*componentName) {
0162 auto component = iPI.component(it->m_record, it->m_key);
0163 if (component->label_.empty()) {
0164 if (component->type_ != componentName) {
0165 indexInRecord = ESResolverIndex::moduleLabelDoesNotMatch();
0166 }
0167 } else if (component->label_ != componentName) {
0168 indexInRecord = ESResolverIndex::moduleLabelDoesNotMatch();
0169 }
0170 }
0171 }
0172 esDataThatCanBeDeletedEarly_->esTokenLookupInfoContainer_.get<kESResolverIndex>(index) = indexInRecord;
0173
0174 int negIndex = -1 * (index + 1);
0175 for (auto& items : esItemsToGetFromTransition_) {
0176 for (auto& itemIndex : items) {
0177 if (itemIndex.value() == negIndex) {
0178 itemIndex = indexInRecord;
0179 ESResolverIndexContainer::size_type transitionIndex = &items - &esItemsToGetFromTransition_.front();
0180 std::vector<ESResolverIndex>::size_type indexToItemInTransition = &itemIndex - &items.front();
0181 esRecordsToGetFromTransition_[transitionIndex][indexToItemInTransition] = iPI.recordIndexFor(it->m_record);
0182 esDataThatCanBeDeletedEarly_->consumesIndexConverter_.emplace_back(transitionIndex, indexToItemInTransition);
0183 negIndex = 1;
0184 break;
0185 }
0186 }
0187 if (negIndex > 0) {
0188 break;
0189 }
0190 }
0191 }
0192 }
0193
0194 void EDConsumerBase::releaseMemoryPostLookupSignal() { esDataThatCanBeDeletedEarly_.reset(); }
0195
0196 std::tuple<ESTokenIndex, char const*> EDConsumerBase::recordESConsumes(
0197 Transition iTrans,
0198 eventsetup::EventSetupRecordKey const& iRecord,
0199 eventsetup::heterocontainer::HCTypeTag const& iDataType,
0200 edm::ESInputTag const& iTag) {
0201 if (frozen_) {
0202 throwESConsumesCallAfterFrozen(iRecord, iDataType, iTag);
0203 }
0204
0205
0206
0207 unsigned int startOfComponentName = 0;
0208 if (not iTag.module().empty()) {
0209 startOfComponentName = m_tokenLabels.size();
0210
0211 m_tokenLabels.reserve(m_tokenLabels.size() + iTag.module().size() + 1);
0212 {
0213 const std::string& m = iTag.module();
0214 m_tokenLabels.insert(m_tokenLabels.end(), m.begin(), m.end());
0215 m_tokenLabels.push_back('\0');
0216 }
0217 }
0218
0219 auto index = static_cast<ESResolverIndex::Value_t>(esTokenLookupInfoContainer().size());
0220 esDataThatCanBeDeletedEarly_->esTokenLookupInfoContainer_.emplace_back(
0221 ESTokenLookupInfo{iRecord, eventsetup::DataKey{iDataType, iTag.data().c_str()}, startOfComponentName},
0222 ESResolverIndex{-1});
0223 if (iTrans >= edm::Transition::NumberOfEventSetupTransitions) {
0224 throwESConsumesInProcessBlock();
0225 }
0226 auto indexForToken = esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)].size();
0227 esItemsToGetFromTransition_[static_cast<unsigned int>(iTrans)].emplace_back(-1 * (index + 1));
0228 esRecordsToGetFromTransition_[static_cast<unsigned int>(iTrans)].emplace_back();
0229 return {ESTokenIndex{static_cast<ESTokenIndex::Value_t>(indexForToken)},
0230 esTokenLookupInfoContainer().get<kESLookupInfo>(index).m_key.name().value()};
0231 }
0232
0233
0234
0235
0236 ProductResolverIndexAndSkipBit EDConsumerBase::indexFrom(EDGetToken iToken,
0237 BranchType iBranch,
0238 TypeID const& iType) const {
0239 if (UNLIKELY(iToken.index() >= m_tokenInfo.size())) {
0240 throwBadToken(iType, iToken);
0241 }
0242 const auto& info = m_tokenInfo.get<kLookupInfo>(iToken.index());
0243 if (LIKELY(iBranch == info.m_branchType)) {
0244 if (LIKELY(iType == info.m_type)) {
0245 return info.m_index;
0246 } else {
0247 throwTypeMismatch(iType, iToken);
0248 }
0249 } else {
0250 throwBranchMismatch(iBranch, iToken);
0251 }
0252 return ProductResolverIndexAndSkipBit(edm::ProductResolverIndexInvalid, false);
0253 }
0254
0255 ProductResolverIndexAndSkipBit EDConsumerBase::uncheckedIndexFrom(EDGetToken iToken) const {
0256 return m_tokenInfo.get<kLookupInfo>(iToken.index()).m_index;
0257 }
0258
0259 void EDConsumerBase::itemsToGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const {
0260
0261 unsigned int count = 0;
0262 {
0263 auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0264 for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0265 ++it, ++itAlwaysGet) {
0266 if (iBranch == it->m_branchType) {
0267 if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0268 if (*itAlwaysGet) {
0269 ++count;
0270 }
0271 }
0272 }
0273 }
0274 }
0275 oIndices.reserve(oIndices.size() + count);
0276 {
0277 auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0278 for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0279 ++it, ++itAlwaysGet) {
0280 if (iBranch == it->m_branchType) {
0281 if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0282 if (*itAlwaysGet) {
0283 oIndices.push_back(it->m_index);
0284 }
0285 }
0286 }
0287 }
0288 }
0289 }
0290
0291 void EDConsumerBase::itemsMayGet(BranchType iBranch, std::vector<ProductResolverIndexAndSkipBit>& oIndices) const {
0292
0293 unsigned int count = 0;
0294 {
0295 auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0296 for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0297 ++it, ++itAlwaysGet) {
0298 if (iBranch == it->m_branchType) {
0299 if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0300 if (not *itAlwaysGet) {
0301 ++count;
0302 }
0303 }
0304 }
0305 }
0306 }
0307 oIndices.reserve(oIndices.size() + count);
0308 {
0309 auto itAlwaysGet = m_tokenInfo.begin<kAlwaysGets>();
0310 for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd;
0311 ++it, ++itAlwaysGet) {
0312 if (iBranch == it->m_branchType) {
0313 if (it->m_index.productResolverIndex() != ProductResolverIndexInvalid) {
0314 if (not *itAlwaysGet) {
0315 oIndices.push_back(it->m_index);
0316 }
0317 }
0318 }
0319 }
0320 }
0321 }
0322
0323 void EDConsumerBase::labelsForToken(EDGetToken iToken, Labels& oLabels) const {
0324 unsigned int index = iToken.index();
0325 auto labels = m_tokenInfo.get<kLabels>(index);
0326 unsigned int start = labels.m_startOfModuleLabel;
0327 oLabels.module = &(m_tokenLabels[start]);
0328 oLabels.productInstance = oLabels.module + labels.m_deltaToProductInstance;
0329 oLabels.process = oLabels.module + labels.m_deltaToProcessName;
0330 }
0331
0332 bool EDConsumerBase::registeredToConsume(ProductResolverIndex iIndex,
0333 bool skipCurrentProcess,
0334 BranchType iBranch) const {
0335 for (auto it = m_tokenInfo.begin<kLookupInfo>(), itEnd = m_tokenInfo.end<kLookupInfo>(); it != itEnd; ++it) {
0336 if (it->m_index.productResolverIndex() == iIndex and it->m_index.skipCurrentProcess() == skipCurrentProcess and
0337 it->m_branchType == iBranch) {
0338 return true;
0339 }
0340 }
0341 return false;
0342 }
0343
0344 void EDConsumerBase::throwTypeMismatch(edm::TypeID const& iType, EDGetToken iToken) const {
0345 throw cms::Exception("TypeMismatch") << "A get using a EDGetToken used the C++ type '" << iType.className()
0346 << "' but the consumes call was for type '"
0347 << m_tokenInfo.get<kLookupInfo>(iToken.index()).m_type.className()
0348 << "'.\n Please modify either the consumes or get call so the types match.";
0349 }
0350 void EDConsumerBase::throwBranchMismatch(BranchType iBranch, EDGetToken iToken) const {
0351 throw cms::Exception("BranchTypeMismatch")
0352 << "A get using a EDGetToken was done in " << BranchTypeToString(iBranch) << " but the consumes call was for "
0353 << BranchTypeToString(m_tokenInfo.get<kLookupInfo>(iToken.index()).m_branchType)
0354 << ".\n Please modify the consumes call to use the correct branch type.";
0355 }
0356
0357 void EDConsumerBase::throwBadToken(edm::TypeID const& iType, EDGetToken iToken) const {
0358 if (iToken.isUninitialized()) {
0359 throw cms::Exception("BadToken") << "A get using a EDGetToken with the C++ type '" << iType.className()
0360 << "' was made using an uninitialized token.\n Please check that the variable is "
0361 "being initialized from a 'consumes' call.";
0362 }
0363 throw cms::Exception("BadToken")
0364 << "A get using a EDGetToken with the C++ type '" << iType.className() << "' was made using a token with a value "
0365 << iToken.index()
0366 << " which is beyond the range used by this module.\n Please check that the variable is being initialized from a "
0367 "'consumes' call from this module.\n You can not share EDGetToken values between modules.";
0368 }
0369
0370 void EDConsumerBase::throwConsumesCallAfterFrozen(TypeToGet const& typeToGet, InputTag const& inputTag) const {
0371 throw cms::Exception("LogicError") << "A module declared it consumes a product after its constructor.\n"
0372 << "This must be done in the contructor\n"
0373 << "The product type was: " << typeToGet.type() << "\n"
0374 << "and " << inputTag << "\n";
0375 }
0376
0377 void EDConsumerBase::throwESConsumesCallAfterFrozen(eventsetup::EventSetupRecordKey const& iRecord,
0378 eventsetup::heterocontainer::HCTypeTag const& iDataType,
0379 edm::ESInputTag const& iTag) const {
0380 throw cms::Exception("LogicError") << "A module declared it consumes an EventSetup product after its constructor.\n"
0381 << "This must be done in the contructor\n"
0382 << "The product type was: " << iDataType.name() << " in record "
0383 << iRecord.type().name() << "\n"
0384 << "and ESInputTag was " << iTag << "\n";
0385 }
0386
0387 void EDConsumerBase::throwESConsumesInProcessBlock() const {
0388 throw cms::Exception("LogicError")
0389 << "A module declared it consumes an EventSetup product during a ProcessBlock transition.\n"
0390 << "EventSetup products can only be consumed in Event, Lumi, or Run transitions.\n";
0391 }
0392
0393 void EDConsumerBase::doSelectInputProcessBlocks(ProductRegistry const&, ProcessBlockHelperBase const&) {}
0394
0395 void EDConsumerBase::convertCurrentProcessAlias(std::string const& processName) {
0396 frozen_ = true;
0397
0398 if (containsCurrentProcessAlias_) {
0399 containsCurrentProcessAlias_ = false;
0400
0401 auto newTokenLabels = makeEmptyTokenLabels();
0402
0403
0404 std::vector<char>::size_type newSize = newTokenLabels.size();
0405 std::string newProcessName;
0406 for (auto iter = m_tokenInfo.begin<kLabels>(), itEnd = m_tokenInfo.end<kLabels>(); iter != itEnd; ++iter) {
0407 newProcessName = &m_tokenLabels[iter->m_startOfModuleLabel + iter->m_deltaToProcessName];
0408 if (newProcessName == InputTag::kCurrentProcess) {
0409 newProcessName = processName;
0410 }
0411 newSize += (iter->m_deltaToProcessName + newProcessName.size() + 1);
0412 }
0413 newTokenLabels.reserve(newSize);
0414
0415 unsigned int newStartOfModuleLabel = newTokenLabels.size();
0416 for (auto iter = m_tokenInfo.begin<kLabels>(), itEnd = m_tokenInfo.end<kLabels>(); iter != itEnd; ++iter) {
0417 unsigned int startOfModuleLabel = iter->m_startOfModuleLabel;
0418 unsigned short deltaToProcessName = iter->m_deltaToProcessName;
0419
0420 iter->m_startOfModuleLabel = newStartOfModuleLabel;
0421
0422 newProcessName = &m_tokenLabels[startOfModuleLabel + deltaToProcessName];
0423 if (newProcessName == InputTag::kCurrentProcess) {
0424 newProcessName = processName;
0425 }
0426
0427 newStartOfModuleLabel += (deltaToProcessName + newProcessName.size() + 1);
0428
0429
0430 newTokenLabels.insert(newTokenLabels.end(),
0431 m_tokenLabels.begin() + startOfModuleLabel,
0432 m_tokenLabels.begin() + (startOfModuleLabel + deltaToProcessName));
0433
0434 newTokenLabels.insert(newTokenLabels.end(), newProcessName.begin(), newProcessName.end());
0435 newTokenLabels.push_back('\0');
0436 }
0437 m_tokenLabels = std::move(newTokenLabels);
0438 }
0439 }
0440
0441 std::vector<ModuleConsumesInfo> EDConsumerBase::moduleConsumesInfos() const {
0442 std::vector<ModuleConsumesInfo> result;
0443 result.reserve(m_tokenInfo.size());
0444 consumedProducts([&](ModuleConsumesInfo const& info) {
0445 assert(not info.label().empty());
0446 result.push_back(info);
0447 });
0448 return result;
0449 }
0450
0451 std::vector<ModuleConsumesMinimalESInfo> EDConsumerBase::moduleConsumesMinimalESInfos() const {
0452 std::vector<ModuleConsumesMinimalESInfo> result;
0453 result.reserve(esTokenLookupInfoContainer().size());
0454 consumedESProducts([&](ModuleConsumesMinimalESInfo&& minInfo) mutable { result.emplace_back(std::move(minInfo)); });
0455 return result;
0456 }