diff --git a/PhysicsTools/CondLiteIO/plugins/FWLiteESRecordWriterAnalyzer.cc b/PhysicsTools/CondLiteIO/plugins/FWLiteESRecordWriterAnalyzer.cc index 52eacf33365d3..e5b49f0b80d7d 100644 --- a/PhysicsTools/CondLiteIO/plugins/FWLiteESRecordWriterAnalyzer.cc +++ b/PhysicsTools/CondLiteIO/plugins/FWLiteESRecordWriterAnalyzer.cc @@ -23,17 +23,21 @@ // user include files #include "FWCore/Framework/interface/Frameworkfwd.h" -#include "FWCore/Framework/interface/EDAnalyzer.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" #include "FWCore/Framework/interface/EventSetup.h" #include "FWCore/Framework/interface/EventSetupRecord.h" +#include "FWCore/Framework/interface/EventSetupRecordImplementation.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" #include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Framework/interface/ESRecordsToProxyIndices.h" +#include "FWCore/Framework/interface/HCTypeTag.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "PhysicsTools/CondLiteIO/interface/RecordWriter.h" #include "FWCore/Utilities/interface/EDMException.h" -#include "FWCore/Framework/interface/HCTypeTag.h" +#include "FWCore/Utilities/interface/ESGetTokenGeneric.h" // // class declaration @@ -45,6 +49,8 @@ namespace { DataInfo(const edm::eventsetup::heterocontainer::HCTypeTag& iTag, const std::string& iLabel) : m_tag(iTag), m_label(iLabel) {} edm::eventsetup::heterocontainer::HCTypeTag m_tag; + edm::ESGetTokenGeneric m_runToken; + edm::ESGetTokenGeneric m_lumiToken; std::string m_label; }; } // namespace @@ -54,16 +60,62 @@ namespace fwliteeswriter { const edm::eventsetup::heterocontainer::HCTypeTag* m_tag; mutable const void* m_data; }; - struct Handle { - Handle(const DataInfo* iInfo) : m_data(nullptr), m_info(iInfo) {} - const void* m_data; - const DataInfo* m_info; - const edm::eventsetup::ComponentDescription* m_desc; + + class FWLWEventSetupRecord : public edm::eventsetup::EventSetupRecordImplementation { + public: + FWLWEventSetupRecord& operator=(const edm::eventsetup::EventSetupRecordGeneric& iOther) { + edm::eventsetup::EventSetupRecord::operator=(iOther); + return *this; + } }; + } // namespace fwliteeswriter namespace edm { + template <> + class ESHandle : public ESHandleBase { + public: + //typedef T value_type; + + ESHandle() = default; + ESHandle(void const* iData) : ESHandleBase(iData, nullptr) {} + ESHandle(void const* iData, edm::eventsetup::ComponentDescription const* desc) : ESHandleBase(iData, desc) {} + ESHandle(std::shared_ptr&& iWhyFailed) : ESHandleBase(std::move(iWhyFailed)) {} + + // ---------- const member functions --------------------- + void const* product() const { return productStorage(); } + // ---------- static member functions -------------------- + static constexpr bool transientAccessOnly = false; + + // ---------- member functions --------------------------- + }; + + template <> + class ESGetToken { + friend class eventsetup::EventSetupRecord; + + public: + explicit constexpr ESGetToken(DataInfo const& info, bool isRun) noexcept : m_info{info}, m_isRun{isRun} {} + + constexpr unsigned int transitionID() const noexcept { + return m_isRun ? m_info.m_runToken.transitionID() : m_info.m_lumiToken.transitionID(); + } + constexpr bool isInitialized() const noexcept { return transitionID() != std::numeric_limits::max(); } + constexpr ESTokenIndex index() const noexcept { + return m_isRun ? m_info.m_runToken.index() : m_info.m_lumiToken.index(); + } + constexpr bool hasValidIndex() const noexcept { return index() != invalidIndex(); } + static constexpr ESTokenIndex invalidIndex() noexcept { return ESTokenIndex{std::numeric_limits::max()}; } + + constexpr DataInfo const& dataInfo() const noexcept { return m_info; } + + private: + char const* name() const noexcept { return m_info.m_label.c_str(); } + DataInfo const& m_info; + bool m_isRun; + }; + class EventSetupImpl; namespace eventsetup { @@ -71,34 +123,71 @@ namespace edm { template <> void EventSetupRecordImpl::getImplementation( fwliteeswriter::DummyType const*& iData, - const char* iName, - const ComponentDescription*& iDesc, + ESProxyIndex iProxyIndex, bool iTransientAccessOnly, + ComponentDescription const*& oDesc, std::shared_ptr& whyFailedFactory, - ESParentContext const& iParent, - edm::EventSetupImpl const* iEventSetupImpl) const { - DataKey dataKey(*(iData->m_tag), iName, DataKey::kDoNotCopyMemory); - - const void* pValue = this->getFromProxy(dataKey, iDesc, iTransientAccessOnly, iParent, iEventSetupImpl); + EventSetupImpl const* iEventSetupImpl) const { + DataKey const* dataKey = nullptr; + + if (iProxyIndex.value() == std::numeric_limits::max()) { + throw cms::Exception("NoProxyException") << "No data of type \"" << iData->m_tag->name() + << "\" with unknown label in record \"" << this->key().name() << "\""; + iData->m_data = nullptr; + return; + } + assert(iProxyIndex.value() > -1 and + iProxyIndex.value() < static_cast(keysForProxies_.size())); + void const* pValue = this->getFromProxyAfterPrefetch(iProxyIndex, iTransientAccessOnly, oDesc, dataKey); if (nullptr == pValue) { - throw cms::Exception("NoProxyException") << "No data of type \"" << iData->m_tag->name() << "\" with label \"" - << iName << "\" in record \"" << this->key().name() << "\""; + throw cms::Exception("NoDataException") + << "No data of type \"" << iData->m_tag->name() << "\" with label \"" << dataKey->name().value() + << "\" in record \"" << this->key().name() << "\""; } iData->m_data = pValue; } template <> - bool EventSetupRecord::get(const std::string& iName, - fwliteeswriter::Handle& iHolder) const { - fwliteeswriter::DummyType t; - t.m_tag = &(iHolder.m_info->m_tag); - const fwliteeswriter::DummyType* value = &t; - const ComponentDescription* desc = nullptr; - std::shared_ptr dummy; - impl_->getImplementation(value, iName.c_str(), desc, true, dummy, *context_, eventSetupImpl_); - iHolder.m_data = t.m_data; - iHolder.m_desc = desc; - return true; + edm::ESHandle + EventSetupRecord::getHandleImpl( + ESGetToken const& iToken) const { + if UNLIKELY (not iToken.isInitialized()) { + std::rethrow_exception(makeUninitializedTokenException(this->key(), iToken.dataInfo().m_tag)); + } + if UNLIKELY (iToken.transitionID() != transitionID()) { + throwWrongTransitionID(); + } + using TheHandle = edm::ESHandle; + assert(getTokenIndices_); + //need to check token has valid index + if UNLIKELY (not iToken.hasValidIndex()) { + return TheHandle{makeESHandleExceptionFactory( + [key = this->key(), tag = iToken.dataInfo().m_tag, transitionID = iToken.transitionID()] { + return makeInvalidTokenException(key, tag, transitionID); + })}; + } + + auto proxyIndex = getTokenIndices_[iToken.index().value()]; + if UNLIKELY (proxyIndex.value() == std::numeric_limits::max()) { + return TheHandle(makeESHandleExceptionFactory([iToken, key = this->key()] { + cms::Exception exc("NoProxyException"); + exc << "No data of type \"" << iToken.dataInfo().m_tag.name() << "\" with label \"" << iToken.name() + << "\" in record \"" << key.name() << "\""; + return std::make_exception_ptr(exc); + })); + } + + fwliteeswriter::DummyType value; + fwliteeswriter::DummyType const* pValue = &value; + ComponentDescription const* desc = nullptr; + std::shared_ptr whyFailedFactory; + + impl_->getImplementation(pValue, proxyIndex, false, desc, whyFailedFactory, eventSetupImpl_); + + if UNLIKELY (not value.m_data) { + std::rethrow_exception(whyFailedFactory->make()); + } + return edm::ESHandle(value.m_data, desc); } } // namespace eventsetup @@ -113,7 +202,7 @@ namespace { m_dataInfos.swap(ioInfo); } - void update(const edm::EventSetup& iSetup) { + void update(const edm::EventSetup& iSetup, bool iIsRun) { if (not m_record) { m_record = iSetup.find(m_key); assert(m_record); @@ -123,9 +212,11 @@ namespace { for (std::vector::const_iterator it = m_dataInfos.begin(), itEnd = m_dataInfos.end(); it != itEnd; ++it) { - fwliteeswriter::Handle h(&(*it)); - m_record->get(it->m_label, h); - m_writer.update(h.m_data, (it->m_tag.value()), it->m_label.c_str()); + fwliteeswriter::FWLWEventSetupRecord tempRecord; + tempRecord = *m_record; + edm::ESGetToken token(*it, iIsRun); + auto h = tempRecord.getHandle(token); + m_writer.update(h.product(), (it->m_tag.value()), it->m_label.c_str()); } edm::ValidityInterval const& iov = m_record->validityInterval(); m_writer.fill(edm::ESRecordAuxiliary(iov.first().eventID(), iov.first().time())); @@ -141,7 +232,7 @@ namespace { }; } // namespace -class FWLiteESRecordWriterAnalyzer : public edm::EDAnalyzer { +class FWLiteESRecordWriterAnalyzer : public edm::one::EDAnalyzer { public: explicit FWLiteESRecordWriterAnalyzer(const edm::ParameterSet&); ~FWLiteESRecordWriterAnalyzer() override; @@ -152,8 +243,12 @@ class FWLiteESRecordWriterAnalyzer : public edm::EDAnalyzer { void endJob() override; void beginRun(edm::Run const&, edm::EventSetup const&) override; void beginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override; + void endLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override {} + void endRun(edm::Run const&, edm::EventSetup const&) override {} - void update(const edm::EventSetup&); + void update(const edm::EventSetup&, bool isRun); + + void registerLateConsumes(edm::eventsetup::ESRecordsToProxyIndices const&) final; // ----------member data --------------------------- std::vector > m_handlers; @@ -192,6 +287,64 @@ FWLiteESRecordWriterAnalyzer::FWLiteESRecordWriterAnalyzer(const edm::ParameterS m_file = TFile::Open(iConfig.getUntrackedParameter("fileName").c_str(), "NEW"); } +void FWLiteESRecordWriterAnalyzer::registerLateConsumes(edm::eventsetup::ESRecordsToProxyIndices const& iInfo) { + using edm::eventsetup::heterocontainer::HCTypeTag; + + for (auto it = m_recordToDataNames.begin(), itEnd = m_recordToDataNames.end(); it != itEnd; ++it) { + HCTypeTag tt = HCTypeTag::findType(it->first); + if (tt == HCTypeTag()) { + throw cms::Exception("UnknownESRecordType") + << "The name '" << it->first + << "' is not associated with a known EventSetupRecord.\n" + "Please check spelling or load a module known to link with the package which declares that Record."; + } + edm::eventsetup::EventSetupRecordKey rKey(tt); + + auto recIndex = iInfo.recordIndexFor(rKey); + if (recIndex == iInfo.missingRecordIndex()) { + throw cms::Exception("UnknownESRecordType") + << "The name '" << it->first + << "' is not associated with a type which is not an EventSetupRecord.\n" + "Please check your spelling."; + } + + //now figure out what data + std::vector >& data = it->second; + if (data.empty()) { + //get everything from the record + auto keys = iInfo.keysForRecord(rKey); + for (auto itKey = keys.first, itKeyEnd = keys.second; itKey != itKeyEnd; ++itKey) { + data.push_back(std::make_pair(std::string(itKey->type().name()), std::string(itKey->name().value()))); + } + } + + std::vector dataInfos; + for (std::vector >::iterator itData = data.begin(), itDataEnd = data.end(); + itData != itDataEnd; + ++itData) { + HCTypeTag tt = HCTypeTag::findType(itData->first); + if (tt == HCTypeTag()) { + throw cms::Exception("UnknownESDataType") + << "The name '" << itData->first << "' is not associated with a known type held in the " << it->first + << " Record.\n" + "Please check spelling or load a module known to link with the package which declares that type."; + } + if (!bool(edm::TypeWithDict(tt.value()))) { + throw cms::Exception("NoDictionary") + << "The type '" << itData->first << "' can not be retrieved from the Record " << it->first + << " and stored \n" + "because no dictionary exists for the type."; + } + dataInfos.push_back(DataInfo(tt, itData->second)); + dataInfos.back().m_runToken = + esConsumes(rKey, edm::eventsetup::DataKey(tt, itData->second.c_str())); + dataInfos.back().m_lumiToken = + esConsumes(rKey, edm::eventsetup::DataKey(tt, itData->second.c_str())); + } + m_handlers.push_back(std::make_shared(rKey, m_file, dataInfos)); + } +} + FWLiteESRecordWriterAnalyzer::~FWLiteESRecordWriterAnalyzer() { // do anything here that needs to be done at desctruction time // (e.g. close files, deallocate resources etc.) @@ -202,79 +355,16 @@ FWLiteESRecordWriterAnalyzer::~FWLiteESRecordWriterAnalyzer() { // // member functions // -void FWLiteESRecordWriterAnalyzer::update(const edm::EventSetup& iSetup) { - using edm::eventsetup::heterocontainer::HCTypeTag; - if (m_handlers.empty()) { - //now we have access to the EventSetup so we can setup our data structure - for (std::map > >::iterator - it = m_recordToDataNames.begin(), - itEnd = m_recordToDataNames.end(); - it != itEnd; - ++it) { - HCTypeTag tt = HCTypeTag::findType(it->first); - if (tt == HCTypeTag()) { - throw cms::Exception("UnknownESRecordType") - << "The name '" << it->first - << "' is not associated with a known EventSetupRecord.\n" - "Please check spelling or load a module known to link with the package which declares that Record."; - } - edm::eventsetup::EventSetupRecordKey rKey(tt); - - auto rec = iSetup.find(tt); - if (not rec) { - throw cms::Exception("UnknownESRecordType") - << "The name '" << it->first - << "' is not associated with a type which is not an EventSetupRecord.\n" - "Please check your spelling."; - } - - //now figure out what data - std::vector >& data = it->second; - if (data.empty()) { - //get everything from the record - std::vector keys; - rec->fillRegisteredDataKeys(keys); - for (std::vector::iterator itKey = keys.begin(), itKeyEnd = keys.end(); - itKey != itKeyEnd; - ++itKey) { - data.push_back(std::make_pair(std::string(itKey->type().name()), std::string(itKey->name().value()))); - } - } - - std::vector dataInfos; - for (std::vector >::iterator itData = data.begin(), itDataEnd = data.end(); - itData != itDataEnd; - ++itData) { - HCTypeTag tt = HCTypeTag::findType(itData->first); - if (tt == HCTypeTag()) { - throw cms::Exception("UnknownESDataType") - << "The name '" << itData->first << "' is not associated with a known type held in the " << it->first - << " Record.\n" - "Please check spelling or load a module known to link with the package which declares that type."; - } - if (!bool(edm::TypeWithDict(tt.value()))) { - throw cms::Exception("NoDictionary") - << "The type '" << itData->first << "' can not be retrieved from the Record " << it->first - << " and stored \n" - "because no dictionary exists for the type."; - } - dataInfos.push_back(DataInfo(tt, itData->second)); - } - m_handlers.push_back(std::make_shared(rKey, m_file, dataInfos)); - } - } - +void FWLiteESRecordWriterAnalyzer::update(const edm::EventSetup& iSetup, bool isRun) { for (std::vector >::iterator it = m_handlers.begin(), itEnd = m_handlers.end(); it != itEnd; ++it) { - (*it)->update(iSetup); + (*it)->update(iSetup, isRun); } } // ------------ method called to for each event ------------ -void FWLiteESRecordWriterAnalyzer::analyze(const edm::Event& /*iEvent*/, const edm::EventSetup& iSetup) { - update(iSetup); -} +void FWLiteESRecordWriterAnalyzer::analyze(const edm::Event& /*iEvent*/, const edm::EventSetup& iSetup) {} // ------------ method called once each job just before starting event loop ------------ void FWLiteESRecordWriterAnalyzer::beginJob() {} @@ -282,10 +372,12 @@ void FWLiteESRecordWriterAnalyzer::beginJob() {} // ------------ method called once each job just after ending the event loop ------------ void FWLiteESRecordWriterAnalyzer::endJob() { m_file->Write(); } -void FWLiteESRecordWriterAnalyzer::beginRun(edm::Run const&, edm::EventSetup const& iSetup) { update(iSetup); } +void FWLiteESRecordWriterAnalyzer::beginRun(edm::Run const&, edm::EventSetup const& iSetup) { update(iSetup, true); } void FWLiteESRecordWriterAnalyzer::beginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const& iSetup) { - update(iSetup); + update(iSetup, false); } //define this as a plug-in DEFINE_FWK_MODULE(FWLiteESRecordWriterAnalyzer); + +EVENTSETUP_RECORD_REG(fwliteeswriter::FWLWEventSetupRecord); diff --git a/PhysicsTools/CondLiteIO/test/EventSetupIntProductAnalyzer.cc b/PhysicsTools/CondLiteIO/test/EventSetupIntProductAnalyzer.cc index cc573c6101cf1..28cf5ddab0c75 100644 --- a/PhysicsTools/CondLiteIO/test/EventSetupIntProductAnalyzer.cc +++ b/PhysicsTools/CondLiteIO/test/EventSetupIntProductAnalyzer.cc @@ -22,7 +22,7 @@ #include // user include files -#include "FWCore/Framework/interface/EDAnalyzer.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" #include "FWCore/Framework/interface/MakerMacros.h" @@ -39,7 +39,7 @@ namespace edmtest { - class EventSetupIntProductAnalyzer : public edm::EDAnalyzer { + class EventSetupIntProductAnalyzer : public edm::one::EDAnalyzer<> { public: explicit EventSetupIntProductAnalyzer(const edm::ParameterSet&); ~EventSetupIntProductAnalyzer(); @@ -50,6 +50,7 @@ namespace edmtest { // ----------member data --------------------------- std::vector expectedValues_; unsigned int index_; + edm::ESGetToken token_; }; // @@ -65,7 +66,8 @@ namespace edmtest { // EventSetupIntProductAnalyzer::EventSetupIntProductAnalyzer(const edm::ParameterSet& iConfig) : expectedValues_(iConfig.getUntrackedParameter >("expectedValues", std::vector())), - index_(0) { + index_(0), + token_(esConsumes()) { //now do what ever initialization is needed } @@ -81,14 +83,13 @@ namespace edmtest { // ------------ method called to produce the data ------------ void EventSetupIntProductAnalyzer::analyze(const edm::Event& /*iEvent*/, const edm::EventSetup& iSetup) { using namespace edm; - ESHandle pSetup; - iSetup.get().get(pSetup); + auto const& setup = iSetup.getData(token_); - std::cout << "edmtest::IntProduct " << pSetup->value << std::endl; + std::cout << "edmtest::IntProduct " << setup.value << std::endl; if (!expectedValues_.empty()) { - if (expectedValues_.at(index_) != pSetup->value) { + if (expectedValues_.at(index_) != setup.value) { throw cms::Exception("TestFail") << "expected value " << expectedValues_[index_] << " but was got " - << pSetup->value; + << setup.value; } ++index_; }