diff --git a/HLT/Event/TrigByteStreamCnvSvc/CMakeLists.txt b/HLT/Event/TrigByteStreamCnvSvc/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f675677a7478f6e3edab7b09129f065f616cceab --- /dev/null +++ b/HLT/Event/TrigByteStreamCnvSvc/CMakeLists.txt @@ -0,0 +1,52 @@ +################################################################################ +# Package: TrigByteStreamCnvSvc +################################################################################ + +# Declare the package name +atlas_subdir( TrigByteStreamCnvSvc ) + +# Declare the package's dependencies +atlas_depends_on_subdirs( + PUBLIC + Control/AthenaBaseComps + Event/ByteStreamData + PRIVATE + Event/ByteStreamCnvSvcBase + Event/ByteStreamCnvSvc + Event/EventInfo + HLT/Trigger/TrigControl/TrigKernel +) + +# External dependencies +find_package( tdaq-common COMPONENTS eformat_write hltinterface ) + +# Libraries in the package +atlas_add_library( + TrigByteStreamCnvSvcLib + TrigByteStreamCnvSvc/*.h + src/*.cxx + PUBLIC_HEADERS + TrigByteStreamCnvSvc + LINK_LIBRARIES + AthenaBaseComps + ByteStreamData + PRIVATE_INCLUDE_DIRS + ${TDAQ-COMMON_INCLUDE_DIRS} + PRIVATE_LINK_LIBRARIES + ${TDAQ-COMMON_LIBRARIES} + ByteStreamCnvSvcBaseLib + ByteStreamCnvSvcLib + EventInfo + TrigKernel +) + +# Components in the package +atlas_add_component( + TrigByteStreamCnvSvc + src/components/*.cxx + LINK_LIBRARIES TrigByteStreamCnvSvcLib +) + +# Install files from the package +atlas_install_python_modules( python/*.py ) +atlas_install_joboptions( share/*.py ) diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b469920796cd9c5d57b91ed6e23824cca3f09608 --- /dev/null +++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx @@ -0,0 +1,61 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + + +// Trigger includes +#include "TrigByteStreamCnvSvc.h" + + +// ============================================================================= +// Standard constructor +// ============================================================================= +TrigByteStreamCnvSvc::TrigByteStreamCnvSvc(const std::string& name, ISvcLocator* svcLoc) +: ByteStreamCnvSvcBase(name, svcLoc) {} + +// ============================================================================= +// Standard destructor +// ============================================================================= +TrigByteStreamCnvSvc::~TrigByteStreamCnvSvc() {} + +// ============================================================================= +// Implementation of Service::initialize +// ============================================================================= +StatusCode TrigByteStreamCnvSvc::initialize() { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + // ... + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of Service::finalize +// ============================================================================= +StatusCode TrigByteStreamCnvSvc::finalize() { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + // ... + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of IConversionSvc::connectOutput +// The argument outputFile is not used +// ============================================================================= +StatusCode TrigByteStreamCnvSvc::connectOutput(const std::string& /*outputFile*/) { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + // ... + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of IConversionSvc::commitOutput +// The arguments outputFile and do_commit are not used +// ============================================================================= +StatusCode TrigByteStreamCnvSvc::commitOutput(const std::string& /*outputFile*/, bool /*do_commit*/) { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + // ... + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} \ No newline at end of file diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h new file mode 100644 index 0000000000000000000000000000000000000000..fceb2d9df3a848ee67199cadd6994e545cf29798 --- /dev/null +++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGBYTESTREAMCNVSVC_H +#define TRIGBYTESTREAMCNVSVC_H + +#include "ByteStreamCnvSvcBase/ByteStreamCnvSvcBase.h" + +/** @class TrigByteStreamCnvSvc + * @brief A ByteStreamCnvSvc implementation for online use + **/ +class TrigByteStreamCnvSvc : public ByteStreamCnvSvcBase { +public: + /// Standard constructor + TrigByteStreamCnvSvc(const std::string& name, ISvcLocator* svcLoc); + /// Standard destructor + virtual ~TrigByteStreamCnvSvc(); + + // ------------------------- IService methods -------------------------------- + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + + // ------------------------- IConversionSvc methods -------------------------- + /// In the case of online BS data, this method creates the output FullEventFragment and fills its header + virtual StatusCode connectOutput(const std::string& outputFile) override; + /// In the case of online BS data, this method binds and sends out the output FullEventFragment + virtual StatusCode commitOutput(const std::string& outputFile, bool do_commit) override; +}; + +#endif // TRIGBYTESTREAMCNVSVC_H diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.cxx b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c57b26341e050ccf25c7af0cfbc267e936bbbd67 --- /dev/null +++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.cxx @@ -0,0 +1,169 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +// Trigger includes +#include "TrigByteStreamInputSvc.h" +#include "TrigKernel/HltExceptions.h" + +// Athena includes +#include "AthenaKernel/EventContextClid.h" +#include "EventInfo/EventInfo.h" +#include "StoreGate/StoreGateSvc.h" + +// TDAQ includes +#include "hltinterface/DataCollector.h" +#include "eformat/write/FullEventFragment.h" + +// ============================================================================= +// Standard constructor +// ============================================================================= +TrigByteStreamInputSvc::TrigByteStreamInputSvc(const std::string& name, ISvcLocator* svcLoc) +: ByteStreamInputSvc(name, svcLoc), + m_robDataProviderSvc("ROBDataProviderSvc", name), + m_evtStore("StoreGateSvc", name) {} + +// ============================================================================= +// Standard destructor +// ============================================================================= +TrigByteStreamInputSvc::~TrigByteStreamInputSvc() {} + +// ============================================================================= +// Implementation of IInterface::queryInterface +// ============================================================================= +StatusCode TrigByteStreamInputSvc::queryInterface(const InterfaceID& riid, void** ppvInterface) { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + + if(ByteStreamInputSvc::interfaceID().versionMatch(riid)) + *ppvInterface = static_cast<ByteStreamInputSvc*>(this); + else + return AthService::queryInterface(riid, ppvInterface); + + addRef(); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of Service::initialize +// ============================================================================= +StatusCode TrigByteStreamInputSvc::initialize() { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + + CHECK(m_robDataProviderSvc.retrieve()); + CHECK(m_evtStore.retrieve()); + + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of Service::finalize +// ============================================================================= +StatusCode TrigByteStreamInputSvc::finalize() { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + if (m_robDataProviderSvc.release().isFailure()) { + ATH_MSG_WARNING("Cannot release rob data provider"); + } + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of ByteStreamInputSvc::nextEvent +// ============================================================================= +const RawEvent* TrigByteStreamInputSvc::nextEvent() { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + + // get event context from event store + EventContext* eventContext = nullptr; + if (m_evtStore->retrieve(eventContext).isFailure()) { + ATH_MSG_ERROR("Failed to retrieve EventContext from the event store, new event cannot be read"); + return nullptr; + } + + ATH_MSG_DEBUG("Reading new event for event context " << *eventContext); + + eformat::write::FullEventFragment l1r; + using DCStatus = hltinterface::DataCollector::Status; + auto status = DCStatus::NO_EVENT; + do { + status = hltinterface::DataCollector::instance()->getNext(l1r); + if (status == DCStatus::NO_EVENT) + ATH_MSG_ERROR("Failed to read new event, DataCollector::getNext returned Status::NO_EVENT. Trying again."); + } while (status == DCStatus::NO_EVENT); + + if (status == DCStatus::STOP) { + ATH_MSG_DEBUG("No more events available"); + throw hltonl::Exception::NoMoreEvents(); + } + else if (status != DCStatus::OK) { + ATH_MSG_ERROR("Unhandled return Status " << static_cast<int>(status) << " from DataCollector::getNext"); + return nullptr; + } + ATH_MSG_VERBOSE("DataCollector::getNext returned Status::OK"); + + // convert write::FullEventFragment to read::FullEventFragment (RawEvent) + const eformat::write::node_t* top = l1r.bind(); + const size_t l1rFragmentSize = l1r.size_word(); + uint32_t* buf = new uint32_t[l1rFragmentSize]; + auto copiedSize = eformat::write::copy(*top,buf,l1rFragmentSize); + if(copiedSize!=l1rFragmentSize){ + ATH_MSG_ERROR("Event serialization failed"); + return nullptr; + } + + // newRawEvent points to memory allocated by buf + RawEvent* newRawEvent = new RawEvent(buf); + + // find the cache corresponding to the current slot + EventCache* cache = m_eventsCache.get(*eventContext); + + // free the memory allocated to the previous event processed in the current slot + // -- if we make sure ROBDataProviderSvc does this, then TrigByteStreamInputSvc won't need a cache + releaseEvent(cache); + + // put the new raw event into the cache + cache->rawEvent = newRawEvent; + + m_robDataProviderSvc->setNextEvent(*eventContext,newRawEvent); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return newRawEvent; +} + +// ============================================================================= +// Implementation of ByteStreamInputSvc::previousEvent +// ============================================================================= +const RawEvent* TrigByteStreamInputSvc::previousEvent() { + ATH_MSG_FATAL("The method " << __FUNCTION__ << " is not implemented for online running"); + return nullptr; +} + +// ============================================================================= +// Implementation of ByteStreamInputSvc::currentEvent +// ============================================================================= +const RawEvent* TrigByteStreamInputSvc::currentEvent() const { + ATH_MSG_FATAL("The method " << __FUNCTION__ << " is not implemented for online running"); + return nullptr; +} + +// ============================================================================= +void TrigByteStreamInputSvc::releaseEvent(EventCache* cache) +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + if (cache->rawEvent) { + OFFLINE_FRAGMENTS_NAMESPACE::PointerType fragment = cache->rawEvent->start(); + delete[] fragment; + fragment = nullptr; + delete cache->rawEvent; + cache->rawEvent = nullptr; + // cache->eventStatus = 0; + } + ATH_MSG_VERBOSE("end of " << __FUNCTION__); +} + +// ============================================================================= +TrigByteStreamInputSvc::EventCache::~EventCache() { + delete rawEvent; + rawEvent = 0; +} diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.h b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.h new file mode 100644 index 0000000000000000000000000000000000000000..66fc6e623287cb49044ce9012d07c2d5b334ad19 --- /dev/null +++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGBYTESTREAMINPUTSVC_H +#define TRIGBYTESTREAMINPUTSVC_H + +#include "ByteStreamCnvSvc/ByteStreamInputSvc.h" +#include "ByteStreamCnvSvcBase/IROBDataProviderSvc.h" +#include "ByteStreamData/RawEvent.h" +#include "AthenaKernel/SlotSpecificObj.h" + +// Forward declarations +class StoreGateSvc; + +/** @class TrigByteStreamInputSvc + * @brief A ByteStreamInputSvc implementation for online use, reading events from hltinterface::DataCollector + * + * The layout and implementation are based on ByteStreamEventStorageInputSvc + **/ +class TrigByteStreamInputSvc : public ByteStreamInputSvc { +public: + /// Standard constructor + TrigByteStreamInputSvc(const std::string& name, ISvcLocator* svcLoc); + /// Standard destructor + virtual ~TrigByteStreamInputSvc(); + + // -------------------------- IInterface methods ----------------------------- + virtual StatusCode queryInterface(const InterfaceID& riid, void** ppvInterface) override; + + // ------------------------- Service methods -------------------------------- + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + + // ------------------------- ByteStreamInputSvc methods ---------------------- + virtual const RawEvent* nextEvent() override; + virtual const RawEvent* previousEvent() override; + virtual const RawEvent* currentEvent() const override; + +private: + // ------------------------- service handles ---- ---------------------------- + ServiceHandle<IROBDataProviderSvc> m_robDataProviderSvc; + ServiceHandle<StoreGateSvc> m_evtStore; + + // ------------------------- private data members ---------------------------- + struct EventCache { + ~EventCache(); + RawEvent* rawEvent = 0; //!< current event + // unsigned int eventStatus = 0; //!< status of the current event + }; + + SG::SlotSpecificObj<EventCache> m_eventsCache; + + // ------------------------- private helper methods -------------------------- + /// Clean up parts of previous event and re-init them + void releaseEvent(EventCache* cache); +}; + +#endif // TRIGBYTESTREAMINPUTSVC_H diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.cxx b/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.cxx new file mode 100644 index 0000000000000000000000000000000000000000..07d0c129775b3217d24aefec232ec5b520341203 --- /dev/null +++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.cxx @@ -0,0 +1,192 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +// Trigger includes +#include "TrigEventSelectorByteStream.h" +#include "TrigKernel/HltExceptions.h" + +// Athena includes +#include "AthenaKernel/EventContextClid.h" +#include "ByteStreamCnvSvc/ByteStreamInputSvc.h" +#include "ByteStreamCnvSvcBase/ByteStreamAddress.h" +#include "ByteStreamData/RawEvent.h" +#include "EventInfo/EventInfo.h" +#include "StoreGate/StoreGateSvc.h" + +// TDAQ includes +#include "hltinterface/DataCollector.h" + +// ============================================================================= +// Standard constructor +// ============================================================================= +TrigEventSelectorByteStream::TrigEventSelectorByteStream(const std::string& name, ISvcLocator* svcLoc) +: base_class(name, svcLoc), + m_eventSource("ByteStreamInputSvc", name), + m_evtStore("StoreGateSvc", name) { + declareProperty("ByteStreamInputSvc", m_eventSource); +} + +// ============================================================================= +// Standard destructor +// ============================================================================= +TrigEventSelectorByteStream::~TrigEventSelectorByteStream() {} + +// ============================================================================= +// Implementation of Service::initialize +// ============================================================================= +StatusCode TrigEventSelectorByteStream::initialize() +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + + ATH_CHECK(m_eventSource.retrieve()); + ATH_CHECK(m_evtStore.retrieve()); + + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of Service::finalize +// ============================================================================= +StatusCode TrigEventSelectorByteStream::finalize() +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + if (m_eventSource.release().isFailure()) { + ATH_MSG_WARNING("Cannot release the event source service"); + } + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of IEvtSelector::next(Context&) +// There is actually no event selection here, we process all events online +// ============================================================================= +StatusCode TrigEventSelectorByteStream::next(IEvtSelector::Context& /*c*/) const +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + + // RawEvent is a typedef for FullEventFragment + const RawEvent* ptrRawEvent = nullptr; + + // Try to get the next event from the event source + try { + ptrRawEvent = m_eventSource->nextEvent(); + } + catch (const hltonl::Exception::NoMoreEvents& e) { + ATH_MSG_INFO(e.what()); + throw; // rethrow NoMoreEvents + } + catch (const std::exception& e) { + ATH_MSG_ERROR("Failed to get next event from the event source, std::exception caught: " << e.what()); + return StatusCode::FAILURE; + } + catch (...) { + ATH_MSG_ERROR("Failed to get next event from the event source, unhandled exception caught"); + return StatusCode::FAILURE; + } + + // Check if something was returned + if (ptrRawEvent == nullptr) { + ATH_MSG_ERROR("Failed to get next event from the event source, nullptr returned"); + return StatusCode::FAILURE; + } + + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of IEvtSelector::createContext(Context*&) +// ============================================================================= +StatusCode TrigEventSelectorByteStream::createContext(IEvtSelector::Context*& c) const +{ + c = new TrigEventSelectorByteStream::Context(this); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of IEvtSelector::releaseContext(Context*&) +// ============================================================================= +StatusCode TrigEventSelectorByteStream::releaseContext(IEvtSelector::Context*& /*c*/) const +{ + // this does nothing + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of IEvtSelector::createAddress(Context&,IOpaqueAddress*&) +// ============================================================================= +StatusCode TrigEventSelectorByteStream::createAddress(const IEvtSelector::Context& /*c*/, IOpaqueAddress*& iop) const +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + + // Get event context from event store + EventContext* eventContext = nullptr; + ATH_CHECK(m_evtStore->retrieve(eventContext)); + + // Perhaps the name shouldn't be hard-coded + ByteStreamAddress* addr = new ByteStreamAddress(ClassID_traits<EventInfo>::ID(), "ByteStreamEventInfo", ""); + addr->setEventContext(*eventContext); + iop = static_cast<IOpaqueAddress*>(addr); + ATH_CHECK(m_evtStore->recordAddress("ByteStreamEventInfo",iop)); + + ATH_MSG_DEBUG("Recorded new ByteStreamAddress for EventInfo with event context " << *eventContext); + + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Unimplemented methods of IEvtSelector +// ============================================================================= +#define TRIGEVENTSELECTORBYTESTREAM_UNIMPL \ + ATH_MSG_FATAL("Misconfiguration - the method " << __FUNCTION__ << " cannot be used online"); \ + return StatusCode::FAILURE; + +StatusCode TrigEventSelectorByteStream::next(IEvtSelector::Context& /*c*/, int /*jump*/) const +{ + TRIGEVENTSELECTORBYTESTREAM_UNIMPL +} + +StatusCode TrigEventSelectorByteStream::previous(IEvtSelector::Context& /*c*/) const +{ + TRIGEVENTSELECTORBYTESTREAM_UNIMPL +} + +StatusCode TrigEventSelectorByteStream::previous(IEvtSelector::Context& /*c*/, int /*jump*/) const +{ + TRIGEVENTSELECTORBYTESTREAM_UNIMPL +} + +StatusCode TrigEventSelectorByteStream::last(IEvtSelector::Context& /*refContext*/) const +{ + TRIGEVENTSELECTORBYTESTREAM_UNIMPL +} + +StatusCode TrigEventSelectorByteStream::rewind(IEvtSelector::Context& /*c*/) const +{ + TRIGEVENTSELECTORBYTESTREAM_UNIMPL +} + +StatusCode TrigEventSelectorByteStream::resetCriteria(const std::string& /*cr*/, IEvtSelector::Context& /*c*/) const +{ + TRIGEVENTSELECTORBYTESTREAM_UNIMPL +} + +// ============================================================================= +// Context implementation +// ============================================================================= +TrigEventSelectorByteStream::Context::Context(const IEvtSelector* selector) +: m_evtSelector(selector) {} + +TrigEventSelectorByteStream::Context::Context(const TrigEventSelectorByteStream::Context& other) +: m_evtSelector(other.m_evtSelector) {} + +TrigEventSelectorByteStream::Context::~Context() {} + +void* TrigEventSelectorByteStream::Context::identifier() const +{ + return (void*)(m_evtSelector); +} diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.h b/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.h new file mode 100644 index 0000000000000000000000000000000000000000..215116729ec3ebce90ac35d6e10318a657a8a765 --- /dev/null +++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.h @@ -0,0 +1,69 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGEVENTSELECTORBYTESTREAM_H +#define TRIGEVENTSELECTORBYTESTREAM_H + +#include "GaudiKernel/IEvtSelector.h" +#include "AthenaBaseComps/AthService.h" + +// Forward declarations +class ByteStreamInputSvc; +class StoreGateSvc; + +/** + * @class TrigEventSelectorByteStream + * @brief online implementation of IEvtSelector for ByteStream + */ + +class TrigEventSelectorByteStream : public extends<AthService, IEvtSelector> { +public: + /** + * @class TrigEventSelectorByteStream::Context + * @brief Event Selector context for TrigEventSelectorByteStream + */ + class Context : public IEvtSelector::Context { + public: + /// Constructor from a selector + Context(const IEvtSelector* selector); + /// Copy constructor + Context(const TrigEventSelectorByteStream::Context& other); + /// Default destructor + virtual ~Context(); + /// Implementation of IEvtSelector::Context::identifier + virtual void* identifier() const override; + private: + /// pointer to the event selector + const IEvtSelector* m_evtSelector; + }; + + /// Standard constructor + TrigEventSelectorByteStream(const std::string& name, ISvcLocator* svcLoc); + /// Standard destructor + virtual ~TrigEventSelectorByteStream(); + + // ------------------------- Service methods -------------------------------- + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + + // ------------------------- IEvtSelector methods --------------------------- + virtual StatusCode createContext(IEvtSelector::Context*& c) const override; + virtual StatusCode next(IEvtSelector::Context& c) const override; + virtual StatusCode next(IEvtSelector::Context& c, int jump) const override; + virtual StatusCode previous(IEvtSelector::Context& c) const override; + virtual StatusCode previous(IEvtSelector::Context& c, int jump) const override; + virtual StatusCode last(IEvtSelector::Context& refContext) const override; + virtual StatusCode rewind(IEvtSelector::Context& c) const override; + virtual StatusCode createAddress(const IEvtSelector::Context& c, IOpaqueAddress*& iop) const override; + virtual StatusCode releaseContext(IEvtSelector::Context*& c) const override; + virtual StatusCode resetCriteria(const std::string& cr, IEvtSelector::Context& c) const override; + +private: + // @property Reference to the event source (ByteStreamInputSvc) + ServiceHandle<ByteStreamInputSvc> m_eventSource; + // Reference to the StoreGateScv + ServiceHandle<StoreGateSvc> m_evtStore; +}; + +#endif // TRIGEVENTSELECTORBYTESTREAM_H diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/components/TrigByteStreamCnvSvc_entries.cxx b/HLT/Event/TrigByteStreamCnvSvc/src/components/TrigByteStreamCnvSvc_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4b702b644a60af65ff87dae2f18caa4cbf0f0fb8 --- /dev/null +++ b/HLT/Event/TrigByteStreamCnvSvc/src/components/TrigByteStreamCnvSvc_entries.cxx @@ -0,0 +1,7 @@ +#include "../TrigEventSelectorByteStream.h" +#include "../TrigByteStreamInputSvc.h" +#include "../TrigByteStreamCnvSvc.h" + +DECLARE_COMPONENT( TrigEventSelectorByteStream ) +DECLARE_COMPONENT( TrigByteStreamInputSvc ) +DECLARE_COMPONENT( TrigByteStreamCnvSvc ) diff --git a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltExceptions.h b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltExceptions.h new file mode 100644 index 0000000000000000000000000000000000000000..7d7ec7cbf0da711280c0db910d83c98351a4b939 --- /dev/null +++ b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltExceptions.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef HltExceptions_H +#define HltExceptions_H + +#include <exception> + +namespace hltonl { + namespace Exception { + /** + * @class NoMoreEvents + * @brief Can be thrown if all events are already read from the input and another one is requested + */ + class NoMoreEvents : public std::exception { + public: + NoMoreEvents() {} + virtual ~NoMoreEvents() {} + const char* what() const noexcept override {return "No more events to be processed";} + }; + } +} + +#endif // HltExceptions_H diff --git a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltOstreams.h b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltOstreams.h index 97bc24c94b8ae66d8655fc9c63d07dc00485f49a..5a591929bb2f149489bd355442efe21f3e368a93 100644 --- a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltOstreams.h +++ b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltOstreams.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration */ #ifndef HltOstreams_H @@ -10,13 +10,11 @@ #include <vector> #include <stdint.h> #include "eformat/eformat.h" -#include "hltinterface/HLTResult.h" std::ostream& operator<<(std::ostream& os, const std::vector<eformat::helper::StreamTag>& rhs); std::ostream& operator<<(std::ostream& os, const std::vector<uint32_t>& rhs); std::ostream& operator<<(std::ostream& os, const std::vector<eformat::SubDetector>& rhs); std::ostream& operator<<(std::ostream& os, const std::set<uint32_t>& rhs); std::ostream& operator<<(std::ostream& os, const std::set<eformat::SubDetector>& rhs); -std::ostream& operator<<(std::ostream& os, const hltinterface::HLTResult& rhs); #endif // HltOstreams_H diff --git a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/ITrigEventLoopMgr.h b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/ITrigEventLoopMgr.h index 0fe1a6891f9321841ae5d0aa4d8f721e99daad03..58caf01982f52808042bcea3e112e45062dfa914 100644 --- a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/ITrigEventLoopMgr.h +++ b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/ITrigEventLoopMgr.h @@ -1,26 +1,12 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration */ -/**@class ITrigEventLoopMgr - * @brief EventLoopMgr interface implemented by the HLT event loop manager - * - * Provides additional interfaces for TDAQ state transitions used by the PSC. - * It follows the usual Gaudi philosophy of separation framework and client - * implemenation into sysXYZ and XYZ methods. - * - * @author Frank Winklmeier - * @version $Id: ITrigEventLoopMgr.h 39 2013-06-10 17:21:44Z ricab $ - */ - #ifndef TRIGKERNEL_ITRIGEVENTLOOPMGR_H #define TRIGKERNEL_ITRIGEVENTLOOPMGR_H -#include "eformat/ROBFragment.h" #include "GaudiKernel/IInterface.h" #include <boost/property_tree/ptree.hpp> -#include <vector> -#include <stdint.h> namespace hltinterface { @@ -28,12 +14,17 @@ namespace hltinterface struct HLTResult; } +/**@class ITrigEventLoopMgr + * @brief EventLoopMgr interface implemented by the HLT event loop manager + * + * Provides additional interfaces for TDAQ state transitions used by the PSC. + * + * @author Frank Winklmeier + */ class ITrigEventLoopMgr: virtual public IInterface { public: - /* - * Retrieve interface ID - */ - static const InterfaceID& interfaceID(); + /// Interface ID + DeclareInterfaceID(ITrigEventLoopMgr, 21, 0); /** * prepareForRun method invoked by framework @@ -44,24 +35,6 @@ public: * update parameters if necessary after forking workers and issue incident */ virtual StatusCode hltUpdateAfterFork(const boost::property_tree::ptree &) = 0; - - /** - * propagate a processing time out via the HLT framework to the steering/algorithms - */ - virtual StatusCode timeOutReached(const boost::property_tree::ptree&) = 0; - - /// process one event/RoI - virtual StatusCode - processRoIs(const std::vector<eformat::ROBFragment<const uint32_t*> >&, - hltinterface::HLTResult&, - const hltinterface::EventId& evId) = 0; - }; -inline const InterfaceID& ITrigEventLoopMgr::interfaceID() -{ - static const InterfaceID IID_ITrigEventLoopMgr("ITrigEventLoopMgr", 20, 1); - return IID_ITrigEventLoopMgr; -} - #endif diff --git a/HLT/Trigger/TrigControl/TrigKernel/src/HltOstreams.cxx b/HLT/Trigger/TrigControl/TrigKernel/src/HltOstreams.cxx index a39824a8bbf4ef290b33b7453e308809d52ba5da..e1e99248c11cb511bdda300e631077ecb8e45097 100644 --- a/HLT/Trigger/TrigControl/TrigKernel/src/HltOstreams.cxx +++ b/HLT/Trigger/TrigControl/TrigKernel/src/HltOstreams.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration */ //========================================================================= @@ -16,8 +16,8 @@ std::ostream& operator<<(std::ostream& os, const std::vector<eformat::helper::St std::string prefix("\n("); for (std::vector<eformat::helper::StreamTag>::const_iterator it = rhs.begin(); it != rhs.end(); it++) { os << prefix << (*it).name << "," << (*it).type << "," << (*it).obeys_lumiblock - << ",[Rob=" << (*it).robs.size() << ":" << (*it).robs - << "],[Det=" << (*it).dets.size() << ":" << (*it).dets + << ",[Rob=" << (*it).robs.size() << ":" << (*it).robs + << "],[Det=" << (*it).dets.size() << ":" << (*it).dets << "])"; prefix=",\n("; } @@ -69,39 +69,3 @@ std::ostream& operator<<(std::ostream& os, const std::set<eformat::SubDetector>& } return os; } - -std::ostream& operator<<(std::ostream& os, const hltinterface::HLTResult& rhs) { - os << "[HLT Result]" ; - os << "\n HLT Result: fragment_pointer = " << std::hex << rhs.fragment_pointer << std::dec - << ", max_result_size [words] = " << rhs.max_result_size ; - os << "\n HLT Result: Number of HLT result ROBs = " << rhs.hltResult_robs.size() ; - os << "\n ["; - if (rhs.fragment_pointer != 0) { - for (const auto& hltrob : rhs.hltResult_robs) { - os << "\n HLT ROB: Source Identifier = 0x" << std::hex << (hltrob.source_id()) << std::dec - << ", ROB fragment size [words] = " << std::setw(6) << hltrob.fragment_size_word() - << ", # status words = " << hltrob.nstatus() << ", status words =" ; - const uint32_t* it; - hltrob.status(it); - for (uint32_t i(0); i < hltrob.nstatus(); ++i) { - os << std::hex << std::setfill( '0' ) << " 0x" << std::setw(8) << *(it+i); - os << std::dec << std::setfill(' '); - if (i == 1) - os << "(" << hltonl::PrintHltResultStatusCode((hltonl::ResultStatusCode) *(it+1)) << ")"; - if (i == 2) - os << "(" << hltonl::PrintPscErrorCode((hltonl::PSCErrorCode) *(it+2)) << ")"; - } - } - } else { - os << "\n No HLT ROB Fragment: fragment_pointer pointer=0x" << std::hex << rhs.fragment_pointer << std::dec; - } - os << "\n ]"; - - os << "\n Stream tags (Name, Type, LumiBlock, PEB Robs, PEB SubDets) : # of tags = " << rhs.stream_tag.size() - << "\n [" << rhs.stream_tag << "\n ]"; - os << "\n HLT trigger info words: # of words = " << rhs.trigger_info.size() - << "\n [" << rhs.trigger_info << "]"; - os << "\n HLT PSC error words: # of words = " << rhs.psc_errors.size() - << "\n [" << rhs.psc_errors << "]"; - return os; -} diff --git a/HLT/Trigger/TrigControl/TrigPSC/TrigPSC/Psc.h b/HLT/Trigger/TrigControl/TrigPSC/TrigPSC/Psc.h index a08fcfcc2756bfeae0cff02e93a5470266ea9327..cce46e17c9ca8ba4817fc692dd40f6bb38386022 100644 --- a/HLT/Trigger/TrigControl/TrigPSC/TrigPSC/Psc.h +++ b/HLT/Trigger/TrigControl/TrigPSC/TrigPSC/Psc.h @@ -17,6 +17,9 @@ #include "hltinterface/HLTInterface.h" #include "hltinterface/EventId.h" +// to be removed together with the Psc::process method +#include "hltinterface/HLTResult.h" + // Gaudi Includes #include "GaudiKernel/StatusCode.h" @@ -36,13 +39,13 @@ namespace psc { // Fwd decl class Config; - + /** * Common base class for HLT Pesa Steering Controller. */ class Psc: public hltinterface::HLTInterface { - public: + public: /** * C'tor. (Nothing happens here...) */ @@ -89,29 +92,15 @@ namespace psc { */ virtual bool publishStatistics (const boost::property_tree::ptree& args); - /** - * Calls the HLT framework to notify it that a time out is imminent - */ - virtual void timeOutReached (const boost::property_tree::ptree& args); - /** * Calls the HLT framework to notify it that a user command has arrived */ virtual bool hltUserCommand (const boost::property_tree::ptree& args); /** - * Process one event, taking as input, the LVL1 Result and producing as - * output, the HLT Result. - * - * @param l1r. LVL1 result ROBs (input) - * @param hltr. HLT result (output) - * @param evId. EventId structure containing global event number l1id and lb - * number (input) + * Starts the HLT event loop. The HLT framework will start requesting and processing events. */ - virtual bool - process(const std::vector<eformat::ROBFragment<const uint32_t*>>& l1r, - hltinterface::HLTResult& hltr, - const hltinterface::EventId& evId); + virtual void doEventLoop (); /** * Method which can be called for a worker to perform the necessary steps to set @@ -125,9 +114,9 @@ namespace psc { */ virtual bool finalizeWorker (const boost::property_tree::ptree& args); - private: bool setDFProperties(std::map<std::string, std::string> name_tr_table); + bool setAthenaProperties(); /** * Initialize the application manager @@ -149,12 +138,12 @@ namespace psc { IAppMgrUI* m_pesaAppMgr; ///< Application Manager std::string m_nameEventLoopMgr; ///< name of the event loop manager bool m_interactive; ///< Running in interactive mode (athenaMT/PT) - + // User command handling bool m_failNextUsrCmd; unsigned int m_sleepNextUsrCmd; psc::Config * m_config; }; } - + #endif /* TRIGPSC_PSC_H */ diff --git a/HLT/Trigger/TrigControl/TrigPSC/share/TrigPSCPythonSetup.py b/HLT/Trigger/TrigControl/TrigPSC/share/TrigPSCPythonSetup.py index 5217970f2acbfd870d916500f035d2b9e745bd63..3a1a962df3e82192686a418d72b3f13293f2c0bc 100755 --- a/HLT/Trigger/TrigControl/TrigPSC/share/TrigPSCPythonSetup.py +++ b/HLT/Trigger/TrigControl/TrigPSC/share/TrigPSCPythonSetup.py @@ -3,251 +3,266 @@ ## @author Werner Wiedenmann <Werner.Wiedenmann@cern.ch> ############################################################### -### basic setup files and definitions ---------------------------------------- -pscBootstrapFile = "TrigServices/TrigServicesBootstrap.py" # PSC bootstrap -pscServiceSetupBegin = "TrigServices/TrigServicesCommonBegin.py" # Service definitions -pscServiceSetupEnd = "TrigServices/TrigServicesCommonEnd.py" # Service definitions - -import sys, os, string - -### Set up some common flags -------------------------------------------------- - -### athenaCommonFlags -from AthenaCommon.AthenaCommonFlags import athenaCommonFlags -athenaCommonFlags.isOnline.set_Value_and_Lock(True) -del athenaCommonFlags +### setup from a .pkl file +from TrigPSC import PscConfig +joPath = PscConfig.optmap['JOBOPTIONSPATH'] +if joPath[-4:] == '.pkl': + print "Configuring the job from a pickle file" + import AthenaCommon.ConfigurationShelve + AthenaCommon.ConfigurationShelve.loadJobOptionsCatalogue( joPath ) + del AthenaCommon.ConfigurationShelve + print "Job configuration loaded successfully from a pickle file" + +else: + + ### basic setup files and definitions ---------------------------------------- + pscBootstrapFile = "TrigServices/TrigServicesBootstrap.py" # PSC bootstrap + pscServiceSetupBegin = "TrigServices/TrigServicesCommonBegin.py" # Service definitions + pscServiceSetupEnd = "TrigServices/TrigServicesCommonEnd.py" # Service definitions + + import sys, os, string + + ### Set up some common flags -------------------------------------------------- + + ### athenaCommonFlags + from AthenaCommon.AthenaCommonFlags import athenaCommonFlags + athenaCommonFlags.isOnline.set_Value_and_Lock(True) + del athenaCommonFlags + + ### TriggerFlags + from TriggerJobOpts.TriggerFlags import TriggerFlags + TriggerFlags.doHLT.set_Value_and_Lock(True) + + ### By default do not run in validation mode (do not lock this one!) + from TriggerJobOpts.TriggerFlags import TriggerFlags + TriggerFlags.Online.doValidation = False + + del TriggerFlags + + ### logging and messages ----------------------------------------------------- + from AthenaCommon.Logging import * + from AthenaCommon.Constants import * + import AthenaCommon.ExitCodes as ExitCodes -### TriggerFlags -from TriggerJobOpts.TriggerFlags import TriggerFlags -TriggerFlags.doHLT.set_Value_and_Lock(True) + from TrigPSC import PscConfig + logLevel=string.upper(PscConfig.optmap['LOGLEVEL']) + logLevel=string.split(logLevel,",") + if len(logLevel)==0: + logLevel=["INFO","ERROR"] -### By default do not run in validation mode (do not lock this one!) -from TriggerJobOpts.TriggerFlags import TriggerFlags -TriggerFlags.Online.doValidation = False - -del TriggerFlags + if len(logLevel)==1: + logLevel.append("ERROR") -### logging and messages ----------------------------------------------------- -from AthenaCommon.Logging import * -from AthenaCommon.Constants import * -import AthenaCommon.ExitCodes as ExitCodes + ### FOR DEVELOPMENT: force verbose log level + logLevel=["VERBOSE","DEBUG","INFO","ERROR"] -from TrigPSC import PscConfig -logLevel=string.upper(PscConfig.optmap['LOGLEVEL']) -logLevel=string.split(logLevel,",") -if len(logLevel)==0: - logLevel=["INFO","ERROR"] - -if len(logLevel)==1: - logLevel.append("ERROR") - -## test and set log level -try: - exec( 'log.setLevel( logging.%s )' % logLevel[0] ) -except: - sys.exit( ExitCodes.OPTIONS_UNKNOWN ) - -### file inclusion and tracing ----------------------------------------------- -from AthenaCommon.Include import Include, IncludeError, include -showincludes = eval(PscConfig.optmap['SHOWINCLUDE']) -include.setShowIncludes( showincludes ) -if showincludes: - import AthenaCommon.Include as AthCIncMod - AthCIncMod.marker = ' -#-' # distinguish bootstrap from other jo-code - -if PscConfig.optmap['TRACEPATTERN']: - import AthenaCommon.Include - AthenaCommon.Include.tracePattern = PscConfig.optmap['TRACEPATTERN'] - -# -### gaudi -------------------------------------------------------------------- -try: - from GaudiPython import * -except ImportError: - from gaudimodule import * - -from AthenaCommon.Configurable import * -from AthenaCommon.OldStyleConfig import * - -### set output level -------------------------------------------------------- -exec 'OUTPUTLEVEL = %s' % logLevel[0] -if not os.environ.has_key( "POOL_OUTMSG_LEVEL" ): - exec 'os.environ[ "POOL_OUTMSG_LEVEL" ] = str(%s)' % logLevel[1] -del logLevel - -OutputLevel=OUTPUTLEVEL -HLTOutputLevel=OUTPUTLEVEL - -### Athena configuration ----------------------------------------------------- -from AthenaCommon import CfgMgr - -## create the application manager and start in a non-initialised state -from AthenaCommon.AppMgr import theApp -from AthenaCommon.AppMgr import ToolSvc, ServiceMgr, theAuditorSvc - -## These properties have alread been set on the C++ ApplicationMgr in the Psc -## but the configurable needs to have them set as well -theApp.MessageSvcType = PscConfig.optmap["MESSAGESVCTYPE"] -theApp.JobOptionsSvcType = PscConfig.optmap["JOBOPTIONSSVCTYPE"] - -## add the MessageSvc and the JobOptionsSvc to the ServiceMgr -from AthenaCommon.ConfigurableDb import getConfigurable -ServiceMgr += getConfigurable(theApp.JobOptionsSvcType)("JobOptionsSvc") -ServiceMgr += getConfigurable(theApp.MessageSvcType )("MessageSvc" ) - -## set the default values -try: - include( pscBootstrapFile ) -except Exception, e: - if isinstance( e, IncludeError ): - print sys.exc_type, e - theApp._exitstate = ExitCodes.INCLUDE_ERROR - sys.exit( ExitCodes.INCLUDE_ERROR ) - raise - -## properties of the application manager -theApp.StatusCodeCheck = False # enabled via TriggerFlags.Online.doValidation (see below) -theApp.setOutputLevel(OUTPUTLEVEL) - -# Configure the CoreDumpSvc -if not hasattr(ServiceMgr,"CoreDumpSvc"): - from AthenaServices.Configurables import CoreDumpSvc - ServiceMgr += CoreDumpSvc() - -# check if the CoreDumpSvc can provide the FatalHandler -# in case this is not available try for backward compatibility -# to load the old libAthenaServicesDict and try to install it from there -# -if ServiceMgr.CoreDumpSvc.properties().has_key('FatalHandler'): - ServiceMgr.CoreDumpSvc.FatalHandler = -1 # make SIG_INT fatal - -## set resource limits -from AthenaCommon.ResourceLimits import SetMaxLimits -SetMaxLimits() -del SetMaxLimits - -## reset include markers -if showincludes: - AthCIncMod.marker = AthCIncMod.__marker__ # reset - del AthCIncMod -del showincludes - -### run optional command before user job options script ---------------------- -if PscConfig.optmap['PRECOMMAND']: - print "\n" - print " +------------------------------------------------+ " - print " | Execute command before jobOptions script START.| " - print " +------------------------------------------------+ " - print " ---> Command = ", PscConfig.optmap['PRECOMMAND'] + ## test and set log level + try: + exec( 'log.setLevel( logging.%s )' % logLevel[0] ) + except: + sys.exit( ExitCodes.OPTIONS_UNKNOWN ) + + ### file inclusion and tracing ----------------------------------------------- + from AthenaCommon.Include import Include, IncludeError, include + showincludes = eval(PscConfig.optmap['SHOWINCLUDE']) + include.setShowIncludes( showincludes ) + if showincludes: + import AthenaCommon.Include as AthCIncMod + AthCIncMod.marker = ' -#-' # distinguish bootstrap from other jo-code + + if PscConfig.optmap['TRACEPATTERN']: + import AthenaCommon.Include + AthenaCommon.Include.tracePattern = PscConfig.optmap['TRACEPATTERN'] + + # + ### gaudi -------------------------------------------------------------------- try: - exec PscConfig.optmap['PRECOMMAND'] + from GaudiPython import * + except ImportError: + from gaudimodule import * + + from AthenaCommon.Configurable import * + from AthenaCommon.OldStyleConfig import * + + ### set output level -------------------------------------------------------- + exec 'OUTPUTLEVEL = %s' % logLevel[0] + if not os.environ.has_key( "POOL_OUTMSG_LEVEL" ): + exec 'os.environ[ "POOL_OUTMSG_LEVEL" ] = str(%s)' % logLevel[1] + del logLevel + + OutputLevel=OUTPUTLEVEL + HLTOutputLevel=OUTPUTLEVEL + + ### Athena configuration ----------------------------------------------------- + from AthenaCommon import CfgMgr + + ## create the application manager and start in a non-initialised state + from AthenaCommon.AppMgr import theApp + from AthenaCommon.AppMgr import ToolSvc, ServiceMgr, theAuditorSvc + + ## These properties have alread been set on the C++ ApplicationMgr in the Psc + ## but the configurable needs to have them set as well + theApp.MessageSvcType = PscConfig.optmap["MESSAGESVCTYPE"] + theApp.JobOptionsSvcType = PscConfig.optmap["JOBOPTIONSSVCTYPE"] + + ## add the MessageSvc and the JobOptionsSvc to the ServiceMgr + from AthenaCommon.ConfigurableDb import getConfigurable + ServiceMgr += getConfigurable(theApp.JobOptionsSvcType)("JobOptionsSvc") + ServiceMgr += getConfigurable(theApp.MessageSvcType )("MessageSvc" ) + + ## set the default values + try: + include( pscBootstrapFile ) except Exception, e: if isinstance( e, IncludeError ): print sys.exc_type, e theApp._exitstate = ExitCodes.INCLUDE_ERROR - sys.exit( theApp._exitstate ) - elif isinstance( e, ImportError ): - print sys.exc_type, e - theApp._exitstate = ExitCodes.IMPORT_ERROR - sys.exit( theApp._exitstate ) + sys.exit( ExitCodes.INCLUDE_ERROR ) raise - print " +------------------------------------------------+ " - print " | Execute command before jobOptions script END. | " - print " +------------------------------------------------+ " - print "\n" - -### basic job configuration before user configuration ------------------------ -try: - include( pscServiceSetupBegin ) - include.block( pscServiceSetupBegin ) -except Exception, e: - print sys.exc_type, e - if isinstance( e, IncludeError ): - theApp._exitstate = ExitCodes.INCLUDE_ERROR - sys.exit( theApp._exitstate ) - raise - -if 'interactive' in dir(): - import TrigPSC.PscConfig - TrigPSC.PscConfig.interactive = bool(interactive) - del interactive - -### run user jobOptions file ------------------------------------------------- -try: - include( "%s" % PscConfig.optmap['JOBOPTIONSPATH'] ) -except Exception, e: - if isinstance(e,SystemExit): + + ## properties of the application manager + theApp.StatusCodeCheck = False # enabled via TriggerFlags.Online.doValidation (see below) + theApp.setOutputLevel(OUTPUTLEVEL) + + # Configure the CoreDumpSvc + if not hasattr(ServiceMgr,"CoreDumpSvc"): + from AthenaServices.Configurables import CoreDumpSvc + ServiceMgr += CoreDumpSvc() + + # check if the CoreDumpSvc can provide the FatalHandler + # in case this is not available try for backward compatibility + # to load the old libAthenaServicesDict and try to install it from there + # + if ServiceMgr.CoreDumpSvc.properties().has_key('FatalHandler'): + ServiceMgr.CoreDumpSvc.FatalHandler = -1 # make SIG_INT fatal + + ## set resource limits + from AthenaCommon.ResourceLimits import SetMaxLimits + SetMaxLimits() + del SetMaxLimits + + ## reset include markers + if showincludes: + AthCIncMod.marker = AthCIncMod.__marker__ # reset + del AthCIncMod + del showincludes + + ### run optional command before user job options script ---------------------- + if PscConfig.optmap['PRECOMMAND']: + print "\n" + print " +------------------------------------------------+ " + print " | Execute command before jobOptions script START.| " + print " +------------------------------------------------+ " + print " ---> Command = ", PscConfig.optmap['PRECOMMAND'] + try: + exec PscConfig.optmap['PRECOMMAND'] + except Exception, e: + if isinstance( e, IncludeError ): + print sys.exc_type, e + theApp._exitstate = ExitCodes.INCLUDE_ERROR + sys.exit( theApp._exitstate ) + elif isinstance( e, ImportError ): + print sys.exc_type, e + theApp._exitstate = ExitCodes.IMPORT_ERROR + sys.exit( theApp._exitstate ) + raise + print " +------------------------------------------------+ " + print " | Execute command before jobOptions script END. | " + print " +------------------------------------------------+ " + print "\n" + + ### basic job configuration before user configuration ------------------------ + try: + include( pscServiceSetupBegin ) + include.block( pscServiceSetupBegin ) + except Exception, e: + print sys.exc_type, e + if isinstance( e, IncludeError ): + theApp._exitstate = ExitCodes.INCLUDE_ERROR + sys.exit( theApp._exitstate ) raise - # "sanitize" the traceback under the assumption that it is the user's fault - import traceback - exc_info = sys.exc_info() - tb = traceback.extract_tb( exc_info[2] ) + if 'interactive' in dir(): + import TrigPSC.PscConfig + TrigPSC.PscConfig.interactive = bool(interactive) + del interactive + + ### run user jobOptions file ------------------------------------------------- + try: + include( "%s" % PscConfig.optmap['JOBOPTIONSPATH'] ) + except Exception, e: + if isinstance(e,SystemExit): + raise - short_tb = [] - for frame_info in tb: - if not 'AthenaCommon' in frame_info[0]: - short_tb.append( frame_info ) + # "sanitize" the traceback under the assumption that it is the user's fault + import traceback + exc_info = sys.exc_info() + tb = traceback.extract_tb( exc_info[2] ) - print 'Shortened traceback (most recent user call last):' - print ''.join( traceback.format_list( short_tb ) ), - print ''.join( traceback.format_exception_only( exc_info[0], exc_info[1] ) ), + short_tb = [] + for frame_info in tb: + if not 'AthenaCommon' in frame_info[0]: + short_tb.append( frame_info ) - # additional processing to get right error codes - import AthenaCommon.ExitCodes as ExitCodes - if isinstance( e, IncludeError ): - theApp._exitstate = ExitCodes.INCLUDE_ERROR - sys.exit( theApp._exitstate ) - elif isinstance( e, ImportError ): - theApp._exitstate = ExitCodes.IMPORT_ERROR - sys.exit( theApp._exitstate ) - - # Throw exception to stop application - theApp._exitstate = ExitCodes.UNKNOWN_EXCEPTION - raise - -### basic job configuration after user configuration ------------------------- -try: - include( pscServiceSetupEnd ) - include.block( pscServiceSetupEnd ) -except Exception, e: - if isinstance( e, IncludeError ): - print sys.exc_type, e - theApp._exitstate = ExitCodes.INCLUDE_ERROR - sys.exit( ExitCodes.INCLUDE_ERROR ) - raise - -### run optional command after user job options script ----------------------- -if PscConfig.optmap['POSTCOMMAND']: - print "\n" - print " +------------------------------------------------+ " - print " | Execute command after jobOptions script START. | " - print " +------------------------------------------------+ " - print " ---> Command = ", PscConfig.optmap['POSTCOMMAND'] + print 'Shortened traceback (most recent user call last):' + print ''.join( traceback.format_list( short_tb ) ), + print ''.join( traceback.format_exception_only( exc_info[0], exc_info[1] ) ), + + # additional processing to get right error codes + import AthenaCommon.ExitCodes as ExitCodes + if isinstance( e, IncludeError ): + theApp._exitstate = ExitCodes.INCLUDE_ERROR + sys.exit( theApp._exitstate ) + elif isinstance( e, ImportError ): + theApp._exitstate = ExitCodes.IMPORT_ERROR + sys.exit( theApp._exitstate ) + + # Throw exception to stop application + theApp._exitstate = ExitCodes.UNKNOWN_EXCEPTION + raise + + ### basic job configuration after user configuration ------------------------- try: - exec PscConfig.optmap['POSTCOMMAND'] + include( pscServiceSetupEnd ) + include.block( pscServiceSetupEnd ) except Exception, e: if isinstance( e, IncludeError ): print sys.exc_type, e theApp._exitstate = ExitCodes.INCLUDE_ERROR sys.exit( ExitCodes.INCLUDE_ERROR ) - elif isinstance( e, ImportError ): - print sys.exc_type, e - theApp._exitstate = ExitCodes.IMPORT_ERROR - sys.exit( ExitCodes.IMPORT_ERROR ) raise - print " +------------------------------------------------+ " - print " | Execute command after jobOptions script END. | " - print " +------------------------------------------------+ " - print "\n" - -### final tweaks ------------------------------------------------------------- - -from TriggerJobOpts.TriggerFlags import TriggerFlags -if TriggerFlags.Online.doValidation(): - theApp.StatusCodeCheck = True - -del TriggerFlags -### setup everything --------------------------------------------------------- -theApp.setup() + ### run optional command after user job options script ----------------------- + if PscConfig.optmap['POSTCOMMAND']: + print "\n" + print " +------------------------------------------------+ " + print " | Execute command after jobOptions script START. | " + print " +------------------------------------------------+ " + print " ---> Command = ", PscConfig.optmap['POSTCOMMAND'] + try: + exec PscConfig.optmap['POSTCOMMAND'] + except Exception, e: + if isinstance( e, IncludeError ): + print sys.exc_type, e + theApp._exitstate = ExitCodes.INCLUDE_ERROR + sys.exit( ExitCodes.INCLUDE_ERROR ) + elif isinstance( e, ImportError ): + print sys.exc_type, e + theApp._exitstate = ExitCodes.IMPORT_ERROR + sys.exit( ExitCodes.IMPORT_ERROR ) + raise + print " +------------------------------------------------+ " + print " | Execute command after jobOptions script END. | " + print " +------------------------------------------------+ " + print "\n" + + ### final tweaks ------------------------------------------------------------- + + from TriggerJobOpts.TriggerFlags import TriggerFlags + if TriggerFlags.Online.doValidation(): + theApp.StatusCodeCheck = True + + del TriggerFlags + + ### setup everything --------------------------------------------------------- + theApp.setup() diff --git a/HLT/Trigger/TrigControl/TrigPSC/src/Config.cxx b/HLT/Trigger/TrigControl/TrigPSC/src/Config.cxx index b9941967b58ed29b67c2a7afef380aa7e44303e0..88729ef3683d153dabdcdd5ca352993e2ec73ef9 100644 --- a/HLT/Trigger/TrigControl/TrigPSC/src/Config.cxx +++ b/HLT/Trigger/TrigControl/TrigPSC/src/Config.cxx @@ -312,14 +312,19 @@ void psc::Config::fillopt_common(const ptree& hlt) } const ptree& com = hlt.get_child("HLTCommonParameters.HLTCommonParameters"); - optmap["MESSAGESVCTYPE"] = com.get_child("messageSvcType").data(); + optmap["MESSAGESVCTYPE"] = com.get_child("messageSvcType").data(); optmap["JOBOPTIONSSVCTYPE"] = com.get_child("jobOptionsSvcType").data(); - optmap["DLLNAME"] = com.get_child("dllName").data(); - optmap["FACTORYNAME"] = com.get_child("factoryName").data(); - optmap["DF_PARTITION_NAME"] = m_config.get_child("Configuration.Partition." - "UID").data(); - optmap["DF_APPLICATIONNAME"] = - m_config.get_child("Configuration.HLTMPPUApplication.UID").data(); + optmap["DLLNAME"] = com.get_child("dllName").data(); + optmap["FACTORYNAME"] = com.get_child("factoryName").data(); + + optmap["DF_PARTITION_NAME"] = m_config.get_child("Configuration.Partition.UID").data(); + + const ptree& hltmppu = m_config.get_child("Configuration.HLTMPPUApplication"); + optmap["DF_APPLICATIONNAME"] = hltmppu.get_child("UID").data(); + optmap["HARDTIMEOUT"] = hltmppu.get_child("HardTimeout").data(); + optmap["SOFTTIMEOUTFRACTION"] = hltmppu.get_child("softTimeoutFraction").data(); + optmap["NEVENTSLOTS"] = hltmppu.get_child("numberOfEventSlots").data(); + optmap["NTHREADS"] = hltmppu.get_child("numberOfAthenaMTThreads").data(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/HLT/Trigger/TrigControl/TrigPSC/src/Psc.cxx b/HLT/Trigger/TrigControl/TrigPSC/src/Psc.cxx index 7c1ad2e34e2ed2c8dd06f7cab6af697718cd8c46..0469d616712174bd69fd7e3b7c7472f843ff7777 100644 --- a/HLT/Trigger/TrigControl/TrigPSC/src/Psc.cxx +++ b/HLT/Trigger/TrigControl/TrigPSC/src/Psc.cxx @@ -27,6 +27,7 @@ #include "GaudiKernel/SmartIF.h" #include "GaudiKernel/Bootstrap.h" #include "GaudiKernel/IAppMgrUI.h" +#include "GaudiKernel/IEventProcessor.h" #include "GaudiKernel/ISvcLocator.h" #include "GaudiKernel/IProperty.h" #include "GaudiKernel/IService.h" @@ -130,11 +131,12 @@ bool psc::Psc::configure(const ptree& config) * of libGaudiSvc. */ void* libHandle = 0; - if (System::loadDynamicLib(dllname, &libHandle)) { + auto retval = System::loadDynamicLib(dllname, &libHandle); + if (retval == 1) { ERS_DEBUG(1,"Successfully pre-loaded " << dllname << "library"); } else { - ERS_DEBUG(1,"Failed pre-loading " << dllname << "library"); + ERS_DEBUG(1,"Failed pre-loading " << dllname << "library, returned code " << retval); } } @@ -419,6 +421,9 @@ bool psc::Psc::configure(const ptree& config) <<" MuonCalBufferSize = " << m_config->getOption("MUONCALBUFFERSIZE") ); } + // Write configuration specific to athena (HltEventLoopMgr) + if(!setAthenaProperties()) return false; + if ( !jobOptConfig ) { // Run post-command std::string cmd = m_config->getOption("POSTCOMMAND"); @@ -647,20 +652,6 @@ bool psc::Psc::publishStatistics (const ptree& /*args*/) return true; } -//-------------------------------------------------------------------------------- -// Time out is reached -//-------------------------------------------------------------------------------- -void psc::Psc::timeOutReached (const ptree& args) -{ - ERS_DEBUG(1, "Time out reached for HLT processing"); - - // bind args to timeOutReached - auto tor = [&args](ITrigEventLoopMgr * mgr) - {return mgr->timeOutReached(args);}; - callOnEventLoopMgr<ITrigEventLoopMgr>(tor, "timeOutReached").ignore(); -} - - //-------------------------------------------------------------------------------- // User command. Can be sent via: @@ -807,30 +798,16 @@ bool psc::Psc::hltUserCommand(const ptree& args) return true; } -bool psc::Psc::process(const vector<ROBFragment<const uint32_t*> >& l1r, - hltinterface::HLTResult& hltr, - const hltinterface::EventId& evId) +void psc::Psc::doEventLoop() { - // protect against empty L1 result vector - if ( l1r.empty() ) { - ERS_PSC_ERROR("psc::Psc::process: Received no L1 Result ROBs."); - return false; - } - - uint32_t lvl1_id = l1r[0].rod_lvl1_id(); - ERS_DEBUG(2,"psc::Psc::process: Start process() of event " << lvl1_id); - - // - //--- Process Event/RoIs with the event loop manager and fill HLT Decision - // - + ERS_LOG("psc::Psc::doEventLoop: start of doEventLoop()"); StatusCode sc; try { - // bind l1r, hltr, and evId to processRoIs - auto proc = [&](ITrigEventLoopMgr * mgr) - {return mgr->processRoIs(l1r, hltr, evId);}; - sc = callOnEventLoopMgr<ITrigEventLoopMgr>(proc, "processRoIs"); + // bind maxevt=-1 (meaning all events) to executeRun + auto exec = [](IEventProcessor * mgr) + {return mgr->executeRun(-1);}; + sc = callOnEventLoopMgr<IEventProcessor>(exec, "executeRun"); } catch(const ers::Issue& e) { @@ -847,22 +824,10 @@ bool psc::Psc::process(const vector<ROBFragment<const uint32_t*> >& l1r, ERS_PSC_ERROR("Caught an unknown exception"); sc = StatusCode::FAILURE; } - - ERS_DEBUG(2,"psc::Psc::process: Event " << lvl1_id << " has /n" << - " # of stream tags = " << hltr.stream_tag.size() << " /n" << - " # of HLT info words = " << hltr.trigger_info.size() << " /n" << - " # of PSC error words = " << hltr.psc_errors.size() << " /n" << - " pointer to HLT result = 0x" << std::hex << hltr.fragment_pointer << std::dec << " /n" - ); - - if( sc.isSuccess() || sc.isRecoverable() ) { - return true; - } else { - ERS_PSC_ERROR("psc::Psc::process: Error in processing RoIs for Level 1 ID =" - << lvl1_id << " in the EventLoopMgr '" - << m_nameEventLoopMgr << "'."); - return false; + if (sc.isFailure()) { + ERS_PSC_ERROR("psc::Psc::doEventLoop failed"); } + ERS_LOG("psc::Psc::doEventLoop: end of doEventLoop()"); } bool psc::Psc::prepareWorker (const boost::property_tree::ptree& args) @@ -957,10 +922,108 @@ bool psc::Psc::setDFProperties(std::map<std::string, std::string> name_tr_table) return true; } +bool psc::Psc::setAthenaProperties() { + // Use the IProperty interface of the ApplicationManager to find the EventLoopMgr name + SmartIF<IProperty> propMgr(m_pesaAppMgr); + if (!propMgr.isValid()) { + ERS_PSC_ERROR("Error retrieving IProperty interface of ApplicationMgr"); + return false; + } + std::string eventLoopMgrName; + if (propMgr->getProperty("EventLoop", eventLoopMgrName).isFailure()) { + ERS_PSC_ERROR("Error while retrieving the property ApplicationMgr.EventLoop"); + return false; + } + + // Use the JobOptionsSvc to write athena-specific options in JobOptions Catalogue of EventLoopMgr + ServiceHandle<IJobOptionsSvc> p_jobOptionSvc("JobOptionsSvc","psc::Psc"); + + std::string opt = m_config->getOption("HARDTIMEOUT"); + if (!opt.empty()) { + StatusCode sc = p_jobOptionSvc->addPropertyToCatalogue( + eventLoopMgrName, + FloatProperty("HardTimeout",std::stof(opt)) + ); + if (sc.isFailure()) { + ERS_PSC_ERROR("Error could not write the " << eventLoopMgrName + << ".HardTimeout property in JobOptions Catalogue"); + p_jobOptionSvc->release(); + return false; + } + } + else { + ERS_PSC_ERROR("Failed to get the HARDTIMEOUT property from the configuration tree"); + p_jobOptionSvc->release(); + return false; + } + + opt = m_config->getOption("SOFTTIMEOUTFRACTION"); + if (!opt.empty()) { + StatusCode sc = p_jobOptionSvc->addPropertyToCatalogue( + eventLoopMgrName, + FloatProperty("SoftTimeoutFraction",std::stof(opt)) + ); + if (sc.isFailure()) { + ERS_PSC_ERROR("Error could not write the " << eventLoopMgrName + << ".SoftTimeoutFraction property in JobOptions Catalogue"); + p_jobOptionSvc->release(); + return false; + } + } + else { + ERS_PSC_ERROR("Failed to get the SOFTTIMEOUTFRACTION property from the configuration tree"); + p_jobOptionSvc->release(); + return false; + } + + /* The names "EventDataSvc" and "AvalancheSchedulerSvc" are hard-coded below, because it is not possible + to retrieve them from HltEventLoopMgr properties before it is initialised. Here we need to set the properties + before the services are initialised." */ + + opt = m_config->getOption("NEVENTSLOTS"); + if (!opt.empty()) { + StatusCode sc = p_jobOptionSvc->addPropertyToCatalogue( + "EventDataSvc", + IntegerProperty("NSlots",std::stoi(opt)) + ); + if (sc.isFailure()) { + ERS_PSC_ERROR("Error could not write the EventDataSvc.NSlots property in JobOptions Catalogue"); + p_jobOptionSvc->release(); + return false; + } + } + else { + ERS_PSC_ERROR("Failed to get the NEVENTSLOTS property from the configuration tree"); + p_jobOptionSvc->release(); + return false; + } + + opt = m_config->getOption("NTHREADS"); + if (!opt.empty()) { + StatusCode sc = p_jobOptionSvc->addPropertyToCatalogue( + "AvalancheSchedulerSvc", + IntegerProperty("ThreadPoolSize",std::stoi(opt)) + ); + if (sc.isFailure()) { + ERS_PSC_ERROR("Error could not write the AvalancheSchedulerSvc.ThreadPoolSize property in JobOptions Catalogue"); + p_jobOptionSvc->release(); + return false; + } + } + else { + ERS_PSC_ERROR("Failed to get the NTHREADS property from the configuration tree"); + p_jobOptionSvc->release(); + return false; + } + + return true; +} + template <typename T> StatusCode psc::Psc::callOnEventLoopMgr(std::function<StatusCode (T*)> func, const std::string& name) const { + // FIXME static variables are dangerous when forking static T* processingMgr = 0; StatusCode sc; if(!processingMgr) // if we already got it, no need to find it again diff --git a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt index 007f3f211fc07d32d8d63b40172e64b321a1b53c..9cb8349e77b3c4fc403dda5543637469a43bae5b 100644 --- a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt +++ b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt @@ -11,9 +11,11 @@ atlas_depends_on_subdirs( PUBLIC Control/AthenaKernel Control/StoreGate Event/ByteStreamCnvSvcBase + Event/ByteStreamCnvSvc Event/ByteStreamData Event/EventInfo Event/xAOD/xAODEventInfo + Event/xAOD/xAODCnvInterfaces GaudiKernel HLT/Trigger/TrigControl/TrigKernel Trigger/TrigDataAccess/TrigDataAccessMonitoring @@ -26,7 +28,8 @@ atlas_depends_on_subdirs( PUBLIC Trigger/TrigConfiguration/TrigConfInterfaces Trigger/TrigEvent/TrigNavigation Trigger/TrigMonitoring/TrigMonitorBase - Trigger/TrigSteer/TrigInterfaces ) + Trigger/TrigSteer/TrigInterfaces + Trigger/TrigSteer/TrigSteering ) # External dependencies: find_package( Boost COMPONENTS filesystem thread system ) @@ -41,15 +44,14 @@ atlas_add_library( TrigServicesLib PUBLIC_HEADERS TrigServices INCLUDE_DIRS ${TDAQ-COMMON_INCLUDE_DIRS} ${TDAQ_INCLUDE_DIRS} PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} - LINK_LIBRARIES ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} AthenaBaseComps AthenaKernel ByteStreamData EventInfo xAODEventInfo GaudiKernel TrigKernel TrigSteeringEvent StoreGateLib SGtests ByteStreamCnvSvcBaseLib ByteStreamData_test TrigDataAccessMonitoringLib TrigROBDataProviderSvcLib TrigNavigationLib TrigMonitorBaseLib TrigInterfacesLib - PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CORAL_LIBRARIES} SGTools AthenaPoolUtilities ) + LINK_LIBRARIES ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} AthenaBaseComps AthenaKernel ByteStreamCnvSvcLib ByteStreamData EventInfo xAODEventInfo GaudiKernel TrigKernel TrigSteeringEvent StoreGateLib SGtests ByteStreamCnvSvcBaseLib ByteStreamData_test TrigDataAccessMonitoringLib TrigROBDataProviderSvcLib TrigNavigationLib TrigMonitorBaseLib TrigInterfacesLib + PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CORAL_LIBRARIES} SGTools AthenaPoolUtilities TrigSteering ) atlas_add_component( TrigServices src/components/*.cxx INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} ${TDAQ-COMMON_INCLUDE_DIRS} ${TDAQ_INCLUDE_DIRS} - LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CORAL_LIBRARIES} ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests ByteStreamCnvSvcBaseLib ByteStreamData ByteStreamData_test EventInfo xAODEventInfo GaudiKernel TrigKernel TrigDataAccessMonitoringLib TrigROBDataProviderSvcLib TrigSteeringEvent SGTools AthenaPoolUtilities TrigNavigationLib TrigMonitorBaseLib TrigInterfacesLib TrigServicesLib ) + LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CORAL_LIBRARIES} ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests ByteStreamCnvSvcBaseLib ByteStreamData ByteStreamData_test EventInfo xAODEventInfo GaudiKernel TrigKernel TrigDataAccessMonitoringLib TrigROBDataProviderSvcLib TrigSteeringEvent SGTools AthenaPoolUtilities TrigNavigationLib TrigMonitorBaseLib TrigInterfacesLib TrigServicesLib TrigSteering ) # Install files from the package: atlas_install_python_modules( python/*.py ) atlas_install_joboptions( share/*.py ) - diff --git a/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h b/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h index 2a35beeb4ac4e6e5eabb56ee77d709c52ea301f6..eeaa3fec46eda1fdd9ccfac0b1c32017ea12e844 100644 --- a/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h +++ b/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h @@ -5,467 +5,263 @@ #ifndef TRIGSERVICES_HLTEVENTLOOPMGR_H #define TRIGSERVICES_HLTEVENTLOOPMGR_H +// Trigger includes +#include "TrigKernel/IHltTHistSvc.h" #include "TrigKernel/ITrigEventLoopMgr.h" -#include "EventInfo/EventID.h" /* number_type */ -#include "EventInfo/TriggerInfo.h" -#include "xAODEventInfo/EventInfo.h" -#include "eformat/eformat.h" +#include "TrigROBDataProviderSvc/ITrigROBDataProviderSvc.h" +#include "TrigSteering/ResultBuilderMT.h" -// Framework include files -#include "GaudiKernel/ServiceHandle.h" -#include "GaudiKernel/SmartIF.h" -#include "GaudiKernel/ToolHandle.h" -#include "GaudiKernel/MinimalEventLoopMgr.h" -#include "GaudiKernel/HistoProperty.h" +// Athena includes +#include "AthenaBaseComps/AthService.h" #include "AthenaKernel/Timeout.h" -#include "TrigKernel/HltOstreams.h" -#include "TrigKernel/HltAcceptFlag.h" -#include "TrigKernel/HltResultStatusCode.h" -#include "TrigKernel/HltPscErrorCode.h" -#include "TrigKernel/IHltTHistSvc.h" -#include "TrigROBDataProviderSvc/ITrigROBDataProviderSvc.h" +#include "EventInfo/EventID.h" // number_type +#include "StoreGate/WriteHandle.h" +#include "xAODCnvInterfaces/IEventInfoCnvTool.h" -#include <tuple> -#include <utility> -#include <functional> +// Gaudi includes +#include "GaudiKernel/IEventProcessor.h" +#include "GaudiKernel/IEvtSelector.h" +#include "GaudiKernel/SmartIF.h" + +// TDAQ includes +#include "eformat/write/FullEventFragment.h" + +// System includes +#include <atomic> +#include <chrono> +#include <condition_variable> #include <memory> -#include <vector> -#include <set> -#include <stdint.h> +#include <thread> // Forward declarations -class IIncidentSvc; -class IAlgContextSvc; +class CondAttrListCollection; +class EventContext; class IAlgExecStateSvc; -class StoreGateSvc; +class IAlgorithm; +class IAlgResourcePool; +class IConversionSvc; +class IHiveWhiteBoard; +class IIncidentSvc; class IROBDataProviderSvc; +class IScheduler; class ITHistSvc; -class TrigISHelper; -class TH1F; -class TH2I; -class TProfile; -class EventInfo; +class StoreGateSvc; class TrigCOOLUpdateHelper; -class CondAttrListCollection; -class EventContext; - namespace coral { class AttributeList; } -namespace TrigConf { - class IHLTConfigSvc; -} namespace HLT { class HLTResult; } -namespace eformat { - namespace write { - class ROBFragment; - } -} -class HltEventLoopMgr : public MinimalEventLoopMgr, - virtual public ITrigEventLoopMgr, - virtual public Athena::TimeoutMaster + +class HltEventLoopMgr : public extends2<AthService, ITrigEventLoopMgr, IEventProcessor>, + public Athena::TimeoutMaster { public: - /// Standard Constructor - HltEventLoopMgr(const std::string& nam, ISvcLocator* svcLoc); - /// Standard Destructor - virtual ~HltEventLoopMgr(); - - /// implementation of IInterface: queryInterface - virtual StatusCode queryInterface(const InterfaceID& riid, void** ppvInterface); - - /// \name State transitions - //@{ - virtual StatusCode sysInitialize(); - virtual StatusCode initialize(); - - virtual StatusCode prepareForRun(const boost::property_tree::ptree & pt); - virtual StatusCode hltUpdateAfterFork(const boost::property_tree::ptree & pt); - - virtual StatusCode stop(); - - virtual StatusCode sysFinalize(); - virtual StatusCode finalize(); - - virtual StatusCode sysReinitialize(); - virtual StatusCode reinitialize(); - //@} - - /// Event processing - virtual StatusCode executeEvent(void* par); - - virtual StatusCode - processRoIs(const std::vector<eformat::ROBFragment<const uint32_t*> >& l1_result, - hltinterface::HLTResult& hlt_result, - const hltinterface::EventId& evId); - - /// Event timoeut reached - virtual StatusCode timeOutReached(const boost::property_tree::ptree& pt); - - /// return the application Name - std::string applicationName() const { return m_applicationName.value(); } - - /// \name Obsolete methods for online running - //@{ - virtual StatusCode nextEvent(int maxevt); ///< Obsolete - virtual StatusCode executeRun(int runNumber); ///< Obsolete - virtual StatusCode stopRun(); ///< Obsolete - virtual StatusCode start(); ///< Obsolete - //@} - -private: + /// Standard constructor + HltEventLoopMgr(const std::string& name, ISvcLocator* svcLoc); + /// Standard destructor + virtual ~HltEventLoopMgr(); - /** - * @brief Call execute method of algorithms - * @return FAILURE in case one algorithm failed - */ - StatusCode executeAlgorithms(); + /// @name Gaudi state transitions (overriden from AthService) + ///@{ + virtual StatusCode initialize() override; + virtual StatusCode start() override; + virtual StatusCode stop() override; + virtual StatusCode finalize() override; + virtual StatusCode reinitialize() override; + virtual StatusCode restart() override; + ///@} + + /// @name State transitions of ITrigEventLoopMgr interface + ///@{ + virtual StatusCode prepareForRun(const boost::property_tree::ptree& pt); + virtual StatusCode hltUpdateAfterFork(const boost::property_tree::ptree& pt); + ///@} /** - * @brief Check if an HLT prescale update is required - * @param hltCounter list of "HLT counters" from CTP fragment (only one used) + * Implementation of IEventProcessor::executeRun which calls IEventProcessor::nextEvent + * @param maxevt number of events to process, -1 means all */ - StatusCode checkHltPrescaleUpdate(std::vector<uint32_t>& hltCounter); + virtual StatusCode executeRun(int maxevt=-1); /** - * @brief Do HLT prescale update - * @param lumiBlock LB for which the update should be done - */ - StatusCode hltPrescaleUpdate(uint32_t lumiBlock); - - /** - * @brief Helper to fill histograms from HLT result - * @param hlt_result reference to dataflow HLTResult object + * Implementation of IEventProcessor::nextEvent which implements the event loop + * @param maxevt number of events to process, -1 means all */ - void fillHltResultHistograms(const hltinterface::HLTResult& hlt_result); - - /// Check if running in partition - bool validPartition() const { - return (m_partitionName.value()!="None" && m_partitionName.value()!="NONE"); - } + virtual StatusCode nextEvent(int maxevt=-1); /** - * @brief Helper to set PSC error word - * @param hlt_result reference to dataflow HLTResult object; filled on return - * @param pscErrorCode PSC Error code which should be set + * Implementation of IEventProcessor::executeEvent which processes a single event + * @param par generic parameter */ - void HltSetPscError(hltinterface::HLTResult& hlt_result, - hltonl::PSCErrorCode pscErrorCode) const; + virtual StatusCode executeEvent(void* par); /** - * @brief Helper to build an empty dataflow HLT Result object - * @param hlt_result reference to dataflow HLTResult object; filled on return - * @param run_no for ROB fragment - * @param lvl1_id for ROB fragment - * @param bunch_crossing_id for ROB fragment - * @param l1_Trigger_Type for ROB fragment - * @param l1_detev_type for ROB fragment - * @param pscErrorCode PSC Error code which should be set + * Implementation of IEventProcessor::stopRun (obsolete for online runnning) */ - void HltEmptyResultROB(hltinterface::HLTResult& hlt_result, - uint32_t run_no, uint32_t lvl1_id, uint32_t bunch_crossing_id, - uint32_t l1_Trigger_Type, uint32_t l1_detev_type, - hltonl::PSCErrorCode pscErrorCode); + virtual StatusCode stopRun(); - /** - * @brief Helper to build the dataflow HLT Result object. - * @return value error code hltonl::PSCErrorCode - * @param hlt_result reference to dataflow HLTResult object; filled on return - * @param run_no for ROB fragment - * @param lvl1_id for ROB fragment - * @param bunch_crossing_id for ROB fragment - * @param l1_Trigger_Type for ROB fragment - * @param l1_detev_type for ROB fragment - * @param trigger_info trigger info words for the HLT - * @param stream_tags stream tags generated during HLT processing - */ - hltonl::PSCErrorCode HltResultROBs(hltinterface::HLTResult& hlt_result, - uint32_t run_no, uint32_t lvl1_id, uint32_t bunch_crossing_id, - uint32_t l1_Trigger_Type, uint32_t l1_detev_type, - const std::vector<TriggerInfo::number_type>& trigger_info, - const std::vector<TriggerInfo::StreamTag>& stream_tags, - const std::vector<xAOD::EventInfo::StreamTag>& xsts); - - /// Helper to build an empty HLTResult object - void HltEmptyResultROB(hltinterface::HLTResult& hlt_result, - hltonl::PSCErrorCode pscErrorCode); - /// Helper to build HLTResult object from Steering result - void HltResult(hltinterface::HLTResult& hlt_result, - const EventInfo* pEvent, - const xAOD::EventInfo* xev); - /// Helpers to book histograms - void bookHistograms(); - void HltBookHistograms(); - void bookAllHistograms(); +private: + // ------------------------- Helper methods ---------------------------------- + + /// Check if running in partition + bool validPartition() const; + + /// Read DataFlow configuration properties void updateDFProps(); - // Call a simple IAlgorithm (usually member) function on all algorithms - StatusCode callOnAlgs(const std::function<StatusCode(IAlgorithm&)> & func, - const std::string & fname, bool failureIsError = false); - StatusCode prepareAlgs(const EventInfo& evinfo); - /// Helper to reset necessary data at prepareForRun - StatusCode internalPrepareResets(); - /// Helper to do whatever is necessary with RunParams (prepare) ptree - const CondAttrListCollection * - processRunParams(const boost::property_tree::ptree & pt); - // Helper to update internally kept data from new sor - void updInternal(const coral::AttributeList & sor_attrlist); - // Helper to get update the metadata store with a new metadata record - void updMetadaStore(const coral::AttributeList & sor_attrlist); - /// Helper to clear per-event stores + + /// Do whatever is necessary with RunParams (prepare) ptree + const CondAttrListCollection* processRunParams(const boost::property_tree::ptree& pt); + + // Update internally kept data from new sor + void updateInternal(const coral::AttributeList & sor_attrlist); + + // Update internally kept data from new sor + void updateMetadataStore(const coral::AttributeList & sor_attrlist) const; + + /// Clear per-event stores StatusCode clearTemporaryStores(); - /// Helper to update the detector mask - void updDetMask(const std::pair<uint64_t, uint64_t>& dm); - /// Helper to update the SOR time stamp - void updSorTime(unsigned long long st); - /// Helper to extract the single attr list off the SOR CondAttrListCollection - const coral::AttributeList & - getSorAttrList(const CondAttrListCollection * sor) const; - /// Update the HLTConfigSvc (only required to succeed with DB based config) - StatusCode updHLTConfigSvc(); - /// Set the EventInfo in the event store and return it - const EventInfo * prepEventInfo() const; - /// Set the xAOD::EventInfo in the event store - StatusCode prepXAODEventInfo() const; - /// Update the magnet field from IS when necessary and possible - StatusCode updMagField(const boost::property_tree::ptree& pt) const; - /// Reset selected proxies / IOV folders - StatusCode resetCoolValidity(); - /// Helper to log a message with some details when ready to run - void readyMsg() const; - /// Helper to fill in HLTResult with stream tags - void setStreamTags(hltinterface::HLTResult& hltr, - const std::vector<TriggerInfo::StreamTag>& stream_tags) const; - void mergeStreamTags(hltinterface::HLTResult& hltr, - const std::vector<xAOD::EventInfo::StreamTag>& xsts) const; - /// get the right hlt decision, setting debug stream tag if necessary - hltonl::AcceptFlag processHltDecision(hltinterface::HLTResult& hltr) const; - /// Serializes Steering's result into hltinterface's result robs - hltonl::PSCErrorCode serializeRobs(hltinterface::HLTResult& hltr, bool& serOk, - HLT::HLTResult* dobj, uint32_t rn, - uint32_t l1id, uint32_t bcid, - uint32_t l1tt, uint32_t dett); - // Check whether a rob fits the space left. If not, issue an error - bool checkRobSize(uint32_t robsize, uint32_t spaceleft, uint32_t maxsize); - // Check consistency of the info received in the EventId and the CTP fragment - bool checkEventIdConsistency(const hltinterface::EventId& evId) const; - // serialize rob from steering's HLTResult - bool serializeRob(uint32_t*& tmpstor, - eformat::write::ROBFragment& rob, - HLT::HLTResult& dobj, - unsigned int robid, - int payload_max); - // add rob to hltinterface::HLTResult - void addRobToHLTResult(hltinterface::HLTResult& hltr, - eformat::write::ROBFragment& rob, - uint32_t*& next_fragment, - uint32_t& spaceleft); /* don't pass original - fragment_pointer or max_result_size (notice parameters - passed by reference) */ - // Get monitoring information for navigation sizes of HLT EDM - void recordEDMSizeInfo(size_t nav_size, bool serializationOk) const; - // check if a ROB is enabled for readout in OKS - bool isRobEnabled(uint32_t robid) const; - // check if a Sub Detector is enabled for readout in OKS - bool isSubDetectorEnabled(uint32_t subdetid) const; - // filter a set of robs according to whether or not they are enabled - std::set<uint32_t> filterRobs(const std::set<uint32_t>& robs) const; - // filter a set of dets according to whether or not they are enabled - std::set<eformat::SubDetector> - filterDets(const std::set<uint32_t>& dets) const; - - // act on failure to process event - void failedEvent(hltinterface::HLTResult& hlt_result, - hltonl::PSCErrorCode ecode, - const std::string& emsg, - bool empty_result = true); - - // get a vector with the ids of the expected L1R robs that are missing - std::vector<uint32_t> - missingL1Robs(const std::vector<eformat::ROBFragment<const uint32_t*>>& l1r) - const; - - // check whether a subdetector is in the run, according to the current detmask - bool isSubDetectorIn(eformat::SubDetector sd) const; - - // Helper to create EventContext - StatusCode installEventContext (const EventInfo* pEvent, EventID::number_type run); - - /** Handles to required services/tools **/ - typedef ServiceHandle<IIncidentSvc> IIncidentSvc_t; - IIncidentSvc_t m_incidentSvc; - - typedef ServiceHandle<StoreGateSvc> StoreGateSvc_t; - StoreGateSvc_t m_evtStore; - StoreGateSvc_t m_detectorStore; - StoreGateSvc_t m_inputMetaDataStore; - - typedef ServiceHandle<IROBDataProviderSvc> IIROBDataProviderSvc_t; - IIROBDataProviderSvc_t m_robDataProviderSvc; - - typedef ServiceHandle<ITHistSvc> ITHistSvc_t; - ITHistSvc_t m_THistSvc; - - ServiceHandle<IAlgExecStateSvc> m_aess; - - ToolHandle<TrigISHelper> m_isHelper; - ToolHandle<TrigCOOLUpdateHelper> m_coolHelper; - - /** Pointers to optional services/tools **/ - TrigConf::IHLTConfigSvc* m_hltConfigSvc{0}; - IAlgContextSvc* m_algContextSvc{0}; - - IntegerProperty m_lvl1CTPROBid ; // Source ID for CTP ROB fragment - BooleanProperty m_doMonitoring; // Monitoring - - /// Helper classes for error codes - hltonl::MapPscErrorCode m_mapPscError; - hltonl::MapResultStatusCode m_mapResultStatus; - hltonl::MapAcceptFlag m_mapAccept; - - EventID::number_type m_currentRun{0}; //!< current run number - EventID::number_type m_currentLB{0}; //!< current lumiblock - const EventInfo* m_currentEvent{0}; //!< current EventInfo object in StoreGate - - /// Start of Run Time: posix time in seconds since 1970/01/01 - /// Start of Run Time: time stamp ns - ns time offset for time_stamp, 32 bit unsigned - std::vector<EventID::number_type> m_sorTime_stamp; - - /// detector mask0,1,2,3 - bit field indicating which TTC zones have been - /// built into the event, one bit per zone, 128 bit total - /// significance increases from first to last - typedef EventID::number_type numt; - std::tuple<numt, numt, numt, numt> m_detector_mask; - uint32_t m_l1_hltPrescaleUpdateLB; //!< LB of prescale update from CTP fragment - - // --------------------------- Monitoring Histograms -------------------------- - TH1F* m_hist_eventAcceptFlags{0}; //!< Accept flags for processed events - TH1F* m_hist_frameworkErrorCodes{0}; //!< PSC error codes - TH1F* m_hist_Hlt_result_size{0}; //!< size of HLT result - TH1F* m_hist_Hlt_result_status{0}; //!< Status flags in HLT result - TH1F* m_hist_numStreamTags{0}; //!< Number of StreamTags from HLT - TH1F* m_hist_streamTagTypes{0}; //!< StreamTag types from HLT - TH1F* m_hist_streamTagNames{0}; //!< StreamTag names from HLT - TH1F* m_hist_num_partial_eb_robs{0}; //!< Number of ROBs for partial event building from HLT - TH1F* m_hist_num_partial_eb_SubDetectors{0}; //!< Number of SubDetectors for partial event building from HLT - TH1F* m_hist_partial_eb_SubDetectors_ROBs{0};//!< SubDetectors for partial event building derived from ROB list - TH1F* m_hist_partial_eb_SubDetectors_SDs{0}; //!< SubDetectors for partial event building derived from SubDetector list - TH1F* m_hist_Hlt_result_size_physics{0}; //!< size of HLT result in physics Main - TH1F* m_hist_Hlt_result_size_express{0}; //!< size of HLT result in express stream - TH1F* m_hist_Hlt_result_size_DataScouting{0}; //!< size of HLT result in express stream - TProfile* m_hist_HltResultSizes_Stream_physics{0}; //!< HLT Result sizes for physiscs streams - TProfile* m_hist_HltResultSizes_Stream_DataScouting{0};//!< HLT Result sizes for DataScouting streams - TProfile* m_hist_HltEdmSizes_No_Truncation{0}; //!< HLT EDM sizes for all events without a truncated HLT result - TProfile* m_hist_HltEdmSizes_With_Truncation{0}; //!< HLT EDM sizes for all events with a truncated HLT result - TProfile* m_hist_HltEdmSizes_TruncatedResult_Retained_Collections{0}; //!< HLT EDM sizes for all collections which were retained in a truncated HLT result - TProfile* m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections{0};//!< HLT EDM sizes for all collections which were truncated in a truncated HLT result - // --------------------------- Properties ------------------------------------- - BooleanProperty m_setMagFieldFromPtree; //!< Read magnet currents from ptree - StringProperty m_applicationName; //!< Application Name (="None" or "athenaHLT" for simulated data, "HLTMPPU-xx"? in online environment) */ - StringProperty m_partitionName; //!< Partition Name (="None" for offline, real partion name in online environment) - BooleanProperty m_forceHltReject; // force reject of all events - BooleanProperty m_forceHltAccept; // force accept of all events - StringProperty m_HltResultName; // name of HLT result in StoreGate - StringProperty m_HltDebugStreamName; // stream name for Debug events - StringProperty m_HltForcedStreamName; // stream name for forced accept events - IntegerProperty m_predefinedLumiBlock; - IntegerProperty m_prepareForRunSleep; //!< max random sleep during prepareForRun in sec - - typedef SimpleProperty< std::vector<uint32_t> > Uint32ArrayProperty; - Uint32ArrayProperty m_enabledROBs; //!< list of all enabled ROBs which can be retrieved - Uint32ArrayProperty m_enabledSubDetectors; //!< list of all enabled Sub Detectors which can be retrieved - Uint32ArrayProperty m_mandatoryL1ROBs; //!< list of mandatory ROB IDs coming from the RoIB (must come in L1R seed) - - StringArrayProperty m_hltEdmCollectionNames; //!< names of all HLT EDM collections for histogram label - - StringProperty m_jobOptionsType; //!< JobOptions type (="NONE" or "DB", same as in PSC) - - Histo1DProperty m_histProp_Hlt_result_size; - Histo1DProperty m_histProp_Hlt_result_size_physics; - Histo1DProperty m_histProp_Hlt_result_size_express; - Histo1DProperty m_histProp_Hlt_result_size_DataScouting; - Histo1DProperty m_histProp_numStreamTags; - Histo1DProperty m_histProp_streamTagNames; - Histo1DProperty m_histProp_num_partial_eb_robs; - Histo1DProperty m_histProp_Hlt_Edm_Sizes; //!< HLT EDM sizes profile plots - - int m_total_evt{0}; - int m_failed_evt{0}; - int m_invalid_lvl1_result{0}; - int m_invalid_hlt_result{0}; - int m_truncated_hlt_result{0}; - int m_truncated_hlt_result_to_debug{0}; - int m_truncated_hlt_result_not_to_debug{0}; - - // for CTP Lvl1 Rob - std::vector<uint32_t> m_ctpRobIdVec ; - // event number - 32 bit unsigned - uint32_t m_lvl1id{0} ; - // run number - 32 bit unsigned - EventID::number_type m_run_no{0} ; - // bunch crossing ID, 32 bit unsigned - EventID::number_type m_bunch_crossing_id{0} ; - // time stamp - posix time in seconds from 1970, 32 bit unsigned - EventID::number_type m_time_stamp{0} ; - // time stamp ns - ns time offset for time_stamp, 32 bit unsigned - EventID::number_type m_time_stamp_ns_offset{0} ; - // luminosity block identifier, 32 bit unsigned - EventID::number_type m_lumi_block{0} ; - // status element - TriggerInfo::number_type m_l1_Status_Element{0} ; - // LVL1 trigger type - TriggerInfo::number_type m_l1_Trigger_Type{0} ; - // LVL1 trigger info - std::vector<TriggerInfo::number_type> m_l1_Trigger_Info ; - // LVL1 detev type - uint32_t m_l1_detev_type{0} ; + /// Update the detector mask + void updateDetMask(const std::pair<uint64_t, uint64_t>& dm); - /// Reference to a THistSvc which implements also the Hlt additions - SmartIF<IHltTHistSvc> m_hltTHistSvc; + /// Extract the single attr list off the SOR CondAttrListCollection + const coral::AttributeList& getSorAttrList(const CondAttrListCollection* sor) const; - /// Reference to a ROBDataProviderSvc which implements also the Hlt additions - SmartIF<ITrigROBDataProviderSvc> m_hltROBDataProviderSvc; + /// Print the SOR record + void printSORAttrList(const coral::AttributeList& atr) const; - /// Check integrity of CTP ROB and put event to debug stream when it fails - BooleanProperty m_lvl1CTPROBcheck ; + /// Handle a failure to process an event + void failedEvent(EventContext* eventContext, + const xAOD::EventInfo* eventInfo=nullptr, + HLT::HLTResult* hltResult=nullptr) const; - /// Monitoring - TH1F* m_hist_l1_robs{0}; + // Build an HLT result FullEventFragment and serialise it into uint32[] + std::unique_ptr<uint32_t[]> fullHltResult(const xAOD::EventInfo* eventInfo, + HLT::HLTResult* hltResult) const; - /// Flag to write events with truncated HLT result to a special debug stream - BooleanProperty m_writeHltTruncationToDebug ; - /// Debug stream name for events with a truncated HLT result - StringProperty m_HltTruncationDebugStreamName; - /// Stream names for which events should be not send to the debug stream even when the HLT result is truncated - StringArrayProperty m_excludeFromHltTruncationDebugStream; - /// Monitoring histogram for truncated HLT results - TH1F* m_hist_Hlt_truncated_result{0}; + /// Send an HLT result to the DataCollector + void eventDone(std::unique_ptr<uint32_t[]> hltResult) const; - /// we need this maintain the data - uint32_t m_status_words[3] = {0}; + /// The method executed by the event timeout monitoring thread + void runEventTimer(); - EventContext m_eventContext; -}; + // ------------------------- Reimplemented AthenaHiveEventLoopMgr helpers ---- + /// Create event context + StatusCode createEventContext(EventContext*& eventContext) const; -//========================================================================= -inline StatusCode HltEventLoopMgr::start() -{ - // This method might be called by ServiceManager::start and does nothing. - // The real start method is prepareForRun and invoked by the PSC. - return StatusCode::SUCCESS; -} + /// Drain the scheduler from all actions that may be queued + int drainScheduler(); -//========================================================================= -inline void -HltEventLoopMgr::HltSetPscError(hltinterface::HLTResult& hlt_result, - hltonl::PSCErrorCode pscErrorCode) const -{ - hlt_result.psc_errors.push_back(pscErrorCode); + /// Clear an event slot in the whiteboard + StatusCode clearWBSlot(int evtSlot) const; + + // ------------------------- Handles to required services/tools -------------- + ServiceHandle<IIncidentSvc> m_incidentSvc; + ServiceHandle<StoreGateSvc> m_evtStore; + ServiceHandle<StoreGateSvc> m_detectorStore; + ServiceHandle<StoreGateSvc> m_inputMetaDataStore; + ServiceHandle<IROBDataProviderSvc> m_robDataProviderSvc; + ServiceHandle<ITHistSvc> m_THistSvc; + ServiceHandle<IEvtSelector> m_evtSelector; + ServiceHandle<IConversionSvc> m_outputCnvSvc; + + /// Reference to the Whiteboard interface + SmartIF<IHiveWhiteBoard> m_whiteboard; + /// Reference to the Algorithm resource pool + SmartIF<IAlgResourcePool> m_algResourcePool; + /// Reference to the Algorithm Execution State Svc + SmartIF<IAlgExecStateSvc> m_aess; + /// A shortcut for the scheduler + SmartIF<IScheduler> m_schedulerSvc; + + /// Helper tool for COOL updates + ToolHandle<TrigCOOLUpdateHelper> m_coolHelper; + + /// Tool to create HLTResult + ToolHandle<HLT::ResultBuilderMT> m_hltResultBuilder; + + /// EventInfo -> xAOD::EventInfo conversion tool + ToolHandle<xAODMaker::IEventInfoCnvTool> m_eventInfoCnvTool; + + // ------------------------- Optional services/tools ------------------------- + /// Reference to a THistSvc which implements also the Hlt additions + SmartIF<IHltTHistSvc> m_hltTHistSvc; + /// Reference to a ROBDataProviderSvc which implements also the Hlt additions + SmartIF<ITrigROBDataProviderSvc> m_hltROBDataProviderSvc; + + // ------------------------- Properties -------------------------------------- + /// Application Name (="None" or "athenaHLT" for simulated data, "HLTMPPU-xx"? in online environment) + StringProperty m_applicationName; + /// Partition Name (="None" for offline, real partion name in online environment) + StringProperty m_partitionName; + /// JobOptions type (="NONE" or "DB", same as in PSC) + StringProperty m_jobOptionsType; + /// Name of the scheduler to be used + StringProperty m_schedulerName; + /// Name of the Whiteboard to be used + StringProperty m_whiteboardName; + /// Vector of top level algorithm names + Gaudi::Property<std::vector<std::string> > m_topAlgNames; + + /// list of all enabled ROBs which can be retrieved + SimpleProperty<std::vector<uint32_t> > m_enabledROBs; + /// list of all enabled Sub Detectors which can be retrieved + SimpleProperty<std::vector<uint32_t> > m_enabledSubDetectors; + + /// Hard event processing timeout + FloatProperty m_hardTimeout; + /// Hard event processing timeout + FloatProperty m_softTimeoutFraction; + + /// StoreGate key for xAOD::EventInfo WriteHandle (needed for manual conversion from old EventInfo) + SG::WriteHandleKey<xAOD::EventInfo> m_xEventInfoWHKey; + + // ------------------------- Other private members --------------------------- + /// typedef used for detector mask fields + typedef EventID::number_type numt; + /** + * Detector mask0,1,2,3 - bit field indicating which TTC zones have been built into the event, + * one bit per zone, 128 bit total, significance increases from first to last + */ + std::tuple<numt, numt, numt, numt> m_detector_mask; + + /// Current run number + EventID::number_type m_currentRun{0}; + /// Number of events which started processing + size_t m_nevt; + /// Current run number + int m_threadPoolSize; + + /// Event selector context + IEvtSelector::Context* m_evtSelContext; + + /// Vector of top level algorithms + std::vector<SmartIF<IAlgorithm> > m_topAlgList; + + /// Vector of event start-processing time stamps in each slot + std::vector<std::chrono::steady_clock::time_point> m_eventTimerStartPoint; + /// Vector of flags to tell if a slot is idle or processing + std::vector<bool> m_isSlotProcessing; // be aware of vector<bool> specialisation + /// Timeout mutex + std::mutex m_timeoutMutex; + /// Timeout condition variable + std::condition_variable m_timeoutCond; + /// Timeout thread + std::unique_ptr<std::thread> m_timeoutThread; + /// Soft timeout value + int m_softTimeoutValue; + /// Flag set to false if timer thread should be stopped + std::atomic<bool> m_runEventTimer; +}; + +//============================================================================== +inline bool HltEventLoopMgr::validPartition() const { + return (m_partitionName.value()!="None" && m_partitionName.value()!="NONE"); } #endif // TRIGSERVICES_HLTEVENTLOOPMGR_H diff --git a/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py b/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py index a23e44b44b7d34c0ee87a0518d9a406aa16663d0..9829367063c546023f1863e763f2db0c29390c08 100644 --- a/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py +++ b/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py @@ -87,8 +87,8 @@ def _setupCommonServices(): svcMgr += CoreDumpSvc() # Configure COOL update helper tool - from TrigServices.TrigServicesConfig import TrigCOOLUpdateHelper - _eventLoopMgr(svcMgr).CoolUpdateTool = TrigCOOLUpdateHelper() + # from TrigServices.TrigServicesConfig import TrigCOOLUpdateHelper + # _eventLoopMgr(svcMgr).CoolUpdateTool = TrigCOOLUpdateHelper() # Setup online THistSvc unless specifically configured otherwise if _Conf.useOnlineTHistSvc: diff --git a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonBegin.py b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonBegin.py index ab547b95b65e5f37b3e2dfb7e37ca5b60555ed6e..bddc77849fa2ad16e95f5e50c9fd4cea76687b9c 100644 --- a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonBegin.py +++ b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonBegin.py @@ -8,10 +8,10 @@ include( "TrigServices/MessageSvc.py" ) include( "TrigServices/TrigServicesEventLoopMgr.py" ) ## HLT standard service configuration -from TrigServices.TriggerUnixStandardSetup import setupHLTServicesBegin -setupHLTServicesBegin() +# from TrigServices.TriggerUnixStandardSetup import setupHLTServicesBegin +# setupHLTServicesBegin() ## clean-up: avoid running multiple times this method -del setupHLTServicesBegin +# del setupHLTServicesBegin #============================================================== # diff --git a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonEnd.py b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonEnd.py index dc98afa1a7abf99c39dfa4ce1e1672de1ff623ad..2cd3fa3055226dad589ffef020f348b06a80402a 100644 --- a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonEnd.py +++ b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonEnd.py @@ -5,13 +5,13 @@ #============================================================== ## get a handle on the ServiceMgr -from AthenaCommon.AppMgr import ServiceMgr as svcMgr +# from AthenaCommon.AppMgr import ServiceMgr as svcMgr ## HLT standard service configuration -from TrigServices.TriggerUnixStandardSetup import setupHLTServicesEnd -setupHLTServicesEnd() +# from TrigServices.TriggerUnixStandardSetup import setupHLTServicesEnd +# setupHLTServicesEnd() ## clean-up: avoid running multiple times this method -del setupHLTServicesEnd +# del setupHLTServicesEnd #============================================================== # # End of HLT common configuration file: TrigServicesCommonEnd.py diff --git a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesEventLoopMgr.py b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesEventLoopMgr.py index 17aac25c1038ace58536e9730fb257620600f4b0..5c35f23b170f2ec711f0db90b3d74eb092c56e45 100644 --- a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesEventLoopMgr.py +++ b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesEventLoopMgr.py @@ -3,25 +3,179 @@ # TrigServicesEventLoopMgr configuration file # #============================================================== +from AthenaCommon import CfgMgr from AthenaCommon.AppMgr import theApp from AthenaCommon.AppMgr import ServiceMgr as svcMgr -from AthenaCommon.Constants import * +from AthenaCommon.AppMgr import ToolSvc + +# from AthenaCommon.Constants import * + +# ============================================================================== +# Set up from StoreGateHiveExample.py and AthExHiveOpts.py and AtlasThreadedJob.py +# ============================================================================== +#nThreads = 1 +#numStores = 1 +#numAlgsInFlight = nThreads + +#from AthenaCommon.ConcurrencyFlags import jobproperties as jps +#jps.ConcurrencyFlags.NumThreads = nThreads +#jps.ConcurrencyFlags.NumConcurrentEvents = numStores + +# from GaudiCommonSvc.GaudiCommonSvcConf import AlgContextSvc +# svcMgr += AlgContextSvc("AlgContextSvc") +# svcMgr.AlgContextSvc.Check = True + +from StoreGate.StoreGateConf import SG__HiveMgrSvc +svcMgr += SG__HiveMgrSvc("EventDataSvc") +#svcMgr.EventDataSvc.NSlots = numStores +#svcMgr.EventDataSvc.OutputLevel = VERBOSE + +from GaudiHive.GaudiHiveConf import AlgResourcePool +arp=AlgResourcePool( OutputLevel = INFO ) +arp.TopAlg=["AthMasterSeq"] #this should enable control flow +svcMgr += arp + +from AthenaCommon.AlgScheduler import AlgScheduler +#AlgScheduler.setThreadPoolSize(nThreads) +AlgScheduler.ShowDataDependencies(True) +AlgScheduler.ShowControlFlow(True) +AlgScheduler.OutputLevel=VERBOSE + +from StoreGate.StoreGateConf import StoreGateSvc +svcMgr += StoreGateSvc() +svcMgr.StoreGateSvc.OutputLevel = VERBOSE +svcMgr.StoreGateSvc.Dump = True + +from StoreGate.StoreGateConf import SGImplSvc +svcMgr += SGImplSvc("SGImplSvc") +svcMgr.SGImplSvc.OutputLevel = VERBOSE + +# ThreadPoolService thread local initialization +from GaudiHive.GaudiHiveConf import ThreadPoolSvc +svcMgr += ThreadPoolSvc("ThreadPoolSvc") +svcMgr.ThreadPoolSvc.ThreadInitTools = ["ThreadInitTool"] + +from AthenaCommon.AlgSequence import AlgSequence +topSequence = AlgSequence() +#algCardinality = nThreads + +# if (algCardinality != 1): +# for alg in topSequence: +# name = alg.name() +# alg.Cardinality = algCardinality + +from SGComps.SGCompsConf import SGInputLoader +topSequence += SGInputLoader( FailIfNoProxy=False ) + +theAuditorSvc = svcMgr.AuditorSvc +theApp.AuditAlgorithms=True +from SGComps.SGCompsConf import SGCommitAuditor +theAuditorSvc += SGCommitAuditor() + +# for easier browsing of verbose logs +ClassIDSvc = Service("ClassIDSvc") +ClassIDSvc.OutputLevel = DEBUG + +# ============================================================================== +# Event selector and input service +# ============================================================================== +from TrigByteStreamCnvSvc.TrigByteStreamCnvSvcConf import TrigByteStreamInputSvc +inputSvc = TrigByteStreamInputSvc("ByteStreamInputSvc") +svcMgr += inputSvc + +from TrigByteStreamCnvSvc.TrigByteStreamCnvSvcConf import TrigEventSelectorByteStream +evtSel = TrigEventSelectorByteStream("EventSelector") +evtSel.ByteStreamInputSvc = inputSvc +svcMgr += evtSel +theApp.EvtSel = "EventSelector" + +# ============================================================================== +# Output conversion service +# ============================================================================== +from TrigByteStreamCnvSvc.TrigByteStreamCnvSvcConf import TrigByteStreamCnvSvc +outputCnvSvc = TrigByteStreamCnvSvc("TrigByteStreamCnvSvc") +svcMgr += outputCnvSvc + +# ============================================================================== +# Some extra services +# ============================================================================== +## basic Gaudi services from AtlasUnixStandardJob.py +import GaudiSvc.GaudiSvcConf as GaudiSvcConf +svcMgr += GaudiSvcConf.IncidentSvc() +svcMgr += GaudiSvcConf.EvtPersistencySvc( "EventPersistencySvc" ) +svcMgr += GaudiSvcConf.HistogramSvc( "HistogramDataSvc" ) +svcMgr += GaudiSvcConf.NTupleSvc() +svcMgr += GaudiSvcConf.ToolSvc() +svcMgr += GaudiSvcConf.RndmGenSvc() +svcMgr += GaudiSvcConf.ChronoStatSvc() + +##### + +from StoreGate.StoreGateConf import StoreGateSvc +svcMgr += StoreGateSvc("DetectorStore") + +# ProxyProviderSvc services configuration +svcMgr += CfgMgr.ProxyProviderSvc() + +# --- ByteStreamAddressProviderSvc configuration +svcMgr += CfgMgr.ByteStreamAddressProviderSvc() +svcMgr.ProxyProviderSvc.ProviderNames += [ "ByteStreamAddressProviderSvc" ] +#theApp.CreateSvc += [ svcMgr.ByteStreamAddressProviderSvc.getFullName() ] + +# Initialization of DetDescrCnvSvc +svcMgr += CfgMgr.DetDescrCnvSvc( + # specify primary Identifier dictionary to be used + IdDictName = "IdDictParser/ATLAS_IDS.xml" + ) +theApp.CreateSvc += [ svcMgr.DetDescrCnvSvc.getFullName() ] +svcMgr.EventPersistencySvc.CnvServices += [ "DetDescrCnvSvc" ] + +# --- ByteStreamCnvSvc configuration +svcMgr += CfgMgr.ByteStreamCnvSvc("ByteStreamCnvSvc") +svcMgr.EventPersistencySvc.CnvServices += [ "ByteStreamCnvSvc" ] + +# dictionary services from AtlasUnixStandardJob.py +# the dict loader +import AthenaServices.AthenaServicesConf as AthenaServicesConf +if not hasattr(svcMgr, 'AthDictLoaderSvc'): + svcMgr += AthenaServicesConf.AthDictLoaderSvc() +theApp.CreateSvc += [svcMgr.AthDictLoaderSvc.getFullJobOptName()] + +# the dict checker +if not hasattr(svcMgr, 'AthenaSealSvc'): + svcMgr += AthenaServicesConf.AthenaSealSvc() +theApp.CreateSvc += [svcMgr.AthenaSealSvc.getFullJobOptName()] + +# ============================================================================== +# Message format +# ============================================================================== +msgFmt = "% F%40W%S %4W%e%s %7W%R %T %0W%M" +svcMgr.MessageSvc.Format = msgFmt + +# ============================================================================== +# General setup +# ============================================================================== # make the HltEventLoopMgr service available svcMgr.HltEventLoopMgr = theApp.service( "HltEventLoopMgr" ) # already instantiated HltEventLoopMgr = svcMgr.HltEventLoopMgr +HltEventLoopMgr.WhiteboardSvc = "EventDataSvc" +HltEventLoopMgr.SchedulerSvc = AlgScheduler.getScheduler().getName() +HltEventLoopMgr.EvtSel = evtSel +HltEventLoopMgr.OutputCnvSvc = outputCnvSvc + # configure here Level-1 CTP ROB identifier which is used in HLT -HltEventLoopMgr.Lvl1CTPROBid = 0x770001 +# HltEventLoopMgr.Lvl1CTPROBid = 0x770001 # request that events with invalid or missing CTP ROBs are skipped by the HltEventLoopMgr # (default: don't skip these events) -HltEventLoopMgr.Lvl1CTPROBcheck = TRUE +# HltEventLoopMgr.Lvl1CTPROBcheck = TRUE # # name of the HLT Result object in StoreGate # -HltEventLoopMgr.HltResultName = "HLTResult_HLT" +# HltEventLoopMgr.HltResultName = "HLTResult_HLT" # # handling of truncated HLT Results @@ -32,47 +186,44 @@ HltEventLoopMgr.HltResultName = "HLTResult_HLT" #HltEventLoopMgr.HltTruncationDebugStreamName = "TruncatedHLTResult" # list of stream names which should not be send to the truncation DEBUG stream (default ["CostMonitoring"]) -HltEventLoopMgr.ExcludeFromHltTruncationDebugStream = ["CostMonitoring"] +# HltEventLoopMgr.ExcludeFromHltTruncationDebugStream = ["CostMonitoring"] # # properties for the HLT result size histograms # --> set upper edge of histogram to maximum allowed number of words in HLT # -# HltEventLoopMgr.histHltResultSize=("HltResultSize",0,500000,100) -# HltEventLoopMgr.histHltResultSizePhysics=("HltResultSize-(Stream (Main_physics))",0,500000,100) -# HltEventLoopMgr.histHltResultSizeExpress=("HltResultSize-(Stream (express_express))",0,250000,100) -# HltEventLoopMgr.histHltResultSizeDS=("HltResultSize-(Streams (DataScouting_*_calibration))",0,125000,100) +# HltEventLoopMgr.histHltResultSize=("HltResultSize",0,125000,100) # # Configuration of EDM size monitoring plots # -try: - from TrigEDMConfig.TriggerEDM import EDMDetails,getTypeAndKey,keyToLabel - from TrigEDMConfig.TriggerEDM import TriggerHLTList - - # TODO update to use import TriggerHLTList directly - #from TrigEDMConfig.TriggerEDM import TriggerL2List,TriggerEFList - #TriggerHLTList = list(set(TriggerL2List).union(TriggerEFList)) - - l = [] - for item in TriggerHLTList: - if ('BS' in item[1].split()) or ('DS' in item[1].split()): - t,k = getTypeAndKey(item[0]) - ctype = t - if EDMDetails[t].has_key('collection'): - ctype = EDMDetails[t]['collection'] - l += [ctype+'__'+keyToLabel(k)] - # add a bin for not accounted collections - l += ['not__configured'] - - HltEventLoopMgr.HltEDMCollectionNames = l - number_of_collections=len( HltEventLoopMgr.HltEDMCollectionNames ) - HltEventLoopMgr.histHltEdmSizes=("HltEDMSizes",0., 15000., number_of_collections) -except ImportError,e: - print " +----------------------------------------------------------------------+ " - print " | No initial configuration for EDM monitoring plots will be available! | " - print " +----------------------------------------------------------------------+ " - print e +# try: + # from TrigEDMConfig.TriggerEDM import EDMDetails,getTypeAndKey,keyToLabel + # from TrigEDMConfig.TriggerEDM import TriggerHLTList + # + # # TODO update to use import TriggerHLTList directly + # #from TrigEDMConfig.TriggerEDM import TriggerL2List,TriggerEFList + # #TriggerHLTList = list(set(TriggerL2List).union(TriggerEFList)) + # + # l = [] + # for item in TriggerHLTList: + # if ('BS' in item[1].split()) or ('DS' in item[1].split()): + # t,k = getTypeAndKey(item[0]) + # ctype = t + # if EDMDetails[t].has_key('collection'): + # ctype = EDMDetails[t]['collection'] + # l += [ctype+'__'+keyToLabel(k)] + # # add a bin for not accounted collections + # l += ['not__configured'] +# + # HltEventLoopMgr.HltEDMCollectionNames = l + # number_of_collections=len( HltEventLoopMgr.HltEDMCollectionNames ) + # HltEventLoopMgr.histHltEdmSizes=("HltEDMSizes",0., 15000., number_of_collections) +# except ImportError,e: + # print " +----------------------------------------------------------------------+ " + # print " | No initial configuration for EDM monitoring plots will be available! | " + # print " +----------------------------------------------------------------------+ " + # print e #============================================================== # # End of TrigServicesEventLoopMgr configuration file diff --git a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx index 8fb7371777cf078249488c6b5ccdad919204c9bc..39836737a2d16024b4b45e6a205cc9878248383c 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx +++ b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx @@ -2,2504 +2,944 @@ Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration */ -// Gaudi includes -#include "GaudiKernel/IAlgorithm.h" -#include "GaudiKernel/Incident.h" -#include "GaudiKernel/IIncidentSvc.h" -#include "GaudiKernel/IEvtSelector.h" -#include "GaudiKernel/IJobOptionsSvc.h" -#include "GaudiKernel/ITHistSvc.h" -#include "GaudiKernel/Timing.h" -#include "GaudiKernel/IAlgContextSvc.h" -#include "GaudiKernel/IAlgExecStateSvc.h" -#include "GaudiKernel/IAlgManager.h" -#include "GaudiKernel/ServiceLocatorHelper.h" -#include "GaudiKernel/SmartIF.h" -#include "GaudiKernel/EventContext.h" - -// Athena includes -#include "AthenaKernel/ExtendedEventContext.h" -#include "AthenaKernel/EventContextClid.h" -#include "StoreGate/StoreGateSvc.h" -#include "EventInfo/EventIncident.h" -#include "EventInfo/EventInfo.h" -#include "EventInfo/EventType.h" -#include "xAODEventInfo/EventAuxInfo.h" -#include "ByteStreamData/ByteStreamMetadata.h" -#include "ByteStreamCnvSvcBase/IROBDataProviderSvc.h" -#include "AthenaPoolUtilities/CondAttrListCollection.h" -#include "CLIDSvc/CLASS_DEF.h" - -// omni redefines this macro, so we save it -namespace { -static std::string CMT_PACKAGE_VERSION = PACKAGE_VERSION; -} - // Trigger includes #include "TrigServices/HltEventLoopMgr.h" -#include "TrigServices/TrigISHelper.h" -#include "TrigServices/TrigHLTIssues.h" #include "TrigCOOLUpdateHelper.h" +#include "TrigKernel/HltExceptions.h" #include "TrigSORFromPtreeHelper.h" -#include "TrigConfInterfaces/IHLTConfigSvc.h" -#include "TrigInterfaces/Incidents.h" -#include "TrigMonitorBase/TrigLockedHist.h" -#include "TrigKernel/HltAcceptFlag.h" -#include "TrigKernel/HltResultStatusCode.h" -#include "TrigKernel/HltExtraStatusCode.h" -#include "TrigKernel/IHltTHistSvc.h" #include "TrigSteeringEvent/HLTResult.h" +#include "TrigSteeringEvent/HLTResultMT.h" + +// Athena includes +#include "AthenaKernel/EventContextClid.h" +#include "ByteStreamCnvSvcBase/IROBDataProviderSvc.h" +#include "ByteStreamData/ByteStreamMetadata.h" +#include "EventInfo/EventInfo.h" +#include "StoreGate/StoreGateSvc.h" +#include "xAODEventInfo/EventInfo.h" +#include "xAODEventInfo/EventAuxInfo.h" #include "TrigSteeringEvent/HLTExtraData.h" -#include "TrigNavigation/TrigEDMSizes.h" + +// Gaudi includes +#include "GaudiKernel/EventIDBase.h" +#include "GaudiKernel/ConcurrencyFlags.h" +#include "GaudiKernel/IAlgExecStateSvc.h" +#include "GaudiKernel/IAlgManager.h" +#include "GaudiKernel/IAlgorithm.h" +#include "GaudiKernel/IAlgResourcePool.h" +#include "GaudiKernel/IConversionSvc.h" +#include "GaudiKernel/IEvtSelector.h" +#include "GaudiKernel/IHiveWhiteBoard.h" +#include "GaudiKernel/IJobOptionsSvc.h" +#include "GaudiKernel/IProperty.h" +#include "GaudiKernel/IScheduler.h" +#include "GaudiKernel/ITHistSvc.h" +#include "GaudiKernel/ThreadLocalContext.h" // TDAQ includes -#include "ers/ers.h" -#include "eformat/eformat.h" -#include "eformat/write/ROBFragment.h" -#include "TTCInfo/LumiBlock.h" -#include "ddc/DdcFloatInfoNamed.h" -#include "hltinterface/HLTInterface.h" -#include "hltinterface/EventId.h" -#include "hltinterface/HLTResult.h" -#include "CTPfragment/CTPfragment.h" -#include "CTPfragment/CTPExtraWordsFormat.h" -#include "CTPfragment/Issue.h" - -// ROOT includes -#include "TH1F.h" -#include "TH2I.h" -#include "TProfile.h" -#include "TClass.h" - -// Other includes -#include <set> -#include <string> -#include <algorithm> -#include <ctime> -#include <mutex> -#include <sys/types.h> -#include <unistd.h> -#include <stdlib.h> -#include <boost/property_tree/ptree.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/lexical_cast.hpp> - -#undef PACKAGE_VERSION // use the CMT_PACKAGE_VERSION std::string instead +#include "eformat/StreamTag.h" +#include "hltinterface/DataCollector.h" +#include "owl/time.h" + +// System includes +#include <sstream> #define ST_WHERE "HltEventLoopMgr::" << __func__ << "(): " using namespace boost::property_tree; -using std::string; -using std::function; -using std::begin; -using std::end; using SOR = TrigSORFromPtreeHelper::SOR; -namespace -{ - //========================================================================= - const eformat::helper::Status SW_UNCLASSIFIED(eformat::UNCLASSIFIED, 0), - SW_FAIL(eformat::DATA_CORRUPTION, 0), - SW_TRUNCATION(eformat::INTERNAL_OVERFLOW, 0); - constexpr unsigned - INITIAL_ROB_SIZE_MARGIN = 4; /* margin for the rob size, to account for - possible additional status words that may - still be unknonw */ - - //========================================================================= - constexpr std::array<uint32_t, 7> L1R_MANDATORY_ROBS = - {{ - 0x7300a8, 0x7300a9, 0x7300aa, 0x7300ab, // TDAQ_CALO_CLUSTER_PROC_ROI ROBs - 0x7500ac, 0x7500ad, // TDAQ_CALO_JET_PROC_ROI ROBs - 0x760001 // TDAQ_MUON_CTP_INTERFACE ROB - }}; // default list of IDs of ROBs that must come in the L1R from the RoIB - - //========================================================================= - constexpr std::array<uint32_t, 12> L1R_SKIP_ROB_CHECK = - {{ - 0x7300a8, 0x7300a9, 0x7300aa, 0x7300ab, // TDAQ_CALO_CLUSTER_PROC_ROI ROBs - 0x7500ac, 0x7500ad, // TDAQ_CALO_JET_PROC_ROI ROBs - 0x760001, // TDAQ_MUON_CTP_INTERFACE ROB - 0x770001, // TDAQ_CTP ROB - 0x910081, 0x910091, 0x910082, 0x910092 // TDAQ_CALO_TOPO_PROC ROBs - }}; //concrete IDs still unknown for TDAQ_FTK and TDAQ_CALO_FEAT_EXTRACT_ROI - - //========================================================================= - constexpr std::array<eformat::SubDetector, 7> L1R_SKIP_SD_CHECK = - {{ - eformat::TDAQ_CALO_CLUSTER_PROC_ROI, - eformat::TDAQ_CALO_JET_PROC_ROI, - eformat::TDAQ_HLT, - eformat::TDAQ_FTK, - eformat::TDAQ_CALO_TOPO_PROC, - eformat::TDAQ_CALO_DIGITAL_PROC, - eformat::TDAQ_CALO_FEAT_EXTRACT_ROI - }}; - - //========================================================================= - constexpr std::array<eformat::SubDetector, 8> L1R_BINS = - {{ - eformat::TDAQ_CALO_CLUSTER_PROC_ROI, - eformat::TDAQ_CALO_JET_PROC_ROI, - eformat::TDAQ_MUON_CTP_INTERFACE, - eformat::TDAQ_CTP, - eformat::TDAQ_FTK, - eformat::TDAQ_CALO_TOPO_PROC, - eformat::TDAQ_CALO_DIGITAL_PROC, - eformat::TDAQ_CALO_FEAT_EXTRACT_ROI - }}; - - //========================================================================= - constexpr const char * UNEXPECTED_L1R_ROB_LABEL = "Unexpected_ROB"; - constexpr const char * MISSING_L1R_CTP_LABEL = "Missing_CTP_Fragment"; - - //========================================================================= - std::mutex timeout_mutex; // To synchronize main and time out threads - - //========================================================================= - bool skipEnabledCheck(eformat::SubDetector sd) - { - // Skip check for HLT Result ROBs (for DataScouting) - if (sd == eformat::TDAQ_HLT) return true; - - // Skip check for certain L1 input ROBs - return std::find(begin(L1R_SKIP_SD_CHECK), - end(L1R_SKIP_SD_CHECK), - sd) != end(L1R_SKIP_SD_CHECK); - } - - //========================================================================= - bool skipEnabledCheck(uint32_t robid) - { - // Skip check for HLT Result ROBs (for DataScouting) - if (eformat::helper::SourceIdentifier(robid).subdetector_id() == eformat::TDAQ_HLT) return true; - - // Skip check for certain L1 input ROBs - return std::find(begin(L1R_SKIP_ROB_CHECK), - end(L1R_SKIP_ROB_CHECK), - robid) != end(L1R_SKIP_ROB_CHECK); - } - - //========================================================================= - std::string - missingL1RobsMsg(const std::vector<uint32_t>& rob_ids) - { - std::ostringstream ost; - if(!rob_ids.empty()) - { - ost << "L1 result ROBs missing: "; - - ost << "0x" << std::hex << std::setfill('0') << std::setw(6); - std::copy(std::begin(rob_ids), - std::end(rob_ids) - 1, // leave one to avoid delimiter - std::ostream_iterator<uint32_t>{ost, ", 0x"}); - ost << rob_ids.back() << "."; // append without delimiter - } - - return ost.str(); - } - - //========================================================================= - void fillEdmHist(TProfile * hist, const std::string& colname, - const HLT::TrigEDMSizes::EDMObjectInfo& info) - { - if(hist) - hist->Fill(colname.c_str(), static_cast<double>(info.words)); - } - - //========================================================================= - void addDebugStreamTag(hltinterface::HLTResult& hlt_result, - const std::string& tagname) - { - hlt_result.stream_tag.emplace_back(tagname, eformat::DEBUG_TAG, false); - } - - //========================================================================= - std::unique_ptr<eformat::write::ROBFragment> - initRob(uint16_t modid, uint32_t rn, uint32_t l1id, uint32_t bcid, - uint32_t l1tt, uint32_t dett, uint32_t * status_words) - { - using namespace eformat; - using write::ROBFragment; - - auto src = helper::SourceIdentifier{TDAQ_HLT, modid}.code(); - auto robp = std::unique_ptr<ROBFragment>{ - new ROBFragment{src, rn, l1id, bcid, l1tt, dett, 0, 0, STATUS_FRONT}}; - - status_words[0] = SW_UNCLASSIFIED.code(); - status_words[1] = hltonl::NORMAL_HLT_RESULT; - status_words[2] = hltonl::PSC_ERROR_UNCLASSIFIED; - - robp->status(1, status_words); - robp->rod_status(1, status_words); - - return robp; - } - - //========================================================================= - // Class that resets a pointer upon destruction, locking given mutex - template <typename T, typename MUTEX> - class PtrResetter - { - public: - explicit PtrResetter(T*& ptr, MUTEX& mut) - : m_ptr{ptr} - , m_mut(mut) // cannot use uniform init due to gcc4.8 bug - {} - ~PtrResetter() // this is where the work happens - { - std::lock_guard<MUTEX>{m_mut}; - m_ptr = nullptr; - } - PtrResetter(const PtrResetter&) = delete; - PtrResetter operator=(const PtrResetter&) = delete; - // no need to delete move ops explicitly in this case - not generated - - private: - T*& m_ptr; - MUTEX& m_mut; - }; -} - - -//========================================================================= -// Standard Constructor -//========================================================================= -HltEventLoopMgr::HltEventLoopMgr(const std::string& nam, - ISvcLocator* svcLoc) -: MinimalEventLoopMgr(nam, svcLoc), - m_incidentSvc ( "IncidentSvc", nam ), - m_evtStore( "StoreGateSvc", nam ), - m_detectorStore( "DetectorStore", nam ), - m_inputMetaDataStore( "StoreGateSvc/InputMetaDataStore", nam ), - m_robDataProviderSvc( "ROBDataProviderSvc",nam ), - m_THistSvc( "THistSvc", nam ), - m_aess( "AlgExecStateSvc", nam), - m_isHelper( "TrigISHelper", this), - m_coolHelper( "TrigCOOLUpdateHelper", this), - m_sorTime_stamp(2,0), +// ============================================================================= +// Standard constructor +// ============================================================================= +HltEventLoopMgr::HltEventLoopMgr(const std::string& name, ISvcLocator* svcLoc) +: base_class(name, svcLoc), + m_incidentSvc("IncidentSvc", name), + m_evtStore("StoreGateSvc", name), + m_detectorStore("DetectorStore", name), + m_inputMetaDataStore("StoreGateSvc/InputMetaDataStore", name), + m_robDataProviderSvc("ROBDataProviderSvc", name), + m_THistSvc("THistSvc", name), + m_evtSelector("EvtSel", name), + m_outputCnvSvc("OutputCnvSvc", name), + m_coolHelper("TrigCOOLUpdateHelper", this), + m_hltResultBuilder("HLT::ResultBuilderMT/ResultBuilder", this), + m_eventInfoCnvTool("xAODMaker::EventInfoCnvTool/EventInfoCnvTool", this), m_detector_mask(0xffffffff, 0xffffffff, 0, 0), - m_l1_hltPrescaleUpdateLB(0xffffffff), - m_histProp_Hlt_result_size(Gaudi::Histo1DDef("HltResultSize",0,500000,100)), - m_histProp_Hlt_result_size_physics(Gaudi::Histo1DDef("HltResultSize-(Stream (Main_physics))",0,500000,100)), - m_histProp_Hlt_result_size_express(Gaudi::Histo1DDef("HltResultSize-(Stream (express_express))",0,250000,100)), - m_histProp_Hlt_result_size_DataScouting(Gaudi::Histo1DDef("HltResultSize-(Streams (DataScouting_*_calibration))",0,125000,100)), - m_histProp_numStreamTags(Gaudi::Histo1DDef("NumberOfStreamTags",-.5,19.5,20)), - m_histProp_streamTagNames(Gaudi::Histo1DDef("StreamTagNames",-.5,.5,1)), - m_histProp_num_partial_eb_robs(Gaudi::Histo1DDef("NumberROBsPartialEB",-.5,199.5,200)), - m_histProp_Hlt_Edm_Sizes(Gaudi::Histo1DDef("HltEDMSizes",0.,10000.,100)) + m_nevt(0), + m_threadPoolSize(-1), + m_evtSelContext(nullptr), + m_softTimeoutValue(10000), + m_runEventTimer(true) { - m_mandatoryL1ROBs.value() = {begin(L1R_MANDATORY_ROBS), end(L1R_MANDATORY_ROBS)}; + ATH_MSG_VERBOSE("start of " << __FUNCTION__); - // General properties for event loop managers - declareProperty("predefinedLumiBlock", m_predefinedLumiBlock=0); - declareProperty("Lvl1CTPROBid", m_lvl1CTPROBid=0x770001); + declareProperty("JobOptionsType", m_jobOptionsType="NONE"); declareProperty("ApplicationName", m_applicationName="None"); declareProperty("PartitionName", m_partitionName="None"); - declareProperty("setMagFieldFromPtree", m_setMagFieldFromPtree=false); declareProperty("enabledROBs", m_enabledROBs); declareProperty("enabledSubDetectors", m_enabledSubDetectors); - declareProperty("MandatoryL1ROBs", m_mandatoryL1ROBs, "List of mandatory ROB IDs coming from the RoIB (must come in L1R seed)"); - declareProperty("HltEDMCollectionNames", m_hltEdmCollectionNames, "Names of all HLT EDM Collections"); - declareProperty("JobOptionsType", m_jobOptionsType="NONE"); - declareProperty("doMonitoring", m_doMonitoring=true, "Produce framework monitoring histograms"); - declareProperty("histHltResultSize", m_histProp_Hlt_result_size, "Histogram for HLT result size in words (overall)"); - declareProperty("histHltResultSizePhysics", m_histProp_Hlt_result_size_physics, "Histogram for HLT result size in words for physics stream "); - declareProperty("histHltResultSizeExpress", m_histProp_Hlt_result_size_express, "Histogram for HLT result size in words for express stream "); - declareProperty("histHltResultSizeDS", m_histProp_Hlt_result_size_DataScouting, "Histogram for HLT result size in words for DataScouting stream "); - declareProperty("histNumberOfStreamTags", m_histProp_numStreamTags, "Histogram with number of stream tags"); - declareProperty("histStreamTagNames", m_histProp_streamTagNames,"Histogram with stream tag names"); - declareProperty("histNumberROBsPartialEB", m_histProp_num_partial_eb_robs, "Histogram with number of ROBs for PEB" ); - declareProperty("histHltEdmSizes", m_histProp_Hlt_Edm_Sizes, "Histogram with sizes of HLT EDM collections" ); - declareProperty("ForceHltReject", m_forceHltReject=false); - declareProperty("ForceHltAccept", m_forceHltAccept=false); - declareProperty("HltResultName", m_HltResultName="HLTResult_HLT"); - declareProperty("HltDebugStreamName", m_HltDebugStreamName ="HLTMissingData"); - declareProperty("HltForcedStreamName", m_HltForcedStreamName ="HLTEventAcceptForced"); + declareProperty("EvtSel", m_evtSelector); + declareProperty("OutputCnvSvc", m_outputCnvSvc); declareProperty("CoolUpdateTool", m_coolHelper); - declareProperty("maxPrepareForRunSleepSec", m_prepareForRunSleep = 0, "Max number of seconds to sleep at the beginning of prepareForRun"); - declareProperty("Lvl1CTPROBcheck", m_lvl1CTPROBcheck=true); - declareProperty("WriteTruncatedHLTtoDebug", m_writeHltTruncationToDebug=true); - declareProperty("HltTruncationDebugStreamName", m_HltTruncationDebugStreamName ="TruncatedHLTResult"); - declareProperty("ExcludeFromHltTruncationDebugStream", m_excludeFromHltTruncationDebugStream ); + declareProperty("ResultBuilder", m_hltResultBuilder); + declareProperty("EventInfoCnvTool", m_eventInfoCnvTool); + declareProperty("SchedulerSvc", m_schedulerName="AvalancheSchedulerSvc", + "Name of the scheduler to be used"); + declareProperty("WhiteboardSvc", m_whiteboardName="EventDataSvc", + "Name of the Whiteboard to be used"); + declareProperty("TopAlg", m_topAlgNames={}, + "List of top level algorithms names"); + declareProperty("xEventInfoWHKey", m_xEventInfoWHKey="EventInfo"); + declareProperty("HardTimeout", m_hardTimeout=10*60*1000/*=10min*/, + "Hard event processing timeout in milliseconds"); + declareProperty("SoftTimeoutFraction", m_softTimeoutFraction=0.8, + "Fraction of the hard timeout to be set as the soft timeout"); + + ATH_MSG_VERBOSE("end of " << __FUNCTION__); } -//========================================================================= -// Standard Destructor -//========================================================================= +// ============================================================================= +// Standard destructor +// ============================================================================= HltEventLoopMgr::~HltEventLoopMgr() { } -//========================================================================= -// implementation of IInterface: queryInterface -//========================================================================= -StatusCode HltEventLoopMgr::queryInterface(const InterfaceID& riid, void** ppvInterface) -{ - if(!ppvInterface) - return StatusCode::FAILURE; - - if(ITrigEventLoopMgr::interfaceID().versionMatch(riid)) - *ppvInterface = static_cast<ITrigEventLoopMgr*>(this); - else - return MinimalEventLoopMgr::queryInterface(riid, ppvInterface); - - addRef(); - return StatusCode::SUCCESS; -} - -//========================================================================= -// implementation of IService::sysInitalize -//========================================================================= -StatusCode HltEventLoopMgr::sysInitialize() -{ - - // initialize the base class - StatusCode sc = MinimalEventLoopMgr::sysInitialize(); - sc.setChecked(); - return sc; -} - -void HltEventLoopMgr::updateDFProps() -{ - ServiceHandle<IJobOptionsSvc> p_jobOptionsSvc("JobOptionsSvc", name()); - if ((p_jobOptionsSvc.retrieve()).isFailure()) { - msgStream() << MSG::WARNING << "Could not find JobOptionsSvc to set " - << "DataFlow properties" << endmsg; - } else { - auto dfprops = p_jobOptionsSvc->getProperties("DataFlowConfig"); - - // Application name - auto pname = "DF_ApplicationName"; - const auto * prop = Gaudi::Utils::getProperty(dfprops, pname); - if(prop && m_applicationName.assign(*prop)) { - msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: " - << m_applicationName << endmsg; - } else { - msgStream() << MSG::WARNING << "Could not set Property '" << pname - << "' from DataFlow." << endmsg; - } - - // Partition name - pname = "DF_PartitionName"; - prop = Gaudi::Utils::getProperty(dfprops, pname); - if (prop && m_partitionName.assign(*prop)) { - msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: " - << m_partitionName << endmsg; - } else { - msgStream() << MSG::WARNING << "Could not set Property '" << pname - << "' from DataFlow." << endmsg; - } - - // get the list of enabled ROBs - pname = "DF_Enabled_ROB_IDs"; - prop = Gaudi::Utils::getProperty(dfprops, pname); - if (prop && m_enabledROBs.assign(*prop)) { - msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: " - << m_enabledROBs.value().size() << " enabled ROB IDs." - << endmsg; - } else { - // this is only info, because it is normal in athenaHLT - msgStream() << MSG::INFO << "Could not set Property '" << pname - << "' from DataFlow." << endmsg; - } - - // get the list of enabled Sub Detectors - pname = "DF_Enabled_SubDet_IDs"; - prop = Gaudi::Utils::getProperty(dfprops, pname); - if (prop && m_enabledSubDetectors.assign(*prop)) { - msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: " - << m_enabledSubDetectors.value().size() - << " enabled Sub Detector IDs." << endmsg; - } else { - // this is only info, because it is normal in athenaHLT - msgStream() << MSG::INFO << "Could not set Property '" - << pname << "' from DataFlow." << endmsg; - } - } - - p_jobOptionsSvc.release().ignore(); -} - -//========================================================================= -// implementation of IService::initalize -//========================================================================= +// ============================================================================= +// Reimplementation of AthService::initalize (IStateful interface) +// ============================================================================= StatusCode HltEventLoopMgr::initialize() { - // initialize the base class - StatusCode sc = MinimalEventLoopMgr::initialize(); + ATH_MSG_VERBOSE("start of " << __FUNCTION__); - // leave this after initialization of base class, otherwise msgSvc is not correctly set up - // ----- - msgStream() << MSG::INFO << " ---> HltEventLoopMgr = " << name() << " initialize " - << " - package version " << CMT_PACKAGE_VERSION << endmsg ; - if (sc.isFailure()) { - msgStream() << MSG::ERROR << "Failed to initialize base class MinimalEventLoopMgr" << endmsg; - return sc; - } + ATH_MSG_INFO(" ---> HltEventLoopMgr = " << name() << " initialize - package version " << PACKAGE_VERSION); + //---------------------------------------------------------------------------- + // Setup properties + //---------------------------------------------------------------------------- + + // read DataFlow configuration properties updateDFProps(); // JobOptions type - SmartIF<IProperty> propMgr ( Gaudi::createApplicationMgr() ); - if( propMgr.isValid() ) { + SmartIF<IProperty> propMgr = serviceLocator()->service<IProperty>("ApplicationMgr"); + if (propMgr.isValid()) { try { if (m_jobOptionsType.assign( propMgr->getProperty("JobOptionsType") )) - msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: " << m_jobOptionsType << endmsg; + ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: " << m_jobOptionsType); } catch (...) { - msgStream() << MSG::WARNING << "Could not set Property '" << m_jobOptionsType.name() << "' from DataFlow." << endmsg; + ATH_MSG_WARNING("Could not set Property '" << m_jobOptionsType.name() << "' from DataFlow"); + } + + if ( m_topAlgNames.value().empty() ) { + if (setProperty(propMgr->getProperty("TopAlg")).isFailure()) { + ATH_MSG_WARNING("Could not set the TopAlg property from ApplicationMgr"); + } } } else { - msgStream() << MSG::WARNING << "Error retrieving IProperty interface of ApplicationMgr" << endmsg; + ATH_MSG_WARNING("Error retrieving IProperty interface of ApplicationMgr" ); } - // print properties - msgStream() << MSG::INFO << " ---> predefinedLumiBlock = " << m_predefinedLumiBlock << endmsg ; - msgStream() << MSG::INFO << " ---> Lvl1 CTP ROB Id = " << m_lvl1CTPROBid - << " SourceID in hex = 0x" << MSG::hex << m_lvl1CTPROBid.value() << MSG::dec << endmsg ; - msgStream() << MSG::INFO << " ---> ApplicationName = " << m_applicationName << endmsg ; - msgStream() << MSG::INFO << " ---> PartitionName = " << m_partitionName << endmsg ; - msgStream() << MSG::INFO << " ---> JobOptionsType = " << m_jobOptionsType << endmsg ; - - msgStream() << MSG::INFO << " ---> Enabled ROBs: size = " - << m_enabledROBs.value().size(); - if (m_enabledROBs.value().size() == 0) - { - msgStream() << MSG::INFO << ". No check will be performed "; + // get JobOptionsSvc to read the configuration of NumConcurrentEvents and NumThreads + ServiceHandle<IJobOptionsSvc> jobOptionsSvc("JobOptionsSvc", name()); + if ((jobOptionsSvc.retrieve()).isFailure()) { + ATH_MSG_WARNING("Could not find JobOptionsSvc to read configuration"); } - msgStream() << endmsg; - msgStream() << MSG::INFO << " ---> Enabled Sub Detectors: size = " - << m_enabledSubDetectors.value().size(); - if (m_enabledSubDetectors.value().size() == 0) - { - msgStream() << ". No check will be performed " << endmsg; - } - msgStream() << endmsg; - - msgStream() << MSG::INFO << " ---> Fill monitoring histograms = " << m_doMonitoring << endmsg ; - msgStream() << MSG::INFO << " ---> Hist: histHltResultSize (overall) = " << m_histProp_Hlt_result_size << endmsg ; - msgStream() << MSG::INFO << " ---> Hist: histHltResultSize (physics) = " << m_histProp_Hlt_result_size_physics << endmsg ; - msgStream() << MSG::INFO << " ---> Hist: histHltResultSize (express) = " << m_histProp_Hlt_result_size_express << endmsg ; - msgStream() << MSG::INFO << " ---> Hist: histHltResultSize (DataScouting) = " << m_histProp_Hlt_result_size_DataScouting << endmsg ; - msgStream() << MSG::INFO << " ---> Hist: histNumberOfStreamTags = " << m_histProp_numStreamTags << endmsg ; - msgStream() << MSG::INFO << " ---> Hist: histStreamTagNames = " << m_histProp_streamTagNames << endmsg ; - msgStream() << MSG::INFO << " ---> Hist: histNumberROBsPartialEB = " << m_histProp_num_partial_eb_robs << endmsg ; - msgStream() << MSG::INFO << " ---> Hist: histHltEdmSizes = " << m_histProp_Hlt_Edm_Sizes << endmsg; - msgStream() << MSG::INFO << " ---> HLT EDM Collection Names = " << m_hltEdmCollectionNames << endmsg; - msgStream() << MSG::INFO << " ---> HltResult SG key = " << m_HltResultName << endmsg ; - msgStream() << MSG::INFO << " ---> HLT debug stream name = " << m_HltDebugStreamName << endmsg ; - msgStream() << MSG::INFO << " ---> HLT stream for forced events = " << m_HltForcedStreamName << endmsg ; - msgStream() << MSG::INFO << " ---> ForceHltReject = " << m_forceHltReject << endmsg ; - msgStream() << MSG::INFO << " ---> ForceHltAccept = " << m_forceHltAccept << endmsg; - - if (m_forceHltReject.value()) { - msgStream() << MSG::INFO << " +------------------------------------------+ " << endmsg ; - msgStream() << MSG::INFO << " | >>> ForceHltReject is enabled ! <<< | " << endmsg ; - msgStream() << MSG::INFO << " | It takes precedence over ForceHltAccept | " << endmsg ; - msgStream() << MSG::INFO << " +------------------------------------------+ " << endmsg ; + // print properties + ATH_MSG_INFO(" ---> ApplicationName = " << m_applicationName); + ATH_MSG_INFO(" ---> PartitionName = " << m_partitionName); + ATH_MSG_INFO(" ---> JobOptionsType = " << m_jobOptionsType); + ATH_MSG_INFO(" ---> HardTimeout = " << m_hardTimeout); + ATH_MSG_INFO(" ---> SoftTimeoutFraction = " << m_softTimeoutFraction); + if (jobOptionsSvc.isValid()) { + const Gaudi::Details::PropertyBase* prop = jobOptionsSvc->getClientProperty("EventDataSvc","NSlots"); + if (prop) + ATH_MSG_INFO(" ---> NumConcurrentEvents = " << *prop); + else + ATH_MSG_WARNING("Failed to retrieve the job property EventDataSvc.NSlots"); + prop = jobOptionsSvc->getClientProperty("AvalancheSchedulerSvc","ThreadPoolSize"); + if (prop) + ATH_MSG_INFO(" ---> NumThreads = " << *prop); + else + ATH_MSG_WARNING("Failed to retrieve the job property AvalancheSchedulerSvc.ThreadPoolSize"); + } + ATH_MSG_INFO(" ---> Enabled ROBs: size = " << m_enabledROBs.value().size() + << (m_enabledROBs.value().size()==0 ? ". No check will be performed" : " ")); + ATH_MSG_INFO(" ---> Enabled Sub Detectors: size = " << m_enabledSubDetectors.value().size() + << (m_enabledSubDetectors.value().size()==0 ? ". No check will be performed" : " ")); + + //---------------------------------------------------------------------------- + // Create and initialise the top level algorithms + //---------------------------------------------------------------------------- + SmartIF<IAlgManager> algMgr = serviceLocator()->as<IAlgManager>(); + if (!algMgr.isValid()) { + ATH_MSG_FATAL("Failed to retrieve AlgManager - cannot initialise top level algorithms"); + return StatusCode::FAILURE; } - - msgStream() << MSG::INFO << " ---> Write events with truncated HLT result to debug stream = " << m_writeHltTruncationToDebug << endmsg; - msgStream() << MSG::INFO << " ---> Debug stream name for events with truncated HLT result = " << m_HltTruncationDebugStreamName << endmsg; - msgStream() << MSG::INFO << " ---> Stream names of events with a truncated HLT result which will not be send to the debug stream = " << m_excludeFromHltTruncationDebugStream << endmsg; - - //------------------------------------------------------------------------- - // Setup the StoreGateSvc - //------------------------------------------------------------------------- - sc = m_evtStore.retrieve(); - if(sc.isFailure()) - { - msgStream() << MSG::FATAL << "Error retrieving StoreGateSvc "+m_evtStore << endmsg; - return sc; + std::vector<SmartIF<IAlgorithm>> topAlgList; + topAlgList.reserve(m_topAlgNames.value().size()); + for (const auto& it : m_topAlgNames.value()) { + Gaudi::Utils::TypeNameString item{it}; + std::string item_name = item.name(); + SmartIF<IAlgorithm> alg = algMgr->algorithm(item_name, /*createIf=*/ false); + if (alg.isValid()) { + ATH_MSG_DEBUG("Top Algorithm " << item_name << " already exists"); + } + else { + ATH_MSG_DEBUG("Creating Top Algorithm " << item.type() << " with name " << item_name); + IAlgorithm* ialg = nullptr; + ATH_CHECK(algMgr->createAlgorithm(item.type(), item_name, ialg)); + alg = ialg; // manage reference counting + } + m_topAlgList.push_back(alg); } - //------------------------------------------------------------------------- - // Setup the DetectorStore - //------------------------------------------------------------------------- - sc = m_detectorStore.retrieve(); - if(sc.isFailure()) - { - msgStream() << MSG::FATAL << "Error retrieving DetectorStore "+m_detectorStore << endmsg; - return sc; + for (auto& ita : m_topAlgList) { + ATH_CHECK(ita->sysInitialize()); } - //------------------------------------------------------------------------- - // Setup the InputMetaDataStore - //------------------------------------------------------------------------- - sc = m_inputMetaDataStore.retrieve(); - if(sc.isFailure()) - { - msgStream() << MSG::FATAL << "Error retrieving InputMetaDataStore"+m_inputMetaDataStore << endmsg; - return sc; + //---------------------------------------------------------------------------- + // Setup stuff for hive - taken from AthenaHiveEventLoopMgr + //---------------------------------------------------------------------------- + m_whiteboard = serviceLocator()->service(m_whiteboardName); + if( !m_whiteboard.isValid() ) { + ATH_MSG_FATAL("Error retrieving " << m_whiteboardName << " interface IHiveWhiteBoard"); + return StatusCode::FAILURE; } + ATH_MSG_DEBUG("Initialised " << m_whiteboardName << " interface IHiveWhiteBoard"); - //-------------------------------------------------------------------------- - // Setup the IncidentSvc - //-------------------------------------------------------------------------- - sc = m_incidentSvc.retrieve(); - if(sc.isFailure()) - { - msgStream() << MSG::FATAL << "Error retrieving IncidentSvc "+m_incidentSvc << endmsg; - return sc; + ATH_MSG_DEBUG("Commented out scheduler initialisation was here, now it's moved to hltUpdateAfterFork"); + /* + m_schedulerSvc = serviceLocator()->service(m_schedulerName); + if ( !m_schedulerSvc.isValid()){ + ATH_MSG_FATAL("Error retrieving " << m_schedulerName << " interface ISchedulerSvc"); + return StatusCode::FAILURE; } - - //-------------------------------------------------------------------------- - // Setup the ROBDataProviderSvc - //-------------------------------------------------------------------------- - sc = m_robDataProviderSvc.retrieve(); - if(sc.isFailure()) - { - msgStream() << MSG::FATAL << "Error retrieving ROBDataProviderSvc "+m_robDataProviderSvc << endmsg; - return sc; + ATH_MSG_DEBUG("initialised " << m_schedulerName << " interface ISchedulerSvc"); + */ + m_algResourcePool = serviceLocator()->service("AlgResourcePool"); + if( !m_algResourcePool.isValid() ) { + ATH_MSG_FATAL("Error retrieving AlgResourcePool"); + return StatusCode::FAILURE; } + ATH_MSG_DEBUG("initialised AlgResourcePool"); - //-------------------------------------------------------------------------- - // Setup the Histogram Service - //-------------------------------------------------------------------------- - sc = m_THistSvc.retrieve(); - if(sc.isFailure()) - { - msgStream() << MSG::FATAL << "Error retrieving THistSvc "+m_THistSvc << endmsg; - return sc; + m_aess = serviceLocator()->service("AlgExecStateSvc"); + if( !m_aess.isValid() ) { + ATH_MSG_FATAL("Error retrieving AlgExecStateSvc"); + return StatusCode::FAILURE; } + ATH_MSG_DEBUG("initialised AlgExecStateSvc"); - ATH_CHECK(m_aess.retrieve()); - //-------------------------------------------------------------------------- - // Setup the TrigISHelper - //-------------------------------------------------------------------------- - sc = m_isHelper.retrieve(); - if(sc.isFailure()) - { - msgStream() << MSG::FATAL << "Error retrieving TrigISHelper "+m_isHelper << endmsg; - return sc; - } - sc = m_isHelper->setProperty(m_partitionName); - if(sc.isFailure()) - { - msgStream() << MSG::FATAL << "Error setting " << m_partitionName.name() - << " of " << m_isHelper << endmsg; - return sc; - } + //---------------------------------------------------------------------------- + // Setup the IncidentSvc + //---------------------------------------------------------------------------- + ATH_CHECK(m_incidentSvc.retrieve()); - //-------------------------------------------------------------------------- - // COOL helper - //-------------------------------------------------------------------------- - if (m_coolHelper.retrieve().isFailure()) { - msgStream() << MSG::FATAL << "Error retrieving" << m_coolHelper << endmsg; - return StatusCode::FAILURE; - } + //---------------------------------------------------------------------------- + // Setup the StoreGateSvc + //---------------------------------------------------------------------------- + ATH_CHECK(m_evtStore.retrieve()); - //-------------------------------------------------------------------------- - // Setup optional services/tools - //-------------------------------------------------------------------------- - if (service("AlgContextSvc", m_algContextSvc, /*createIf=*/ false).isFailure()) { - m_algContextSvc = 0; - msgStream() << MSG::DEBUG << "No AlgContextSvc available" << endmsg; - } + //---------------------------------------------------------------------------- + // Setup the DetectorStore + //---------------------------------------------------------------------------- + ATH_CHECK(m_detectorStore.retrieve()); - // The remainder of this method used to be in the L2/EF specialization + //---------------------------------------------------------------------------- + // Setup the InputMetaDataStore + //---------------------------------------------------------------------------- + ATH_CHECK(m_inputMetaDataStore.retrieve()); - // fill CTP ROB id vector - m_ctpRobIdVec.clear(); - if (m_lvl1CTPROBid.value() != 0) { - m_ctpRobIdVec.push_back( m_lvl1CTPROBid.value() ); - } + //---------------------------------------------------------------------------- + // Setup the ROBDataProviderSvc + //---------------------------------------------------------------------------- + ATH_CHECK(m_robDataProviderSvc.retrieve()); - // print properties - msgStream() << MSG::INFO << " ---> HltEventLoopMgr = " << name() << " special properties <--- " << endmsg ; - msgStream() << MSG::INFO << " ---> Lvl1 CTP ROB Id vec. = 0x" << MSG::hex << m_ctpRobIdVec[0] << MSG::dec - << " size of vector = " << m_ctpRobIdVec.size() << endmsg ; - msgStream() << MSG::INFO << " ---> Check for invalid CTP ROBs = " << m_lvl1CTPROBcheck << endmsg ; - -//------------------------------------------------------------------------- -// Reset counters -//------------------------------------------------------------------------- - m_total_evt = 0; - m_failed_evt = 0; - m_invalid_lvl1_result = 0; - m_invalid_hlt_result = 0; - m_truncated_hlt_result = 0; - m_truncated_hlt_result_to_debug = 0; - m_truncated_hlt_result_not_to_debug = 0; - -//-------------------------------------------------------------------------- -// Setup the HLT Histogram Service when configured -//-------------------------------------------------------------------------- + //---------------------------------------------------------------------------- + // Setup the Histogram Service + //---------------------------------------------------------------------------- + ATH_CHECK(m_THistSvc.retrieve()); + + //---------------------------------------------------------------------------- + // Setup the Event Selector + //---------------------------------------------------------------------------- + ATH_CHECK(m_evtSelector.retrieve()); + ATH_CHECK(m_evtSelector->createContext(m_evtSelContext)); + + //---------------------------------------------------------------------------- + // Setup the Output Conversion Service + //---------------------------------------------------------------------------- + ATH_CHECK(m_outputCnvSvc.retrieve()); + + //---------------------------------------------------------------------------- + // Setup the COOL helper + //---------------------------------------------------------------------------- + ATH_CHECK(m_coolHelper.retrieve()); + + //---------------------------------------------------------------------------- + // Setup the HLT result builder + //---------------------------------------------------------------------------- + ATH_CHECK(m_hltResultBuilder.retrieve()); + + //---------------------------------------------------------------------------- + // Setup the EventInfo conversion tool and WriteHandleKey + //---------------------------------------------------------------------------- + ATH_CHECK(m_eventInfoCnvTool.retrieve()); + ATH_CHECK(m_xEventInfoWHKey.initialize()); + + //---------------------------------------------------------------------------- + // Setup the HLT Histogram Service when configured + //---------------------------------------------------------------------------- if ( &*m_THistSvc ) { m_hltTHistSvc = SmartIF<IHltTHistSvc>( &*m_THistSvc ); - if (m_hltTHistSvc.isValid()) { - msgStream() << MSG::INFO << "A THistSvc implementing the HLT interface IHltTHistSvc was found." - << endmsg; - } else { - msgStream() << MSG::INFO << "No THistSvc implementing the HLT interface IHltTHistSvc was found." - << endmsg; - } + if (m_hltTHistSvc.isValid()) + ATH_MSG_INFO("A THistSvc implementing the HLT interface IHltTHistSvc was found"); + else + ATH_MSG_INFO("No THistSvc implementing the HLT interface IHltTHistSvc was found"); } -//-------------------------------------------------------------------------- -// Setup the HLT ROB Data Provider Service when configured -//-------------------------------------------------------------------------- + //---------------------------------------------------------------------------- + // Setup the HLT ROB Data Provider Service when configured + //---------------------------------------------------------------------------- if ( &*m_robDataProviderSvc ) { m_hltROBDataProviderSvc = SmartIF<ITrigROBDataProviderSvc>( &*m_robDataProviderSvc ); - if (m_hltROBDataProviderSvc.isValid()) { - msgStream() << MSG::INFO << "A ROBDataProviderSvc implementing the HLT interface ITrigROBDataProviderSvc was found." - << endmsg; - } else { - msgStream() << MSG::INFO << "No ROBDataProviderSvc implementing the HLT interface ITrigROBDataProviderSvc was found." - << endmsg; - } + if (m_hltROBDataProviderSvc.isValid()) + ATH_MSG_INFO("A ROBDataProviderSvc implementing the HLT interface ITrigROBDataProviderSvc was found"); + else + ATH_MSG_INFO("No ROBDataProviderSvc implementing the HLT interface ITrigROBDataProviderSvc was found"); } + ATH_MSG_VERBOSE("end of " << __FUNCTION__); return StatusCode::SUCCESS; } -//========================================================================= -// implementation of IService::sysFinalize -//========================================================================= -StatusCode HltEventLoopMgr::sysFinalize() -{ - // initialize the base class - StatusCode sc = MinimalEventLoopMgr::sysFinalize(); - sc.setChecked(); - return sc; -} - -//========================================================================= -// implementation of IService::finalize -//========================================================================= -StatusCode HltEventLoopMgr::finalize() -{ - MsgStream log(msgSvc(), name()); - log << MSG::INFO << " ---> HltEventLoopMgr = " << name() << " finalize " << endmsg; - log << MSG::INFO << " Total number of events processed : " << m_total_evt << endmsg; - log << MSG::INFO << " Events with error in event processing " << m_failed_evt << endmsg; - log << MSG::INFO << " Events with invalid Lvl1 Result " << m_invalid_lvl1_result << endmsg; - log << MSG::INFO << " Events with invalid Hlt Result " << m_invalid_hlt_result << endmsg; - log << MSG::INFO << " Events with truncated Hlt Result payload " << m_truncated_hlt_result << endmsg; - log << MSG::INFO << " Events with truncated Hlt Result payload (send to debug stream) " << m_truncated_hlt_result_to_debug << endmsg; - log << MSG::INFO << " Events with truncated Hlt Result payload (not send to debug stream) " << m_truncated_hlt_result_not_to_debug << endmsg; - - // Need to release now. Automatic release in destructor is too late since services are already gone. - m_hltTHistSvc.reset(); - m_hltROBDataProviderSvc.reset(); - - StatusCode sc = MinimalEventLoopMgr::finalize(); - if (sc.isFailure()) { - msgStream() << MSG::ERROR << "Error in MinimalEventLoopMgr Finalize" << endmsg; - } - - - // Release all interfaces - m_incidentSvc.release().ignore(); - m_robDataProviderSvc.release().ignore(); - m_evtStore.release().ignore(); - m_detectorStore.release().ignore(); - m_inputMetaDataStore.release().ignore(); - m_THistSvc.release().ignore(); - m_isHelper.release().ignore(); - - return sc; -} - -//========================================================================= -// implementation of IService::sysReinitialize -//========================================================================= -StatusCode HltEventLoopMgr::sysReinitialize() +// ============================================================================= +// Reimplementation of AthService::start (IStateful interface) +// ============================================================================= +StatusCode HltEventLoopMgr::start() { - // initialize the base class - StatusCode sc = MinimalEventLoopMgr::sysReinitialize(); - sc.setChecked(); - - return sc; -} + ATH_CHECK(AthService::start()); -//========================================================================= -// implementation of IService::reinitialize -//========================================================================= -StatusCode HltEventLoopMgr::reinitialize() -{ - MsgStream log(msgSvc(), name()); - log << MSG::INFO << " ---> HltEventLoopMgr = " << name() << " reinitialize " << endmsg; - -//------------------------------------------------------------------------- -// Reset counters -//------------------------------------------------------------------------- - m_total_evt = 0; - m_failed_evt = 0; - m_invalid_lvl1_result = 0; - m_invalid_hlt_result = 0; - m_truncated_hlt_result = 0; - m_truncated_hlt_result_to_debug = 0; - m_truncated_hlt_result_not_to_debug = 0; - - StatusCode sc = MinimalEventLoopMgr::reinitialize(); - if (sc.isFailure()) { - msgStream() << MSG::ERROR << "Error in MinimalEventLoopMgr Reinitialize" << endmsg; + // start top level algorithms + for (auto& ita : m_topAlgList) { + ATH_CHECK(ita->sysStart()); } - return sc; -} - -StatusCode HltEventLoopMgr::executeAlgorithms() -{ - // Reset all algorithms - m_aess->reset(m_eventContext); - - // Call the execute() method of all top algorithms - StatusCode sc; - for(auto alg : m_topAlgList) { - sc = alg->sysExecute(m_eventContext); - if(sc.isFailure()) { - msgStream() << MSG::ERROR << "Execution of algorithm " << alg->name() - << " failed" << endmsg; - return sc; - } - } return StatusCode::SUCCESS; } - -//========================================================================= -// implementation of IEventProcessor::executeEvent(void* par) ---> for "online" running -//========================================================================= -StatusCode HltEventLoopMgr::executeEvent(void* par) -{ - StatusCode sc; - if (msgLevel() <= MSG::DEBUG) { - msgStream() << MSG::DEBUG << " ---> HltEventLoopMgr = " << name() - << " executeEvent(par): par = 0x" << MSG::hex << par << MSG::dec << endmsg; - } - - { - std::lock_guard<std::mutex>{timeout_mutex}; - - resetTimeout(Athena::Timeout::instance()); - sc = m_evtStore->retrieve(m_currentEvent); - } - - if( sc.isFailure() ) { - msgStream() << MSG::ERROR << "Expected an EventInfo object." << endmsg; - return StatusCode::FAILURE; - } else { - const auto eventrn = m_currentEvent->event_ID()->run_number(); - if ( (m_currentRun != eventrn)) - msgStream() << (m_currentRun ? MSG::WARNING : MSG::DEBUG) - << "Run number changed from " << m_currentRun << " to " - << eventrn << " Complete EventID = " - << *(m_currentEvent->event_ID()) << endmsg; - } - - //----------------------------------------------------------------------- - // Create EventContext - //----------------------------------------------------------------------- - ATH_CHECK(installEventContext(m_currentEvent, m_currentRun)); - - //----------------------------------------------------------------------- - // obtain the HLT conditions update counters from the CTP fragment - //----------------------------------------------------------------------- - std::vector<uint32_t> l1_hltCounters(1,0); // HLT counters from CTP fragment - std::vector<uint32_t> l1_extraPayload; // extra paylaod from CTP fragment - - // find the CTP ROB and get the HLT conditions update counters - bool b_invalidCTPRob = false; - std::vector<uint32_t> ctpRobIdVec(1,m_lvl1CTPROBid.value()); - std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*> ctpRobFragmentVec; - m_robDataProviderSvc->getROBData(ctpRobIdVec,ctpRobFragmentVec); - if( ctpRobFragmentVec.size() == 1 ) { - try { - // get the HLT Counter - l1_hltCounters[0] = CTPfragment::hltCounter( ctpRobFragmentVec[0] ); - l1_extraPayload = CTPfragment::extraPayloadWords( ctpRobFragmentVec[0] ); - } - catch (CTPfragment::NullFragmentPointer& ex) { - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (CTPfragment::Inconsistency& ex) { - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (CTPfragment::TimeOutOfRange& ex) { - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (CTPfragment::TriggerWordsOutOfRange& ex) { - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (CTPfragment::GenericIssue& ex) { - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (eformat::Issue& ex) { - std::string issue_msg = std::string("Uncaught eformat issue: ")+std::string(ex.what()); - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << issue_msg << endmsg; - } - catch (ers::Issue& ex) { - std::string issue_msg = std::string("Uncaught ERS issue: ")+std::string(ex.what()); - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << issue_msg << endmsg; - } - catch (std::exception& ex) { - std::string issue_msg = std::string("Uncaught std exception: ")+std::string(ex.what()); - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << issue_msg << endmsg; - } - catch (...) { - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << "Uncaught unknown exception" << endmsg; - } - } else { - // no valid CTP fragment found - std::string issue_msg = std::string("No valid CTP fragment found. ") ; - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << issue_msg << endmsg; - } - - //----------------------------------------------------------------------- - // create an empty HLT Result Object and register it in StoreGate - // (if this fails, steering will try to create a HLT result object) - //----------------------------------------------------------------------- - auto pHltResult = new HLT::HLTResult; - pHltResult->setLvl1Id(m_currentEvent->event_ID()->event_number()); - HLT::HLTExtraData& extraData = pHltResult->getExtraData(); - extraData.appName = applicationName(); - extraData.statusCode |= hltonl::HLT_PRESCALE_UPDATE; // OK - - // Record it in StoreGate (object can be modified) - sc = m_evtStore->record(pHltResult, m_HltResultName, true); - if(sc.isFailure()) { - msgStream() << MSG::ERROR << "Error declaring HLT Result object in SG" << endmsg; - } - - //----------------------------------------------------------------------- - // Decode CTP extra payload words - //----------------------------------------------------------------------- - CTPfragment::ExtraPayload ctp_payload; - try { - ctp_payload = CTPfragment::ExtraPayload(l1_extraPayload); - } - catch (CTPfragment::ExtraPayloadTooLong& ex) { - b_invalidCTPRob=true; - msgStream() << MSG::ERROR << "Invalid CTP fragment. Exception = " << ex.what() << endmsg; - } - - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << "CTP extra payload (" << l1_extraPayload.size() << " words): "; - for (std::size_t i=0; i<l1_extraPayload.size(); ++i) msgStream() << " " << l1_extraPayload[i]; - - msgStream() << ctp_payload << endmsg; - } - - // Schedule COOL updates - m_coolHelper->setFolderUpdates(ctp_payload.getFolderUpdates()); - - //----------------------------------------------------------------------- - // Check if an HLT conditions update is required - //----------------------------------------------------------------------- - if (!b_invalidCTPRob) { - sc = checkHltPrescaleUpdate(l1_hltCounters); - if(sc.isFailure()) { - std::vector<uint32_t>& vExtraData = pHltResult->getExtras(); - // set the HLT PSK flag to 0 to indicate error - vExtraData[vExtraData.size()-2] = 0; // one word for prescale counter (=1 ok, =0 error) - msgStream() << MSG::FATAL << "HLT Conditions update failed" << endmsg; - throw ers::HLTAbort(ERS_HERE, name()+": HLT Conditions update failed"); - } - } - - // Fire BeginEvent "Incident" - m_incidentSvc->fireIncident(EventIncident(*m_currentEvent, name(),"BeginEvent")); - - //----------------------------------------------------------------------- - // COOL updates for LB changes - //----------------------------------------------------------------------- - if ( m_currentLB != m_currentEvent->event_ID()->lumi_block() ) { // LB change - m_currentLB = m_currentEvent->event_ID()->lumi_block(); - - if ( m_coolHelper->hltCoolUpdate(m_currentLB, m_currentRun, - m_sorTime_stamp[0], m_sorTime_stamp[1]).isFailure() ) { - msgStream() << MSG::FATAL << "COOL update failed. Aborting." << endmsg; - throw ers::HLTAbort(ERS_HERE, name()+": Failure during COOL update"); - } - } - - // Execute Algorithms - bool eventFailed = false; - try { - sc = executeAlgorithms(); - } - catch ( const std::exception& e ) { - msgStream() << MSG::ERROR << "Caught a standard exception " - << e.what() << endmsg; - sc = StatusCode::FAILURE; - } - catch (...) { - msgStream() << MSG::ERROR << "Unknown exception" << endmsg; - sc = StatusCode::FAILURE; - } - - if (sc.isSuccess()) { - // Call the execute() method of all output streams - for (auto o : m_outStreamList ) { - sc = o->sysExecute(m_eventContext); - if(sc.isFailure()) { - msgStream() << MSG::WARNING << "Execution of output stream " << o->name() << " failed" << endmsg; - eventFailed = true; - } - } - } - else { - eventFailed = true; - } - - // Fire EndEvent "Incident" - m_incidentSvc->fireIncident(EventIncident(*m_currentEvent, name(),"EndEvent")); - - return eventFailed ? StatusCode::FAILURE : StatusCode::SUCCESS; -} - - -//========================================================================= -// prepare for run step -//========================================================================= -StatusCode HltEventLoopMgr::prepareForRun(const ptree & pt) -{ - try - { - - (void)TClass::GetClass("vector<unsigned short>"); // preload to overcome an issue with dangling references in serialization - (void)TClass::GetClass("vector<unsigned long>"); - - const SOR * sor; - if(internalPrepareResets().isFailure() || // do the necessary resets and - !(sor = processRunParams(pt))) // update SOR in det store and get it back - return StatusCode::FAILURE; - - auto & soral = getSorAttrList(sor); - updInternal(soral); // update internally kept info - updMetadaStore(soral); // update metadata store - - const EventInfo * evinfo; - if(updMagField(pt).isFailure() || // update mag field when appropriate - updHLTConfigSvc().isFailure() || // update config svc when appropriate - resetCoolValidity().isFailure() || // reset selected proxies/IOV folders - prepXAODEventInfo().isFailure() || // update xAOD event data in SG - !(evinfo = prepEventInfo())) // update old event data in SG - return StatusCode::FAILURE; - - bookAllHistograms(); - - if(prepareAlgs(*evinfo).isSuccess()) - return StatusCode::SUCCESS; - } - catch(const ptree_bad_path & e) - { - msgStream() << MSG::ERROR << ST_WHERE - << "Bad ptree path: \"" - << e.path<ptree::path_type>().dump() << "\" - " << e.what() - << endmsg; - } - catch(const ptree_bad_data & e) - { - msgStream() << MSG::ERROR << ST_WHERE - << "Bad ptree data: \"" - << e.data<ptree::data_type>() << "\" - " << e.what() << endmsg; - } - catch(const std::runtime_error& e) - { - msgStream() << MSG::ERROR << ST_WHERE - << "Runtime error: " << e.what() << endmsg; - } - - return StatusCode::FAILURE; -} - -StatusCode HltEventLoopMgr::installEventContext(const EventInfo* pEvent, EventID::number_type run) -{ - if (pEvent) m_eventContext.setEventID( *((EventIDBase*) pEvent->event_ID()) ); - m_eventContext.set(m_total_evt ,0); - - m_eventContext.setExtension( Atlas::ExtendedEventContext( m_evtStore->hiveProxyDict(), run) ); - Gaudi::Hive::setCurrentContext( m_eventContext ); - - m_aess->reset(m_eventContext); - ATH_CHECK(m_evtStore->record(std::make_unique<EventContext> (m_eventContext), "EventContext")); - - return StatusCode::SUCCESS; -} - - -//========================================================================= -// allow for updates after forking the workers and issue an incident -// to inform the clients -//========================================================================= -StatusCode HltEventLoopMgr::hltUpdateAfterFork(const ptree & pt) -{ - updateDFProps(); - - //----------------------------------------------------------------------- - // Fire "UpdateAfterFork" "Incident" - //----------------------------------------------------------------------- - int worker_id = atoi( (pt.get_child("workerId").data()).c_str() ); - int process_id = getpid(); - m_incidentSvc->fireIncident(HLT::Incidents::UpdateAfterFork(worker_id,process_id,name())); - - readyMsg(); // The event processing will start now - - return StatusCode::SUCCESS; -} - -//========================================================================= -// Hlt: process one event/RoI ---> for "online" running -//========================================================================= -StatusCode HltEventLoopMgr::processRoIs ( - const std::vector<eformat::ROBFragment<const uint32_t*>>& l1_result, - hltinterface::HLTResult& hlt_result, - const hltinterface::EventId& evId) -{ - PtrResetter<const EventInfo, std::mutex> currentEventResetter{m_currentEvent, - timeout_mutex}; - StatusCode sc; - - //----------------------------------------------------------------------- - // increase event counter - //----------------------------------------------------------------------- - m_total_evt++; - - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << " " << endmsg; - msgStream() << MSG::DEBUG << " +------------+" << endmsg; - msgStream() << MSG::DEBUG << " | processRoI | for " << name() - << " and event number = " << m_total_evt << " called." - << endmsg; - msgStream() << MSG::DEBUG << " +------------+" << endmsg; - } - - //----------------------------------------------------------------------- - // If HLT THistSvc flush N-tuple buffer - //----------------------------------------------------------------------- - if ( m_hltTHistSvc.isValid() ) { - (m_hltTHistSvc->send()).ignore() ; - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << " ---> THistSvc->send(): m_hltTHistSvc = " - << m_hltTHistSvc << endmsg; - } - } - - //----------------------------------------------------------------------- - // reset event qualifiers - //----------------------------------------------------------------------- - m_lvl1id = 0; // Level-1 ID=event no., 32 bit unsigned - m_run_no = 0; // run number, 32 bit unsigned - m_bunch_crossing_id = 0; // bunch crossing ID, 32 bit unsigned - m_l1_Status_Element = 0; - m_l1_Trigger_Type = 0; - m_l1_detev_type = 0; - m_time_stamp = 0; // time stamp - posix time in seconds from 1970, 32 bit unsigned - m_time_stamp_ns_offset = 0; // time stamp ns - ns time offset for time_stamp, 32 bit unsigned - m_lumi_block = 0; // luminosity block identifier, 32 bit unsigned - m_l1_Trigger_Info.assign(16,0); // triggerInfo - - // clear hlt_result structure - // ------------------------- - hlt_result.trigger_info.clear(); - hlt_result.stream_tag.clear(); - hlt_result.psc_errors.clear(); - (*hlt_result.fragment_pointer) = 0; - - //----------------------------------------------------------------------- - // Check received Lvl1 result (Integrity is checked by HLTPU) - // get basic event parameters - // Store LVL1 Result in ROBDataProviderSvc cache - // Get extended information from the CTP ROB - //----------------------------------------------------------------------- - if( l1_result.size() == 0 ) { // no Lvl1 result robs - m_invalid_lvl1_result++; - - failedEvent(hlt_result, - hltonl::PSC_ERROR_NO_L1_RESULT, - "No Lvl1 result ROBs received."); - - return StatusCode::RECOVERABLE; - } - - // *-- SubDetectors in received L1 ROB list - if (m_doMonitoring.value()) { - scoped_lock_histogram lock; - for(const auto& rob : l1_result) - { - auto sid = eformat::helper::SourceIdentifier(rob.rob_source_id()); - auto label = std::string{UNEXPECTED_L1R_ROB_LABEL}; - if(std::find(begin(L1R_BINS), end(L1R_BINS), sid.subdetector_id()) - != end(L1R_BINS)) - label = sid.human_detector(); - m_hist_l1_robs->Fill(label.c_str(), 1.); - } - } - - const OFFLINE_FRAGMENTS_NAMESPACE::DataType* buffer; - // at least 1 Lvl1 rob, set basic parameters - m_lvl1id = l1_result[0].rod_lvl1_id(); // Level-1 ID=event no., 32 bit unsigned - m_run_no = l1_result[0].rod_run_no(); // run number, 32 bit unsigned - m_bunch_crossing_id = l1_result[0].rod_bc_id(); // bunch crossing ID, 32 bit unsigned - l1_result[0].status(buffer); - m_l1_Status_Element = *buffer; - m_l1_Trigger_Type = l1_result[0].rod_lvl1_trigger_type(); - m_l1_detev_type = l1_result[0].rod_detev_type(); - m_time_stamp = 0; // time stamp - posix time in seconds from 1970, 32 bit unsigned - m_time_stamp_ns_offset = 0; // time stamp ns - ns time offset for time_stamp, 32 bit unsigned - m_lumi_block = 0; // luminosity block identifier, 32 bit unsigned - m_l1_Trigger_Info.assign(16,0); // triggerInfo can be obtained from CTP fragment - - // put Lvl1 result in ROBDataProviderSvc cache - m_robDataProviderSvc->setNextEvent(l1_result); - - // find the CTP ROB and get the complete event info data - std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*> ctpRobFragmentVec; - m_robDataProviderSvc->getROBData(m_ctpRobIdVec,ctpRobFragmentVec); - bool b_invalidCTPRob = false; - std::ostringstream ost; - if( ctpRobFragmentVec.size() == 1 ) { - try { - m_lvl1id = ctpRobFragmentVec[0]->rod_lvl1_id(); // Level-1 ID=event no., 32 bit unsigned - m_run_no = ctpRobFragmentVec[0]->rod_run_no(); // run number, 32 bit unsigned - m_bunch_crossing_id = ctpRobFragmentVec[0]->rod_bc_id(); // bunch crossing ID, 32 bit unsigned - ctpRobFragmentVec[0]->status(buffer); - m_l1_Status_Element = *buffer; - m_l1_Trigger_Type = ctpRobFragmentVec[0]->rod_lvl1_trigger_type(); - m_l1_detev_type = ctpRobFragmentVec[0]->rod_detev_type(); - // get time_stamp - posix time in seconds from 1970, and time_stamp_ns - ns time offset for time_stamp - CTPfragment::time( ctpRobFragmentVec[0], m_time_stamp, m_time_stamp_ns_offset ); - // luminosity block identifier, 32 bit unsigned - m_lumi_block = CTPfragment::lumiBlockNumber( ctpRobFragmentVec[0] ); - // get the L1 trigger info - m_l1_Trigger_Info = CTPfragment::triggerDecision( ctpRobFragmentVec[0] ); - - b_invalidCTPRob = !checkEventIdConsistency(evId); - } - catch (CTPfragment::NullFragmentPointer& ex) { - m_invalid_lvl1_result++; - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " Invalid CTP fragment. Exception = " << ex.what(); - } - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (CTPfragment::Inconsistency& ex) { - m_invalid_lvl1_result++; - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " Invalid CTP fragment. Exception = " << ex.what(); - } - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (CTPfragment::TimeOutOfRange& ex) { - m_invalid_lvl1_result++; - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " Invalid CTP fragment. Exception = " << ex.what(); - } - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (CTPfragment::TriggerWordsOutOfRange& ex) { - m_invalid_lvl1_result++; - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " Invalid CTP fragment. Exception = " << ex.what(); - } - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (CTPfragment::GenericIssue& ex) { - m_invalid_lvl1_result++; - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " Invalid CTP fragment. Exception = " << ex.what(); - } - msgStream() << MSG::ERROR << ex.what() << endmsg; - } - catch (eformat::Issue& ex) { - m_invalid_lvl1_result++; - std::string issue_msg = std::string("Uncaught eformat issue: ")+std::string(ex.what()); - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " Invalid CTP fragment. Exception = " << ex.what(); - } - msgStream() << MSG::ERROR << issue_msg << endmsg; - } - catch (ers::Issue& ex) { - m_invalid_lvl1_result++; - std::string issue_msg = std::string("Uncaught ERS issue: ")+std::string(ex.what()); - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " Invalid CTP fragment. Exception = " << ex.what(); - } - msgStream() << MSG::ERROR << issue_msg << endmsg; - } - catch (std::exception& ex) { - m_invalid_lvl1_result++; - std::string issue_msg = std::string("Uncaught std exception: ")+std::string(ex.what()); - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " Invalid CTP fragment. Exception = " << ex.what(); - } - msgStream() << MSG::ERROR << issue_msg << endmsg; - } - catch (...) { - m_invalid_lvl1_result++; - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " Invalid CTP fragment. Uncaught unknown exception."; - } - msgStream() << MSG::ERROR << "Uncaught unknown exception." << endmsg; - } - } else { - // no valid CTP fragment found - m_invalid_lvl1_result++; - if (m_doMonitoring.value()) m_hist_l1_robs->Fill(MISSING_L1R_CTP_LABEL, 1.); - - std::string issue_msg = std::string("No valid CTP fragment found. ") ; - if (m_hltROBDataProviderSvc.isValid()) issue_msg = issue_msg + std::string("\n") + - m_hltROBDataProviderSvc->dumpROBcache() ; - if (m_lvl1CTPROBcheck) { - b_invalidCTPRob=true; - ost << " No valid CTP fragment found. " ; - } - msgStream() << MSG::ERROR << issue_msg << endmsg; - } - - // in case a check of the CTP Rob is requested and an invalid fragment was found - // skip the event and put it on the debug stream - // ----------------------------------------------------------------------------- - if (m_lvl1CTPROBcheck && b_invalidCTPRob) { - ost << " Skip event requested. "; - failedEvent(hlt_result, - hltonl::PSC_ERROR_INVALID_CTP_RESULT, - ost.str()); - - return StatusCode::RECOVERABLE; - } - - // Check for other missing L1 ROBs - auto missing_l1_robs = missingL1Robs(l1_result); - if(!missing_l1_robs.empty()) - { - ++m_invalid_lvl1_result; - failedEvent(hlt_result, hltonl::PSC_ERROR_NO_L1_RESULT, - missingL1RobsMsg(missing_l1_robs)); - - return StatusCode::RECOVERABLE; - } - - //----------------------------------------------------------------------- - // Clear the event store, if used in the event loop - //----------------------------------------------------------------------- - sc = m_evtStore->clearStore(); - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << " ---> Clear of Event data store " << sc << endmsg; - } - if(sc.isFailure()) { - failedEvent(hlt_result, hltonl::PSC_ERROR_SG_CLEAR_FAILED, - "Clear of Event data store failed."); - return sc; - } - - // create an EventInfo Object to fire the incidents and register in evt store - auto pEvent = new EventInfo(new EventID(m_run_no, - evId.globalId, - m_time_stamp, - m_time_stamp_ns_offset, - m_lumi_block, - m_bunch_crossing_id, - std::get<0>(m_detector_mask), - std::get<1>(m_detector_mask), - std::get<2>(m_detector_mask), - std::get<3>(m_detector_mask)), - new EventType(), - new TriggerInfo(m_l1_Status_Element, - m_lvl1id, - m_l1_Trigger_Type, - m_l1_Trigger_Info)); - - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << " +-----------+ " << endmsg; - msgStream() << MSG::DEBUG << " | New Event | Run = " << m_run_no - << " / Level-1 ID = " << m_lvl1id - << " / global Event ID = " << evId.globalId - << endmsg; - msgStream() << MSG::DEBUG << " +-----------+ " << endmsg; - msgStream() << MSG::DEBUG << " Complete EventID = " << *(pEvent->event_ID()) << endmsg; - msgStream() << MSG::DEBUG << " EventType = " << ((pEvent->event_type())->typeToString()) << endmsg; - msgStream() << MSG::DEBUG << " TriggerInfo = " << *(pEvent->trigger_info()) << endmsg; - msgStream() << MSG::DEBUG << " Current Run number = " << m_currentRun << endmsg; - } - - // Record it in StoreGate - if(m_evtStore->record(pEvent, "EventInfo").isFailure()) - { - failedEvent(hlt_result, hltonl::PSC_ERROR_NO_EVENTINFO, - "Error recording EventInfo object in SG"); - - return StatusCode::FAILURE; - } - - //----------------------------------------------------------------------- - // process the RoI(s)/Event - //----------------------------------------------------------------------- - sc = executeEvent(NULL); - if(sc.isFailure()) { - failedEvent(hlt_result, hltonl::PSC_ERROR_UNCLASSIFIED, - "An unknown error occured during event processing", - false /* no empty result */); - } - - // Get the xAOD::EventInfo from SG - xAOD::EventInfo * xev{nullptr}; - if(m_evtStore->retrieve(xev, "EventInfo").isFailure()) - { - msgStream() << MSG::WARNING << ST_WHERE - << "Could not retrieve xAOD::EventInfo in store gate. " - << "If running in HelloWorld algorithms, this is OK." - << endmsg; - } - - if (msgLevel() <= MSG::DEBUG) - msgStream() << MSG::DEBUG << " new xAOD::EventInfo: " << xev << endmsg; - - //----------------------------------------------------------------------- - // build HLT result - //----------------------------------------------------------------------- - HltResult(hlt_result, pEvent, xev); - // fill histograms - fillHltResultHistograms(hlt_result); - - return sc; -} - -//========================================================================= -// implementation of IService::stop() ---> for "online" running -//========================================================================= +// ============================================================================= +// Reimplementation of AthService::stop (IStateful interface) +// ============================================================================= StatusCode HltEventLoopMgr::stop() { - // Do nothing if we are already stopped - if ( FSMState() != Gaudi::StateMachine::RUNNING ) - return StatusCode::SUCCESS; - - if (msgLevel() <= MSG::DEBUG) { - msgStream() << MSG::DEBUG << " ---> HltEventLoopMgr = " << name() << " stop() " << endmsg; + // Stop top level algorithms + for (auto& ita : m_topAlgList) { + ATH_CHECK(ita->sysStop()); } - //----------------------------------------------------------------------- - // Fire EndRun "Incident" - //----------------------------------------------------------------------- - m_incidentSvc->fireIncident(Incident(name(), IncidentType::EndRun)); - - //----------------------------------------------------------------------- - // Call endRun() and stop() of all algorithms - //----------------------------------------------------------------------- - auto suc1 = callOnAlgs(&IAlgorithm::sysEndRun, "sysEndRun").isSuccess(); - auto suc2 = callOnAlgs(&IAlgorithm::sysStop, "sysStop").isSuccess(); - - return (suc1 && suc2) ? StatusCode::SUCCESS : StatusCode::FAILURE; + return AthService::stop(); } -//========================================================================= -// implementation of ITrigEventLoopMgr::timeOutReached ---> for "online" running -//========================================================================= -/** - * Called by the PSC once the HLTPU signals the timeout warning. - * - * !!! This method is executed in the context of the timeout thread !!! - * !!! Make sure the code is thread-safe !!! - * - */ -StatusCode HltEventLoopMgr::timeOutReached(const ptree& pt) +// ============================================================================= +// Reimplementation of AthService::finalize (IStateful interface) +// ============================================================================= +StatusCode HltEventLoopMgr::finalize() { - IAlgorithm* alg = m_algContextSvc ? m_algContextSvc->currentAlg() : 0; - - // add current algorithm info - std::ostringstream tmsg; - tmsg << "Timeout warning received" - << (alg ? (" while executing '"+alg->name()+"'. ") : ". "); + ATH_MSG_INFO(" ---> HltEventLoopMgr = " << name() << " finalize "); + ATH_MSG_INFO(" Total number of events processed " << m_nevt); - // set timeout and add current event info - { - std::lock_guard<std::mutex>{timeout_mutex}; + // Need to release now - automatic release in destructor is too late since services are already gone + m_hltTHistSvc.reset(); + m_hltROBDataProviderSvc.reset(); - setTimeout(Athena::Timeout::instance()); - if (m_currentEvent) - tmsg << " On event " << *m_currentEvent->event_ID() << ". "; - else - tmsg << " Unknown event - outside of event processing? "; + // Finalise top level algorithms + for (auto& ita : m_topAlgList) { + if (ita->sysFinalize().isFailure()) + ATH_MSG_WARNING("Finalisation of algorithm " << ita->name() << " failed"); } - - // add time interval info - auto starts = pt.get_optional<long long>("StartTime_s"); - if(starts) - { - auto ends = std::chrono::duration_cast<std::chrono::seconds>( - std::chrono::steady_clock::now().time_since_epoch()).count(); - tmsg << (ends - *starts) << " seconds elapsed since "; + // Release top level algorithms + SmartIF<IAlgManager> algMgr = serviceLocator()->as<IAlgManager>(); + if (!algMgr.isValid()) { + ATH_MSG_WARNING("Failed to retrieve AlgManager - cannot finalise top level algorithms"); } - else - tmsg << "No information of when "; - - tmsg << "the HLTPU last started counting."; - - // log timeout message - ERS_HLT_WARNING(tmsg.str()); - - // Also fire timeout incident (this seems to cause problems, see #66066) - // m_incidentSvc->fireIncident( HLT::Incidents::EventTimeout(name()) ); - - return StatusCode::SUCCESS; -} - - - -//========================================================================= -// implementation of ITrigEventLoopMgr::checkHltPrescaleUpdate() ---> for "online" running -//========================================================================= -StatusCode HltEventLoopMgr::checkHltPrescaleUpdate(std::vector<uint32_t>& hltCounter) -{ - if (msgLevel() <= MSG::DEBUG) { - msgStream() << MSG::DEBUG << " ---> HltEventLoopMgr = " << name() - << " hltConditionsUpdate(std::vector<uint32_t>&): size of input = " << hltCounter.size() << ": "; - for (size_t i=0; i<hltCounter.size(); ++i) msgStream() << hltCounter[i] << " "; - msgStream() << endmsg; - } - if ( hltCounter.empty() ) return StatusCode::SUCCESS; - - // First (and only used) element is LB of the prescale update - uint32_t new_hltPrescaleUpdateLB = hltCounter[0]; - - // Only update if counter (lumiblock for update) changed (or first event) - if ( m_l1_hltPrescaleUpdateLB != new_hltPrescaleUpdateLB ) { - m_l1_hltPrescaleUpdateLB = new_hltPrescaleUpdateLB; - - // Retrieve EventInfo object - const EventInfo* pEvent(0); - StatusCode sc = m_evtStore->retrieve(pEvent); - if(sc.isFailure()) { - msgStream() << MSG::ERROR << "Unable to retrieve EventInfo object" << endmsg; - return sc; + else { + for (auto& ita : m_topAlgList) { + if (algMgr->removeAlgorithm(ita).isFailure()) + ATH_MSG_WARNING("Problems removing Algorithm " << ita->name()); } - - msgStream() << MSG::INFO << "Prescale update requested for lumiblock " - << m_l1_hltPrescaleUpdateLB << ". Current event: " << *pEvent->event_ID() << endmsg; - - // Perform prescale update right away (including on first event) - sc = hltPrescaleUpdate(m_l1_hltPrescaleUpdateLB); - return sc; } + m_topAlgList.clear(); + + // Release service handles + if (m_incidentSvc.release().isFailure()) + ATH_MSG_WARNING("Failed to release service " << m_incidentSvc.typeAndName()); + if (m_robDataProviderSvc.release().isFailure()) + ATH_MSG_WARNING("Failed to release service " << m_robDataProviderSvc.typeAndName()); + if (m_evtStore.release().isFailure()) + ATH_MSG_WARNING("Failed to release service " << m_evtStore.typeAndName()); + if (m_detectorStore.release().isFailure()) + ATH_MSG_WARNING("Failed to release service " << m_detectorStore.typeAndName()); + if (m_inputMetaDataStore.release().isFailure()) + ATH_MSG_WARNING("Failed to release service " << m_inputMetaDataStore.typeAndName()); + if (m_THistSvc.release().isFailure()) + ATH_MSG_WARNING("Failed to release service " << m_THistSvc.typeAndName()); + if (m_evtSelector.release().isFailure()) + ATH_MSG_WARNING("Failed to release service " << m_evtSelector.typeAndName()); + if (m_outputCnvSvc.release().isFailure()) + ATH_MSG_WARNING("Failed to release service " << m_outputCnvSvc.typeAndName()); + + // Release tool handles + if (m_coolHelper.release().isFailure()) + ATH_MSG_WARNING("Failed to release tool " << m_coolHelper.typeAndName()); + if (m_hltResultBuilder.release().isFailure()) + ATH_MSG_WARNING("Failed to release tool " << m_hltResultBuilder.typeAndName()); + if (m_eventInfoCnvTool.release().isFailure()) + ATH_MSG_WARNING("Failed to release tool " << m_eventInfoCnvTool.typeAndName()); + + // Release SmartIFs + m_whiteboard.reset(); + m_algResourcePool.reset(); + m_aess.reset(); + m_schedulerSvc.reset(); + m_hltTHistSvc.reset(); + m_hltROBDataProviderSvc.reset(); return StatusCode::SUCCESS; } - -//========================================================================= -// implementation of ITrigEventLoopMgr::hltPrescaleUpdate() ---> for "online" running -//========================================================================= -StatusCode HltEventLoopMgr::hltPrescaleUpdate(uint32_t lumiBlock) -{ - if ( !m_hltConfigSvc ) { - return StatusCode::SUCCESS; - } - - // ID must be unqiue across runs until DbProxy gets restarted - unsigned int id = m_currentRun*10000 + lumiBlock; - msgStream() << MSG::INFO << " ---> HltEventLoopMgr = " << name() - << " calling HLTConfigSvc::updatePrescaleSets(" << id << ")" << endmsg; - StatusCode sc = m_hltConfigSvc->updatePrescaleSets(id); - - return sc; -} - -//========================================================================= -// check that a ROB ID is enabled for readout in OKS ---> for "online" running -//========================================================================= -bool HltEventLoopMgr::isRobEnabled(uint32_t robid) const +// ============================================================================= +// Reimplementation of AthService::reinitalize (IStateful interface) +// ============================================================================= +StatusCode HltEventLoopMgr::reinitialize() { - bool b_enabled = true; + ATH_CHECK(AthService::reinitialize()); - // check if given ROB is actually enabled for readout - // Consider some ROBs from SubDetectorGroup TDAQ as always enabled - if ((m_enabledROBs.value().size() != 0) && - !skipEnabledCheck(robid)) - { - auto rob_enabled_it = std::find(m_enabledROBs.value().begin(), - m_enabledROBs.value().end(), - robid); - if(rob_enabled_it == m_enabledROBs.value().end()) - { - if(msgLevel() <= MSG::DEBUG) - msgStream() << MSG::DEBUG << "---> ROB Id : 0x" << MSG::hex << robid - << MSG::dec << " will not be retrieved, since it is not on " - "the list of enabled ROBs." << endmsg; - - b_enabled = false; - } + // reinitialise top level algorithms + for (auto& ita : m_topAlgList) { + ATH_CHECK(ita->sysReinitialize()); } - return b_enabled; + return StatusCode::SUCCESS; } -//========================================================================= -// check that a Sub Detector ID is enabled for readout in OKS ---> for "online" running -//========================================================================= -bool HltEventLoopMgr::isSubDetectorEnabled(uint32_t subdetid) const +// ============================================================================= +// Reimplementation of AthService::restart (IStateful interface) +// ============================================================================= +StatusCode HltEventLoopMgr::restart() { - bool b_enabled = true; + ATH_CHECK(AthService::restart()); - // check if given subdetector is actually enabled for readout - if ((m_enabledSubDetectors.value().size() != 0) && - !skipEnabledCheck(static_cast<eformat::SubDetector>(subdetid))) - { - auto sd_enabled_it = std::find(m_enabledSubDetectors.value().begin(), - m_enabledSubDetectors.value().end(), - subdetid); - if(sd_enabled_it == m_enabledSubDetectors.value().end()) - { - if(msgLevel() <= MSG::DEBUG) - msgStream() << MSG::DEBUG << "---> Sub Detector Id : 0x" << MSG::hex - << subdetid << MSG::dec << " will not be retrieved, since " - "it is not on the list of enabled Sub Detectors." << endmsg; - b_enabled = false; - } + // restart top level algorithms + for (auto& ita : m_topAlgList) { + m_aess->resetErrorCount(ita); + ATH_CHECK(ita->sysRestart()); } - return b_enabled; -} - -//========================================================================= -// filter a set of robs according to whether or not they are enabled -//========================================================================= -std::set<uint32_t> -HltEventLoopMgr::filterRobs(const std::set<uint32_t>& robs) const -{ - auto ret = decltype(robs){}; - for(const auto& r : robs) - if(isRobEnabled(r)) - ret.insert(r); - - return ret; -} - -//========================================================================= -// filter a set of dets according to whether or not they are enabled -//========================================================================= -std::set<eformat::SubDetector> -HltEventLoopMgr::filterDets(const std::set<uint32_t>& dets) const -{ - auto ret = std::set<eformat::SubDetector>{}; - for(const auto& d : dets) - if(isSubDetectorEnabled(d)) - ret.insert(static_cast<eformat::SubDetector>(d)); - - return ret; -} - -//========================================================================= -// Obsolete methods for online running -//========================================================================= -StatusCode HltEventLoopMgr::nextEvent(int maxevt) -{ - msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg; - msgStream() << MSG::ERROR << " | method ---> HltEventLoopMgr::nextEvent(int maxevt) <--- called | " << endmsg; - msgStream() << MSG::ERROR << " | This method can not be used in trigger since the event loop is | " << endmsg; - msgStream() << MSG::ERROR << " | controlled by the data flow software. | " << endmsg; - msgStream() << MSG::ERROR << " | Method is not implemented | " << endmsg; - msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg; - msgStream() << MSG::ERROR << " maxevt = " << maxevt << endmsg; - msgStream() << MSG::ERROR << " Type info = " << System::typeinfoName(typeid(*this)) << endmsg; - return StatusCode::FAILURE; -} - -StatusCode HltEventLoopMgr::executeRun(int) -{ - msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg; - msgStream() << MSG::ERROR << " | method ---> HltEventLoopMgr::executeRun(int) <--- called | " << endmsg; - msgStream() << MSG::ERROR << " | This method can not be used in trigger since the event loop is | " << endmsg; - msgStream() << MSG::ERROR << " | controlled by the data flow software. | " << endmsg; - msgStream() << MSG::ERROR << " | Method is not implemented | " << endmsg; - msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg; - msgStream() << MSG::ERROR << " Type info = " << System::typeinfoName(typeid(*this)) << endmsg; - return StatusCode::FAILURE; -} - -StatusCode HltEventLoopMgr::stopRun() -{ - msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg; - msgStream() << MSG::ERROR << " | method ---> HltEventLoopMgr::stopRun() <--- called | " << endmsg; - msgStream() << MSG::ERROR << " | This method is not implemented for online usage. Call stop() instead. | " << endmsg; - msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg; - msgStream() << MSG::ERROR << " Type info = " << System::typeinfoName(typeid(*this)) << endmsg; - return StatusCode::FAILURE; + return StatusCode::SUCCESS; } -//========================================================================= -// HltEmptyResultROB() -//========================================================================= -void HltEventLoopMgr::HltEmptyResultROB(hltinterface::HLTResult& hlt_result, - uint32_t run_no, uint32_t lvl1_id, uint32_t bunch_crossing_id, - uint32_t l1_Trigger_Type, uint32_t l1_detev_type, - hltonl::PSCErrorCode pscErrorCode) -{ - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << "---> HltEmptyResultROB() for " << name() - << " and sub detector = " << eformat::helper::SubDetectorDictionary.string(eformat::TDAQ_HLT) - << " called " << endmsg; - } - - // - // Set the PSC error words - // ----------------------- - // - HltSetPscError(hlt_result, pscErrorCode); - - // - // Create a dummy HLT result ROB - // ----------------------------- - // - - // the second status element - hltonl::ResultStatusCode hlt_status = hltonl::DUMMY_HLT_RESULT ; - - // Build the third status elements for the dummy HLT result - // number of status words used (in case of PSC error = 3, otherwise = 2) - uint32_t n_status_word = 3; - m_status_words[0] = SW_FAIL.code(); - m_status_words[1] = hlt_status; - m_status_words[2] = pscErrorCode; //this means "dummy HLT result, with no data due PSC error" - - if (!pscErrorCode) { - m_status_words[0] = SW_UNCLASSIFIED.code(); //this means "dummy HLT result, with no data, no PSC error" - n_status_word = 2; - } - - // Build an empty HLT result - eformat::helper::SourceIdentifier src(eformat::TDAQ_HLT, 0); - eformat::write::ROBFragment rob(src.code(), run_no, lvl1_id, bunch_crossing_id, l1_Trigger_Type, l1_detev_type, - 0, 0, eformat::STATUS_FRONT); - rob.status(n_status_word, m_status_words); - rob.rod_status(n_status_word, m_status_words); - - // find the maximum allowed payload - int hltr_max_payload = hlt_result.max_result_size - rob.size_word() ; - if ( hlt_result.max_result_size <= rob.size_word() ) { - msgStream() << MSG::ERROR - << "Can not create empty HLT result ROB with available ROB buffer size ! Available buffer size = " - << hlt_result.max_result_size << " Number of header words used by empty ROB = " << rob.size_word() - << endmsg; - return; - } - - // Create a dummy HLT result and check data size - uint32_t* hltr_data(0); - int hltr_data_size = 0; - HLT::HLTResult emptyHLTResult; - emptyHLTResult.setLvl1Id(lvl1_id); - - HLT::HLTExtraData& extraData = emptyHLTResult.getExtraData(); - extraData.appName = applicationName(); - extraData.statusCode &= ~hltonl::HLT_PRESCALE_UPDATE; // error (clear bit) - - bool serializationOk = emptyHLTResult.serialize( hltr_data, hltr_data_size, hltr_max_payload); - - if ( !serializationOk ) { - // Update status words for dummy HLT result - hlt_status = hltonl::DUMMY_HLT_RESULT_TRUNCATED; - m_status_words[0] = SW_TRUNCATION.code() ; - m_status_words[1] = hlt_status ; - } - - if (( hltr_data_size > hltr_max_payload)) { // consistency check - msgStream() << MSG::ERROR - << "Inconsistency for created dummy HLT result ROB. Returned data size = " << hltr_data_size - << " is greater than allowed max. payload size = " << hltr_max_payload << "." - << endmsg; - hltr_data_size = hltr_max_payload; - - // Update status words for dummy HLT result - hlt_status = hltonl::DUMMY_HLT_RESULT_TRUNCATED; - m_status_words[0] = SW_TRUNCATION.code(); - m_status_words[1] = hlt_status ; - } - - // build the fragment - rob.status(n_status_word, m_status_words); - rob.rod_status(n_status_word, m_status_words); - rob.rod_data(hltr_data_size, hltr_data); - - // - // store the dummy HLT ROB fragment in the hlt_result structure - // ------------------------------------------------------------ - // - // The maximum possible space is already allocated by the HLTMPPU - // copy the ROB contents into the allocated memory - auto next_fragment = hlt_result.fragment_pointer; - auto spaceleft = hlt_result.max_result_size; - addRobToHLTResult(hlt_result, rob, next_fragment, spaceleft); - - // delete the data array - if (hltr_data != 0) delete[] hltr_data; - - return; -} // end method HltEventLoopMgr::HltEmptyResultROB - -//========================================================================= -// HltEmptyResultROB() ---> for "online" running -//========================================================================= -void HltEventLoopMgr::HltEmptyResultROB(hltinterface::HLTResult& hlt_result, hltonl::PSCErrorCode pscErrorCode) +// ============================================================================= +// Implementation of ITrigEventLoopMgr::prepareForRun +// ============================================================================= +StatusCode HltEventLoopMgr::prepareForRun(const ptree& pt) { - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << "---> HltEmptyResultROB() for " - << name() << " called " << endmsg; - } - - HltEmptyResultROB(hlt_result, - m_run_no, m_lvl1id, m_bunch_crossing_id, - m_l1_Trigger_Type, m_l1_detev_type, - pscErrorCode); - return; -} // end method HltEventLoopMgr::HltEmptyResult - -//========================================================================= -// HltResultROBs() -//========================================================================= -hltonl::PSCErrorCode HltEventLoopMgr::HltResultROBs( - hltinterface::HLTResult& hlt_result, - uint32_t run_no, uint32_t lvl1_id, uint32_t bunch_crossing_id, - uint32_t l1_Trigger_Type, uint32_t l1_detev_type, - const std::vector<TriggerInfo::number_type>& trigger_info, - const std::vector<TriggerInfo::StreamTag>& stream_tags, - const std::vector<xAOD::EventInfo::StreamTag>& xsts) -{ - HLT::HLTResult* dobj{0}; - auto hlt_decision = hltonl::PSC_FORCED_REJECT; - auto ecode = hltonl::PSC_ERROR_UNCLASSIFIED; - if(!m_forceHltReject) + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + try { - // preliminary hlt_result setup - setStreamTags(hlt_result, stream_tags); - mergeStreamTags(hlt_result, xsts); - hlt_result.trigger_info = trigger_info; - - // Get Pesa HLT Result from Steering - StatusCode sc; - if(!(m_evtStore->transientContains<HLT::HLTResult>(m_HltResultName)) || - (sc = m_evtStore->retrieve(dobj,m_HltResultName)).isFailure()) - { - hlt_decision = hltonl::PSC_DEBUG; - msgStream() << MSG::ERROR << ST_WHERE - << "Error retrieving HLTResult from StoreGate with key = " - << m_HltResultName << endmsg; - - ecode = sc.isFailure() ? hltonl::PSC_ERROR_NO_HLTRESULT_RETRIEVED - : hltonl::PSC_ERROR_NO_HLTRESULT_FOUND; - } - else if((hlt_decision = processHltDecision(hlt_result)) != - hltonl::STEERING_REJECT) - { - // Got Steering's HLT Result and confirmed the event should be accepted - auto serializationOk = true; - ecode = serializeRobs(hlt_result, serializationOk, dobj, run_no, lvl1_id, - bunch_crossing_id, l1_Trigger_Type, l1_detev_type); - if(!ecode) - recordEDMSizeInfo(dobj->getNavigationResult().size(), serializationOk); - - // The HLT result got truncated, put the event on a special debug stream if requested - if (!serializationOk) { - m_truncated_hlt_result++; - if (m_doMonitoring.value()) m_hist_Hlt_truncated_result->Fill(1.); - - if ((!m_HltTruncationDebugStreamName.value().empty()) && - (m_writeHltTruncationToDebug.value())) { - // check if event should be not send to the debug stream (e.g. Cost Monitoring) - bool sendToDebug(true); - for (auto it_st : hlt_result.stream_tag) { - auto p = std::find(m_excludeFromHltTruncationDebugStream.value().begin(), - m_excludeFromHltTruncationDebugStream.value().end(), - (it_st).name); - if (p != m_excludeFromHltTruncationDebugStream.value().end()) sendToDebug=false; - } - if (sendToDebug) { - m_truncated_hlt_result_to_debug++; - if (m_doMonitoring.value()) m_hist_Hlt_truncated_result->Fill(2.); - hlt_result.stream_tag.clear(); - addDebugStreamTag(hlt_result, m_HltTruncationDebugStreamName); - msgStream() << MSG::ERROR << ST_WHERE - << "HLTResult was truncated. Event send to debug stream = " - << m_HltTruncationDebugStreamName << endmsg; - } else { - m_truncated_hlt_result_not_to_debug++; - if (m_doMonitoring.value()) m_hist_Hlt_truncated_result->Fill(3.); - msgStream() << MSG::WARNING << ST_WHERE - << "HLTResult was truncated. Event was NOT send to debug stream = " - << m_HltTruncationDebugStreamName - << " because an exclusion stream tag name matched from = " << m_excludeFromHltTruncationDebugStream.value() - << endmsg; - } - } else { - m_truncated_hlt_result_not_to_debug++; - if (m_doMonitoring.value()) m_hist_Hlt_truncated_result->Fill(3.); - } - } - } - } - - if (m_doMonitoring.value()) - m_hist_eventAcceptFlags->Fill(static_cast<float>(m_mapAccept.codeToHash(hlt_decision))); - - if(msgLevel() <= MSG::DEBUG) { - msgStream() << MSG::DEBUG << ST_WHERE << "Decision = " - << hltonl::PrintHltAcceptFlag(hlt_decision) << "\n" - << hlt_result << endmsg; - if(dobj) { - const auto& extraData = dobj->getExtraData(); - msgStream() << MSG::DEBUG << ST_WHERE - << "HltResult extra data: Host name = " << extraData.appName - << ", status code = " << extraData.statusCode << endmsg; + // (void)TClass::GetClass("vector<unsigned short>"); // preload to overcome an issue with dangling references in serialization + // (void)TClass::GetClass("vector<unsigned long>"); + + // do the necessary resets + // internalPrepareResets() was here + StatusCode sc = clearTemporaryStores(); + if (sc.isFailure()) { + ATH_MSG_ERROR("Clearing temporary stores failed"); + return sc; } - } - - return ecode; -} // end method HltEventLoopMgr::HltResultROBs -//========================================================================= -// HltResult() ---> for "online" running -//========================================================================= -void HltEventLoopMgr::HltResult(hltinterface::HLTResult& hlt_result, - const EventInfo* pEvent, - const xAOD::EventInfo * xev) -{ - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << "---> HltResult() for " << name() << " called " << endmsg; - } - - using xev_stags_t = decltype(xev->streamTags()); - auto xev_stags = xev ? xev->streamTags() : xev_stags_t{}; - - hltonl::PSCErrorCode hlt_psc_error = HltResultROBs(hlt_result, - m_run_no, m_lvl1id, m_bunch_crossing_id, - m_l1_Trigger_Type, m_l1_detev_type, - pEvent->trigger_info()->eventFilterInfo(), - pEvent->trigger_info()->streamTags(), - xev_stags); - // If there was an error when building the HLT result ROB, - // put the event on the debug stream and try to create a dummy result ROB - if (hlt_psc_error) { - // put event on debug stream - addDebugStreamTag(hlt_result, m_HltDebugStreamName.value()); - // make empty HLT result ROB - HltEmptyResultROB(hlt_result,hlt_psc_error); - // increase counter - m_invalid_hlt_result++; - } - - return; -} // end method HltEventLoopMgr::HltResult + const SOR* sor; + // update SOR in det store and get it back + if(!(sor = processRunParams(pt))) + return StatusCode::FAILURE; -//========================================================================= -void HltEventLoopMgr::bookHistograms() -{ - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << "---> bookHistograms() for " << name() - << " called. Do monitoring = " << m_doMonitoring.value() << endmsg; - } + auto& soral = getSorAttrList(sor); - // return if no monitoring is requested - if ( !m_doMonitoring.value() ) { return; } + updateInternal(soral); // update internally kept info + updateMetadataStore(soral); // update metadata store - std::vector<TH1F**> regHistsTH1F; - regHistsTH1F.reserve(14); - std::vector<TProfile**> regHistsTProfile; - regHistsTProfile.reserve(4); + /* + const EventInfo * evinfo; + if(updMagField(pt).isFailure() || // update mag field when appropriate + updHLTConfigSvc().isFailure() || // update config svc when appropriate + resetCoolValidity().isFailure() || // reset selected proxies/IOV folders + prepXAODEventInfo().isFailure() || // update xAOD event data in SG + !(evinfo = prepEventInfo())) // update old event data in SG + return StatusCode::FAILURE; - // monitoring information root directory - const std::string histPath = std::string("/EXPERT/") + name() + "/"; + bookAllHistograms(); - // +--------------------+ - // *-- | Event accept flags | - // +--------------------+ - uint32_t n_bins_eventAcceptFlags = hltonl::NUM_ACCEPTANCE_FLAGS; - m_hist_eventAcceptFlags = new TH1F ("EventAcceptFlags", - "EventAcceptFlags;;entries", - n_bins_eventAcceptFlags, 0.5, - n_bins_eventAcceptFlags+0.5); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + if(prepareAlgs(*evinfo).isSuccess()) + return StatusCode::SUCCESS; + */ - for (const auto& m : m_mapAccept) { - m_hist_eventAcceptFlags->GetXaxis()->SetBinLabel( m.second.second , (m.second.first).c_str() ); - } - regHistsTH1F.push_back(&m_hist_eventAcceptFlags); - - // +-----------------------+ - // *-- | HLT result properties | - // +-----------------------+ - // *-- HLT result size plot - m_hist_Hlt_result_size = new TH1F ((m_histProp_Hlt_result_size.value().title()).c_str(), - (m_histProp_Hlt_result_size.value().title() + ";words;entries").c_str(), - m_histProp_Hlt_result_size.value().bins(), - m_histProp_Hlt_result_size.value().lowEdge(), - m_histProp_Hlt_result_size.value().highEdge()); - - regHistsTH1F.push_back(&m_hist_Hlt_result_size); - - // *-- HLT result status codes - uint32_t n_bins_ResultStatus = hltonl::NUM_HLT_STATUS_CODES; - m_hist_Hlt_result_status = new TH1F ("HltResultStatusCodes", "HltResultStatusCodes;;entries", - n_bins_ResultStatus, 0.5, n_bins_ResultStatus+0.5); - - // do not print label for normal HLT result with no errors, it is not filled - for (hltonl::MapResultStatusCode::EnumMap::const_iterator map_it = m_mapResultStatus.begin(); map_it != m_mapResultStatus.end(); ++map_it) { - if ( (*map_it).first == hltonl ::NORMAL_HLT_RESULT ) { - m_hist_Hlt_result_status->GetXaxis()->SetBinLabel( ((*map_it).second).second, (((*map_it).second).first+" (bin not filled)").c_str() ); - } else { - m_hist_Hlt_result_status->GetXaxis()->SetBinLabel( ((*map_it).second).second, (((*map_it).second).first).c_str() ); - } - } - regHistsTH1F.push_back(&m_hist_Hlt_result_status); - - // *-- HLT result truncation - uint32_t n_bins_ResultTruncation = 3; - m_hist_Hlt_truncated_result = new TH1F ("HltResultTruncation", - "HltResultTruncation;;entries", - n_bins_ResultTruncation, 0.5, n_bins_ResultTruncation+0.5); - - m_hist_Hlt_truncated_result->GetXaxis()->SetBinLabel( 1, std::string("Truncated HLT result").c_str() ); - m_hist_Hlt_truncated_result->GetXaxis()->SetBinLabel( 2, std::string("Truncated HLT result (send to debug stream)").c_str() ); - m_hist_Hlt_truncated_result->GetXaxis()->SetBinLabel( 3, std::string("Truncated HLT result (not send to debug stream)").c_str() ); - regHistsTH1F.push_back(&m_hist_Hlt_truncated_result); - - // *-- HLT result size plot (Stream Physics Main) - m_hist_Hlt_result_size_physics = - new TH1F ((m_histProp_Hlt_result_size_physics.value().title()).c_str(), - (m_histProp_Hlt_result_size_physics.value().title() + ";words;entries").c_str(), - m_histProp_Hlt_result_size_physics.value().bins(), - m_histProp_Hlt_result_size_physics.value().lowEdge(), - m_histProp_Hlt_result_size_physics.value().highEdge()); - - regHistsTH1F.push_back(&m_hist_Hlt_result_size_physics); - - - // *-- HLT result size plot (Stream Express) - m_hist_Hlt_result_size_express = - new TH1F ((m_histProp_Hlt_result_size_express.value().title()).c_str(), - (m_histProp_Hlt_result_size_express.value().title() + ";words;entries").c_str(), - m_histProp_Hlt_result_size_express.value().bins(), - m_histProp_Hlt_result_size_express.value().lowEdge(), - m_histProp_Hlt_result_size_express.value().highEdge()); - - regHistsTH1F.push_back(&m_hist_Hlt_result_size_express); - - - // *-- HLT result size plot (Stream calibration, DataScouting results) - m_hist_Hlt_result_size_DataScouting = - new TH1F ((m_histProp_Hlt_result_size_DataScouting.value().title()).c_str(), - (m_histProp_Hlt_result_size_DataScouting.value().title() + ";words;entries").c_str(), - m_histProp_Hlt_result_size_DataScouting.value().bins(), - m_histProp_Hlt_result_size_DataScouting.value().lowEdge(), - m_histProp_Hlt_result_size_DataScouting.value().highEdge()); - - regHistsTH1F.push_back(&m_hist_Hlt_result_size_DataScouting); - - - // *-- HLT result size profile plot for all stream types "physics" - m_hist_HltResultSizes_Stream_physics = new TProfile( "Average Hlt Result size for physics streams", - "Average Hlt Result size for physics streams;Stream Name;Average size in words", - 1, - (double) 0., (double) 1., - (double) 0., (double) 3000000.); - - m_hist_HltResultSizes_Stream_physics->GetXaxis()->SetBinLabel(1, "NoTag"); - m_hist_HltResultSizes_Stream_physics->SetCanExtend(TH1::kAllAxes); - regHistsTProfile.push_back(&m_hist_HltResultSizes_Stream_physics); - - // *-- HLT result size profile plot for all stream names "DataScouting" - m_hist_HltResultSizes_Stream_DataScouting = new TProfile( "Average Hlt Result size for data scouting streams", - "Average Hlt Result size for data scouting streams;Stream Name;Average size in words", - 1, - (double) 0., (double) 1., - (double) 0., (double) 3000000.); - - m_hist_HltResultSizes_Stream_DataScouting->GetXaxis()->SetBinLabel(1, "NoTag"); - m_hist_HltResultSizes_Stream_DataScouting->SetCanExtend(TH1::kAllAxes); - regHistsTProfile.push_back(&m_hist_HltResultSizes_Stream_DataScouting); - - // +-----------------------+ - // *-- | framework error codes | - // +-----------------------+ - uint32_t n_bins_error = hltonl::NUM_PSC_ERROR_CODES; - m_hist_frameworkErrorCodes = new TH1F ("FrameworkErrorCodes", - "FrameworkErrorCodes;;entries", - n_bins_error, 0.5, n_bins_error+0.5); - - for (const auto& m : m_mapPscError) { - m_hist_frameworkErrorCodes->GetXaxis()->SetBinLabel( m.second.second , (m.second.first).c_str() ); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; } - regHistsTH1F.push_back(&m_hist_frameworkErrorCodes); - - // +-------------+ - // *-- | Stream Tags | - // +-------------+ - // *-- number of set stream tags - m_hist_numStreamTags = new TH1F ((m_histProp_numStreamTags.value().title()).c_str(), - (m_histProp_numStreamTags.value().title() + ";tags;entries").c_str(), - m_histProp_numStreamTags.value().bins(), - m_histProp_numStreamTags.value().lowEdge(), - m_histProp_numStreamTags.value().highEdge()); - regHistsTH1F.push_back(&m_hist_numStreamTags); - - - // *-- stream tag types - uint32_t n_bins_tag = eformat::helper::TagTypeDictionary.size() + 1; - m_hist_streamTagTypes = new TH1F ("StreamTagTypes", - "StreamTagTypes;tags;entries", n_bins_tag, -0.5 , n_bins_tag-0.5); - - using eformat::helper::tagtype_to_string; - for(uint32_t i=0; i < n_bins_tag; i++ ) { // StreamTag labels - uint32_t bit = (1u << i); - m_hist_streamTagTypes->GetXaxis()->SetBinLabel( i+1, tagtype_to_string( static_cast<eformat::TagType>(bit) ).c_str() ); + catch(const ptree_bad_path & e) + { + ATH_MSG_ERROR(ST_WHERE << "Bad ptree path: \"" << e.path<ptree::path_type>().dump() << "\" - " << e.what()); } - m_hist_streamTagTypes->GetXaxis()->SetBinLabel(n_bins_tag, "NoTag(=Rejected)"); - regHistsTH1F.push_back(&m_hist_streamTagTypes); - - - // *-- stream tag names - m_hist_streamTagNames = new TH1F ((m_histProp_streamTagNames.value().title()).c_str(), - (m_histProp_streamTagNames.value().title() + ";tags;entries").c_str(), - m_histProp_streamTagNames.value().bins(), - m_histProp_streamTagNames.value().lowEdge(), - m_histProp_streamTagNames.value().highEdge()); - if (m_histProp_streamTagNames.value().bins()>0) { - m_hist_streamTagNames->GetXaxis()->SetBinLabel(1,std::string("NoTag").c_str() ); + catch(const ptree_bad_data & e) + { + ATH_MSG_ERROR(ST_WHERE << "Bad ptree data: \"" << e.data<ptree::data_type>() << "\" - " << e.what()); } - m_hist_streamTagNames->SetCanExtend(TH1::kAllAxes); - regHistsTH1F.push_back(&m_hist_streamTagNames); - - // +------------------------+ - // *-- | Partial event building | - // +------------------------+ - // *-- number of bins for sub detector plots (55 SubDet max.) - uint32_t n_bins_partEBSubDet = eformat::helper::SubDetectorDictionary.size(); - - // *-- number of ROBs for partial event building - m_hist_num_partial_eb_robs = new TH1F ((m_histProp_num_partial_eb_robs.value().title()).c_str(), - (m_histProp_num_partial_eb_robs.value().title() + ";robs;entries").c_str(), - m_histProp_num_partial_eb_robs.value().bins(), - m_histProp_num_partial_eb_robs.value().lowEdge(), - m_histProp_num_partial_eb_robs.value().highEdge()); - - regHistsTH1F.push_back(&m_hist_num_partial_eb_robs); - - - // *-- number of SubDetectors used in partial event building - m_hist_num_partial_eb_SubDetectors = new TH1F ("NumberSubDetectorsPartialEB", - "NumberSubDetectorsPartialEB;subdet;entries", - n_bins_partEBSubDet,-0.5,(float) n_bins_partEBSubDet-0.5); - regHistsTH1F.push_back(&m_hist_num_partial_eb_SubDetectors); - - // *-- SubDetectors used in partial event building: ROB list - m_hist_partial_eb_SubDetectors_ROBs = new TH1F ("SubDetectorsPartialEBFromROBList", - "SubDetectorsPartialEBFromROBList;;entries", - n_bins_partEBSubDet,0.,(float) n_bins_partEBSubDet); - uint32_t n_tmp_bin = 1; - for (const auto& sub : eformat::helper::SubDetectorDictionary) { - m_hist_partial_eb_SubDetectors_ROBs->GetXaxis()->SetBinLabel( n_tmp_bin++, sub.second.c_str() ); + catch(const std::runtime_error& e) + { + ATH_MSG_ERROR(ST_WHERE << "Runtime error: " << e.what()); } - regHistsTH1F.push_back(&m_hist_partial_eb_SubDetectors_ROBs); - // *-- SubDetectors used in partial event building: SD list - m_hist_partial_eb_SubDetectors_SDs = new TH1F ("SubDetectorsPartialEBFromSDList", - "SubDetectorsPartialEBFromSDList;;entries", - n_bins_partEBSubDet,0.,(float) n_bins_partEBSubDet); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::FAILURE; +} + +// ============================================================================= +// Implementation of ITrigEventLoopMgr::hltUpdateAfterFork +// ============================================================================= +StatusCode HltEventLoopMgr::hltUpdateAfterFork(const ptree& /*pt*/) +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); - n_tmp_bin = 1; - for (const auto& sub: eformat::helper::SubDetectorDictionary) { - m_hist_partial_eb_SubDetectors_SDs->GetXaxis()->SetBinLabel( n_tmp_bin++, sub.second.c_str() ); - } - regHistsTH1F.push_back(&m_hist_partial_eb_SubDetectors_SDs); - - - // +---------------+ - // *-- | HLT EDM Sizes | - // +---------------+ - // *-- EDM sizes for all events without a truncated HLT result - m_hist_HltEdmSizes_No_Truncation = - new TProfile( (m_histProp_Hlt_Edm_Sizes.value().title()+":Events_Without_Truncation").c_str(), - (m_histProp_Hlt_Edm_Sizes.value().title()+":Events_Without_Truncation;;Average size in words").c_str(), - m_histProp_Hlt_Edm_Sizes.value().bins(), 0., m_histProp_Hlt_Edm_Sizes.value().bins(), - m_histProp_Hlt_Edm_Sizes.value().lowEdge(), m_histProp_Hlt_Edm_Sizes.value().highEdge()); - - n_tmp_bin = 1; - for (const std::string& col_name : m_hltEdmCollectionNames.value()) { - m_hist_HltEdmSizes_No_Truncation->GetXaxis()->SetBinLabel( n_tmp_bin++, col_name.c_str() ); - } - regHistsTProfile.push_back(&m_hist_HltEdmSizes_No_Truncation); - - // *-- EDM sizes for all events with a truncated HLT result - m_hist_HltEdmSizes_With_Truncation = - new TProfile( (m_histProp_Hlt_Edm_Sizes.value().title()+":Events_With_Truncation").c_str(), - (m_histProp_Hlt_Edm_Sizes.value().title()+":Events_With_Truncation;;Average size in words").c_str(), - m_histProp_Hlt_Edm_Sizes.value().bins(), 0., m_histProp_Hlt_Edm_Sizes.value().bins(), - m_histProp_Hlt_Edm_Sizes.value().lowEdge(), m_histProp_Hlt_Edm_Sizes.value().highEdge()); - - n_tmp_bin = 1; - for (const std::string& col_name : m_hltEdmCollectionNames.value()) { - m_hist_HltEdmSizes_With_Truncation->GetXaxis()->SetBinLabel( n_tmp_bin++, col_name.c_str() ); - } - regHistsTProfile.push_back(&m_hist_HltEdmSizes_With_Truncation); - - // *-- Sizes of collections which were retained for events with a truncated HLT result - m_hist_HltEdmSizes_TruncatedResult_Retained_Collections = - new TProfile( "Events_With_HLTResult_Truncation:Size_of_Not_Truncated_Collections", - "Events_With_HLTResult_Truncation:Size_of_Not_Truncated_Collections;;Average size in words", - m_histProp_Hlt_Edm_Sizes.value().bins(), 0., m_histProp_Hlt_Edm_Sizes.value().bins(), - m_histProp_Hlt_Edm_Sizes.value().lowEdge(), m_histProp_Hlt_Edm_Sizes.value().highEdge()); - - n_tmp_bin = 1; - for (const std::string& col_name : m_hltEdmCollectionNames.value()) { - m_hist_HltEdmSizes_TruncatedResult_Retained_Collections->GetXaxis()->SetBinLabel( n_tmp_bin++, col_name.c_str() ); + ATH_MSG_DEBUG("Initialising the scheduler after forking"); + m_schedulerSvc = serviceLocator()->service(m_schedulerName, /*createIf=*/ true); + if ( !m_schedulerSvc.isValid()){ + ATH_MSG_FATAL("Error retrieving " << m_schedulerName << " interface ISchedulerSvc"); + return StatusCode::FAILURE; } - regHistsTProfile.push_back(&m_hist_HltEdmSizes_TruncatedResult_Retained_Collections); - - // *-- Sizes of collections which were truncated for events with a truncated HLT result - m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections = - new TProfile( "Events_With_HLTResult_Truncation:Size_of_Truncated_Collections", - "Events_With_HLTResult_Truncation:Size_of_Truncated_Collections;;Average size in words", - m_histProp_Hlt_Edm_Sizes.value().bins(), 0., m_histProp_Hlt_Edm_Sizes.value().bins(), - m_histProp_Hlt_Edm_Sizes.value().lowEdge(), - m_histProp_Hlt_Edm_Sizes.value().highEdge()); - - n_tmp_bin = 1; - for (const std::string& col_name : m_hltEdmCollectionNames.value()) { - m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections->GetXaxis()->SetBinLabel( n_tmp_bin++, col_name.c_str() ); + ATH_MSG_DEBUG("Initialised " << m_schedulerName << " interface ISchedulerSvc"); + + ATH_MSG_DEBUG("Trying a stop-start of CoreDumpSvc"); + SmartIF<IService> svc = serviceLocator()->service("CoreDumpSvc", /*createIf=*/ false); + if (svc.isValid()) { + svc->stop(); + svc->start(); + ATH_MSG_DEBUG("Done a stop-start of CoreDumpSvc"); } - regHistsTProfile.push_back(&m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections); - - // +---------------------+ - // *-- | register histograms | - // +---------------------+ - // *-- TH1F - for (TH1F** hist : regHistsTH1F) { - if ( *hist && m_THistSvc->regHist(histPath + (*hist)->GetName(), (*hist)).isFailure() ) { - msgStream() << MSG::WARNING << "Cannot register histogram " << (*hist)->GetName() << endmsg; - delete (*hist); - *hist = 0; - } + else { + ATH_MSG_WARNING("Could not retrieve CoreDumpSvc"); } - // *-- TProfile - for (TProfile** hist : regHistsTProfile) { - if ( *hist && m_THistSvc->regHist(histPath + (*hist)->GetName(), (*hist)).isFailure() ) { - msgStream() << MSG::WARNING << "Cannot register histogram " << (*hist)->GetName() << endmsg; - delete (*hist); - *hist = 0; - } + + // Start the timeout thread + ATH_MSG_DEBUG("Starting the timeout thread"); + m_timeoutThread.reset(new std::thread(std::bind(&HltEventLoopMgr::runEventTimer,this))); + + // Initialise vector of time points for event timeout monitoring + { + std::unique_lock<std::mutex> lock(m_timeoutMutex); + m_eventTimerStartPoint.clear(); + m_eventTimerStartPoint.resize(m_whiteboard->getNumberOfStores(), std::chrono::steady_clock::time_point()); + m_isSlotProcessing.resize(m_whiteboard->getNumberOfStores(), false); } + m_timeoutCond.notify_all(); + + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; } -//========================================================================= -void HltEventLoopMgr::HltBookHistograms() +// ============================================================================= +// Implementation of IEventProcessor::executeRun +// ============================================================================= +StatusCode HltEventLoopMgr::executeRun(int maxevt) { - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << "---> HltBookHistograms() for " << name() - << " called. Do monitoring = " << m_doMonitoring.value() << endmsg; + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + StatusCode sc = nextEvent(maxevt); + if (sc.isFailure()) { + ATH_MSG_ERROR("Event loop failed"); + // some special cleanup here? } - // return if no monitoring is requested - if ( !m_doMonitoring.value() ) { return; } + // do some cleanup here - // monitoring information root directory - std::string path = std::string("/EXPERT/") + name() + "/"; - - // *-- SubDetectors from l1 ROBs - auto nbins = L1R_BINS.size() + 2; - m_hist_l1_robs = new TH1F ("HLTROBsReceivedFromL1", - "HLTROBsReceivedFromL1;;entries", - nbins, - 0., - static_cast<double>(nbins)); - - // Set labels from L1R_BINS - unsigned short i = 0; - while(i < L1R_BINS.size()) + // Stop the timer thread { - auto sid = eformat::helper::SourceIdentifier(L1R_BINS[i], 0); - m_hist_l1_robs->GetXaxis()->SetBinLabel(++i, sid.human_detector().c_str()); + ATH_MSG_DEBUG("Stopping the timeout thread"); + std::unique_lock<std::mutex> lock(m_timeoutMutex); + m_runEventTimer = false; } + m_timeoutCond.notify_all(); + m_timeoutThread->join(); + ATH_MSG_DEBUG("The timeout thread finished"); - // Add a label for unexpected robs and another for missing CTP fragment - m_hist_l1_robs->GetXaxis()->SetBinLabel(++i, UNEXPECTED_L1R_ROB_LABEL); - m_hist_l1_robs->GetXaxis()->SetBinLabel(++i, MISSING_L1R_CTP_LABEL); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return sc; +} - // Register it - if(m_THistSvc->regHist(path + m_hist_l1_robs->GetName(), m_hist_l1_robs).isFailure()) - { - msgStream() << MSG::WARNING << "Can not register monitoring histogram: " - << m_hist_l1_robs->GetName() << endmsg; - } -} // end method HltEventLoopMgr::HltBookHistograms +// ============================================================================= +// Implementation of IEventProcessor::nextEvent +// maxevt is not used - we always want to process all events delivered +// ============================================================================= +StatusCode HltEventLoopMgr::nextEvent(int /*maxevt*/) +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + + ATH_MSG_INFO("Starting loop on events"); + bool loop_ended = false; + bool events_available = true; // DataCollector has more events + + while (!loop_ended) { + ATH_MSG_DEBUG("Free slots = " << m_schedulerSvc->freeSlots()); + if (m_schedulerSvc->freeSlots()>0 && events_available) { + ATH_MSG_DEBUG("Free slots = " << m_schedulerSvc->freeSlots() << ". Reading the next event."); + + eformat::write::FullEventFragment l1r; // to be removed + + //------------------------------------------------------------------------ + // Create new EventContext + //------------------------------------------------------------------------ + ++m_nevt; + EventContext* evtContext = nullptr; + if (createEventContext(evtContext).isFailure()){ + ATH_MSG_ERROR("Failed to create event context"); + // what do we do now? we haven't requested the next event from DataCollector yet, + // we have a failure while not processing an event + failedEvent(evtContext); + continue; + } -//========================================================================= -void HltEventLoopMgr::fillHltResultHistograms(const hltinterface::HLTResult& hlt_result) -{ - if ( msgLevel() <= MSG::DEBUG ) { - msgStream() << MSG::DEBUG << "---> fillHltResultHistograms(hltinterface::HLTResult& hlt_result) for " << name() << " called " << endmsg; - } + // do we need this duplication? it's selected already in createEventContext + if (m_whiteboard->selectStore(evtContext->slot()).isFailure()){ + ATH_MSG_ERROR("Slot " << evtContext->slot() << " could not be selected for the WhiteBoard"); + // what do we do now? we haven't requested the next event from DataCollector yet, + // we have a failure while not processing an event + failedEvent(evtContext); + continue; + } - // return if no monitoring is requested - if ( !m_doMonitoring.value() ) { return; } + // Record EventContext in current whiteboard + if (m_evtStore->record(std::make_unique<EventContext> (*evtContext), "EventContext").isFailure()) { + ATH_MSG_ERROR("Error recording event context object"); + // what do we do now? we haven't requested the next event from DataCollector yet, + // we have a failure while not processing an event + failedEvent(evtContext); + continue; + } - // +-----------------------+ - // *-- | HLT result properties | - // +-----------------------+ - if ( (hlt_result.fragment_pointer != 0) && ( (*hlt_result.fragment_pointer) != 0 ) ) { - eformat::ROBFragment<uint32_t*> hltrob(hlt_result.fragment_pointer); - uint16_t hltrob_moduleID = eformat::helper::SourceIdentifier( hltrob.rob_source_id() ).module_id(); + // Not so nice behind-the-scenes way to inform some services about the current context. + // If possible, services should use EventContext from the event store as recorded above. + Gaudi::Hive::setCurrentContext(*evtContext); + + //------------------------------------------------------------------------ + // Create a new address for EventInfo to facilitate automatic conversion from input data + //------------------------------------------------------------------------ + IOpaqueAddress* addr = nullptr; + if (m_evtSelector->createAddress(*m_evtSelContext, addr).isFailure()) { + ATH_MSG_ERROR("Could not create an IOpaqueAddress"); + // we have not read a new event yet, should we try to create any output? + failedEvent(evtContext); + continue; + } - // *-- HLT result size plots - if (hltrob_moduleID == 0) { - lock_histogram_operation<TH1F>(m_hist_Hlt_result_size)->Fill( (float) hltrob.fragment_size_word() ) ; - } + //------------------------------------------------------------------------ + // Get the next event + //------------------------------------------------------------------------ + StatusCode sc = StatusCode::SUCCESS; + try { + sc = m_evtSelector->next(*m_evtSelContext); + } + catch (const hltonl::Exception::NoMoreEvents& e) { + sc = StatusCode::SUCCESS; + events_available = false; + sc = clearWBSlot(evtContext->slot()); + if (sc.isFailure()) { + ATH_MSG_WARNING("Failed to clear the whiteboard slot " << evtContext->slot() + << " after NoMoreEvents detected"); + // do we need to do anything here? + } + continue; + } + catch (...) { + sc = StatusCode::FAILURE; + } + if (sc.isFailure()) { + ATH_MSG_ERROR("Failed to get the next event"); + // we called getNext and some failure happened, but we don't know the event number + // should we return anything to the DataCollector? + failedEvent(evtContext); + continue; + } - int xbins_physics = m_hist_HltResultSizes_Stream_physics->GetNbinsX(); - int xbins_DS = m_hist_HltResultSizes_Stream_DataScouting->GetNbinsX(); - { - scoped_lock_histogram lock; - for (const eformat::read::ROBFragment& rob : hlt_result.hltResult_robs) { - uint16_t moduleID = eformat::helper::SourceIdentifier( rob.rob_source_id() ).module_id(); - for (const eformat::helper::StreamTag& st : hlt_result.stream_tag) { - // only normal HLT Results - if (moduleID == 0) { - if (st.type == "physics") { - if (st.name == "Main") m_hist_Hlt_result_size_physics->Fill( (float) rob.fragment_size_word() ) ; - m_hist_HltResultSizes_Stream_physics->Fill( st.name.c_str(), (double) rob.fragment_size_word() ) ; - } - if (st.type == "express") { - m_hist_Hlt_result_size_express->Fill( (float) rob.fragment_size_word() ) ; - } - } - // DataScouting HLT ROBs - if (moduleID != 0) { - if ((st.type == "calibration") && ((st.name).find("DataScouting_") != std::string::npos)) { - m_hist_Hlt_result_size_DataScouting->Fill( (float) rob.fragment_size_word() ) ; - m_hist_HltResultSizes_Stream_DataScouting->Fill( st.name.c_str(), (double) rob.fragment_size_word() ) ; - } - } + //------------------------------------------------------------------------ + // Set event processing start time for timeout monitoring and reset timeout flag + //------------------------------------------------------------------------ + { + std::unique_lock<std::mutex> lock(m_timeoutMutex); + m_eventTimerStartPoint[evtContext->slot()] = std::chrono::steady_clock::now(); + m_isSlotProcessing[evtContext->slot()] = true; + resetTimeout(Athena::Timeout::instance(*evtContext)); + } + m_timeoutCond.notify_all(); + + //------------------------------------------------------------------------ + // Load event proxies and get event info + //------------------------------------------------------------------------ + + if (addr != nullptr) { + /* do we need this??? + sc = m_evtStore->recordAddress(addr); + if (sc.isFailure()) { + ATH_MSG_WARNING("Failed to record IOpaqueAddress in the event store"); + // we cannot get the EventInfo, so we don't know the event number + // should we return anything to the DataCollector? + // failedEvent(evtContext); } - } + */ + sc = m_evtStore->loadEventProxies(); + if (sc.isFailure()) { + ATH_MSG_ERROR("Failed to load event proxies"); + // we cannot get the EventInfo, so we don't know the event number + // should we return anything to the DataCollector? + failedEvent(evtContext); + } + } - // deflate bins for profile histograms if needed - if ( m_hist_HltResultSizes_Stream_physics->GetNbinsX()!=xbins_physics ) { - m_hist_HltResultSizes_Stream_physics->LabelsDeflate("X"); + const EventInfo* oldEventInfo = nullptr; + sc = m_evtStore->retrieve(oldEventInfo); + if (sc.isFailure()) { + ATH_MSG_ERROR("Failed to retrieve EventInfo"); + // we cannot get the EventInfo, so we don't know the event number + // should we return anything to the DataCollector? + failedEvent(evtContext); } - if ( m_hist_HltResultSizes_Stream_DataScouting->GetNbinsX()!=xbins_DS ) { - m_hist_HltResultSizes_Stream_DataScouting->LabelsDeflate("X"); + + // convert EventInfo to xAOD::EventInfo using a cnv tool explicitly, like in EventInfoCnvAlg + // - this should be done by an automatic conversion through proxy in the future, + // replacing the code above and below + SG::WriteHandle<xAOD::EventInfo> eventInfoWH(m_xEventInfoWHKey, *evtContext); + if (eventInfoWH.record( + std::make_unique<xAOD::EventInfo>(), + std::make_unique<xAOD::EventAuxInfo>() + ).isFailure()) { + ATH_MSG_ERROR("Failed to record xAOD::EventInfo in event store"); + failedEvent(evtContext); } - } - // *-- HLT result status codes - if ((hltrob.nstatus() > 1) && (hltrob_moduleID == 0)) { - scoped_lock_histogram lock; - const uint32_t* it; - hltrob.status(it); - m_hist_Hlt_result_status->Fill( (float) m_mapResultStatus.codeToHash( (hltonl::ResultStatusCode) *(it+1)) ); - } - } + xAOD::EventInfo* eventInfo = eventInfoWH.ptr(); + if (m_eventInfoCnvTool->convert(oldEventInfo, eventInfo).isFailure()) { + ATH_MSG_ERROR("Failed to convert EventInfo to xAOD::EventInfo"); + failedEvent(evtContext); + } - // +-----------------------+ - // *-- | framework error codes | - // +-----------------------+ - if (hlt_result.psc_errors.size() > 0) { - scoped_lock_histogram lock; - for (uint32_t ec : hlt_result.psc_errors) { - m_hist_frameworkErrorCodes->Fill( (float) m_mapPscError.codeToHash( (hltonl::PSCErrorCode) ec) ); - } - } + ATH_MSG_DEBUG("Retrieved event info for the new event " << *eventInfo); + + // create EventIDBase for the EventContext + EventIDBase eid(eventInfo->runNumber(), + eventInfo->eventNumber(), + eventInfo->timeStamp(), + eventInfo->timeStampNSOffset(), + eventInfo->lumiBlock(), + eventInfo->bcid()); + evtContext->setEventID(eid); + + // set run number for conditions + evtContext->template getExtension<Atlas::ExtendedEventContext>()->setConditionsRun(m_currentRun); + + // update thread-local EventContext after setting EventID and conditions runNumber + Gaudi::Hive::setCurrentContext(*evtContext); + + //------------------------------------------------------------------------ + // Record an empty HLT Result + //------------------------------------------------------------------------ + // auto hltResult = new HLT::HLTResultMT; + // hltResult->getExtraData().appName = m_applicationName.value(); + // m_evtStore->record(hltResult, m_HltResultName, /*allowMods=*/ true); + + //------------------------------------------------------------------------ + // Process the event + //------------------------------------------------------------------------ + if (executeEvent(evtContext).isFailure()) { + ATH_MSG_ERROR("Error processing event"); + failedEvent(evtContext,eventInfo); + continue; + } - // +-------------+ - // *-- | Stream Tags | - // +-------------+ - // number of set stream tags - m_hist_numStreamTags->Fill( (float) hlt_result.stream_tag.size() ); + //------------------------------------------------------------------------ + // Set ThreadLocalContext to an invalid context + //------------------------------------------------------------------------ + // We have passed the event to the scheduler and we are entering back a context-less environment + Gaudi::Hive::setCurrentContext( EventContext() ); - // stream tag types - if(hlt_result.stream_tag.empty()) { - m_hist_streamTagTypes->Fill( (float) m_hist_streamTagTypes->GetXaxis()->GetNbins() - 1. ); - } - using namespace eformat::helper; - for(int32_t i=0; i < m_hist_streamTagTypes->GetXaxis()->GetNbins(); i++) { - uint32_t bit = (1u<<i); - if( contains_type(hlt_result.stream_tag, static_cast<eformat::TagType>(bit)) ) { - m_hist_streamTagTypes->Fill( (float) i); } - } - - // stream tag names - if(hlt_result.stream_tag.empty()) { - m_hist_streamTagNames->Fill(0.); - } else { - int xbins = m_hist_streamTagNames->GetNbinsX(); - scoped_lock_histogram lock; - for(const eformat::helper::StreamTag& st: hlt_result.stream_tag) { - m_hist_streamTagNames->Fill(st.name.c_str(),1.); + else { + ATH_MSG_DEBUG("No free slots or no more events to process - draining the scheduler"); + int ir = drainScheduler(); + if (ir<0) { + ATH_MSG_ERROR("Error draining scheduler"); + continue; + } + else if (ir==0 && !events_available) { + ATH_MSG_INFO("All events processed, finalising the event loop"); + loop_ended = true; + } } - // Remove extra empty bins if needed - if ( m_hist_streamTagNames->GetNbinsX()!=xbins ) - m_hist_streamTagNames->LabelsDeflate("X"); - } - - // +------------------------+ - // *-- | Partial Event Building | - // +------------------------+ - // *-- loop over stream tags and get total number of ROBs and SDs - uint32_t num_robs(0), num_sd(0); - std::set<uint32_t> peb_robs; - std::set<eformat::SubDetector> peb_sd; - for (const eformat::helper::StreamTag& st : hlt_result.stream_tag) { - num_robs = num_robs + (st.robs).size(); - num_sd = num_sd + (st.dets).size(); - peb_robs.insert( (st.robs).begin(),(st.robs).end() ); - peb_sd.insert( (st.dets).begin(),(st.dets).end() ); } - // *-- number of ROBs for partial event building - m_hist_num_partial_eb_robs->Fill( (float) num_robs); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} - // *-- number of SubDetectors for partial event building - m_hist_num_partial_eb_SubDetectors->Fill( (float) num_sd); +// ============================================================================= +// Implementation of IEventProcessor::stopRun (obsolete for online runnning) +// ============================================================================= +StatusCode HltEventLoopMgr::stopRun() { + ATH_MSG_FATAL("Misconfiguration - the method HltEventLoopMgr::stopRun() cannot be used online"); + return StatusCode::FAILURE; +} - // *-- SubDetectors for partial event building in ROB list - for(uint32_t rob : peb_robs) { - m_hist_partial_eb_SubDetectors_ROBs->Fill(eformat::helper::SourceIdentifier(rob).human_detector().c_str(),1.); - } +// ============================================================================= +// Implementation of IEventProcessor::executeEvent +// ============================================================================= +StatusCode HltEventLoopMgr::executeEvent(void* pEvtContext) +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); - // *-- SubDetectors for partial event building in SD list - for (const eformat::SubDetector& sd : peb_sd) { - m_hist_partial_eb_SubDetectors_SDs->Fill(eformat::helper::SourceIdentifier(sd,0).human_detector().c_str(),1.); + EventContext* evtContext = static_cast<EventContext*>(pEvtContext); + if (!evtContext) { + ATH_MSG_ERROR("Failed to cast the call parameter to EventContext*"); + return StatusCode::FAILURE; } - return; -} // end method HltEventLoopMgr::fillHltResultHistograms + resetTimeout(Athena::Timeout::instance(*evtContext)); -//========================================================================= -void HltEventLoopMgr::bookAllHistograms() -{ - // Book the monitoring histograms - HltBookHistograms(); // (histograms that were booked differently in l2/ef) - // Book own histograms - bookHistograms(); -} + // Now add event to the scheduler + ATH_MSG_DEBUG("Adding event " << evtContext->evt() << ", slot " << evtContext->slot() << " to the scheduler"); + StatusCode addEventStatus = m_schedulerSvc->pushNewEvent(evtContext); -//========================================================================= -StatusCode -HltEventLoopMgr::callOnAlgs(const function<StatusCode(IAlgorithm&)> & func, - const string & fname, bool failureIsError) -{ - StatusCode sc; - for(auto alg : m_topAlgList) - { - if(func(*alg).isFailure()) - { - msgStream() << (failureIsError ? MSG::ERROR : MSG::WARNING) << ST_WHERE - << "Calling " << fname << "() on algorithm " << alg->name() - << " failed" << endmsg; - sc = StatusCode::FAILURE; - if(failureIsError) - break; - } + // If this fails, we need to wait for something to complete + if (!addEventStatus.isSuccess()){ + ATH_MSG_ERROR("Failed adding event " << evtContext->evt() << ", slot " << evtContext->slot() + << " to the scheduler"); + return StatusCode::FAILURE; } - return sc; + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; } -//========================================================================= -StatusCode HltEventLoopMgr::prepareAlgs(const EventInfo& evinfo) +// ============================================================================= +void HltEventLoopMgr::updateDFProps() { - auto suc1 = callOnAlgs(&IAlgorithm::sysStart, "sysStart").isSuccess(); - m_incidentSvc->fireIncident(EventIncident(evinfo, name(), - IncidentType::BeginRun)); - auto suc2 = callOnAlgs(&IAlgorithm::sysBeginRun, "sysBeginRun").isSuccess(); - m_incidentSvc->fireIncident(EventIncident(evinfo, name(), "EndOfBeginRun")); + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + ServiceHandle<IJobOptionsSvc> p_jobOptionsSvc("JobOptionsSvc", name()); + if ((p_jobOptionsSvc.retrieve()).isFailure()) { + ATH_MSG_WARNING("Could not find JobOptionsSvc to set DataFlow properties"); + } else { + auto dfprops = p_jobOptionsSvc->getProperties("DataFlowConfig"); - return (suc1 && suc2) ? StatusCode::SUCCESS : StatusCode::FAILURE; -} + // Application name + auto pname = "DF_ApplicationName"; + const auto * prop = Gaudi::Utils::getProperty(dfprops, pname); + if(prop && m_applicationName.assign(*prop)) { + ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: " << m_applicationName); + } else { + ATH_MSG_WARNING("Could not set Property '" << pname << "' from DataFlow"); + } -//========================================================================= -StatusCode HltEventLoopMgr::internalPrepareResets() -{ - m_currentEvent = nullptr; // no time out would make sense here, so not locking - m_currentLB = 0; - if (m_predefinedLumiBlock > 0) - { - m_currentLB = m_predefinedLumiBlock; - msgStream() << MSG::DEBUG << ST_WHERE - << "Using predefined lumi block " << m_currentLB << endmsg; - } + // Partition name + pname = "DF_PartitionName"; + prop = Gaudi::Utils::getProperty(dfprops, pname); + if (prop && m_partitionName.assign(*prop)) { + ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: " << m_partitionName); + } else { + ATH_MSG_WARNING("Could not set Property '" << pname << "' from DataFlow"); + } + + // get the list of enabled ROBs + pname = "DF_Enabled_ROB_IDs"; + prop = Gaudi::Utils::getProperty(dfprops, pname); + if (prop && m_enabledROBs.assign(*prop)) { + ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: " + << m_enabledROBs.value().size() << " enabled ROB IDs"); + } else { + // this is only info, because it is normal in athenaHLT + ATH_MSG_INFO("Could not set Property '" << pname << "' from DataFlow"); + } - // The real CTP counter only has 16 bits and never reaches this value - m_l1_hltPrescaleUpdateLB = 0xffffffff; + // get the list of enabled Sub Detectors + pname = "DF_Enabled_SubDet_IDs"; + prop = Gaudi::Utils::getProperty(dfprops, pname); + if (prop && m_enabledSubDetectors.assign(*prop)) { + ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: " + << m_enabledSubDetectors.value().size() << " enabled Sub Detector IDs"); + } else { + // this is only info, because it is normal in athenaHLT + ATH_MSG_INFO("Could not set Property '" << pname << "' from DataFlow"); + } + } - return clearTemporaryStores(); + p_jobOptionsSvc.release().ignore(); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); } -//========================================================================= -const SOR * HltEventLoopMgr::processRunParams(const ptree & pt) +// ============================================================================= +const SOR* HltEventLoopMgr::processRunParams(const ptree & pt) { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); // update the run number m_currentRun = pt.get<uint32_t>("RunParams.run_number"); - ATH_CHECK(installEventContext(nullptr, m_currentRun), nullptr); + // need to provide an event context extended with a run number, down the line passed to IOVDBSvc::signalBeginRun + EventContext runStartEventContext = {}; // with invalid evt number and slot number + runStartEventContext.setExtension(Atlas::ExtendedEventContext(m_evtStore->hiveProxyDict(), m_currentRun)); // Fill SOR parameters from the ptree TrigSORFromPtreeHelper sorhelp{msgStream()}; - auto sor = sorhelp.fillSOR(pt.get_child("RunParams"), m_eventContext); - if(!sor) - msgStream() << MSG::ERROR << ST_WHERE - << "setup of SOR from ptree failed" << endmsg; + const SOR* sor = sorhelp.fillSOR(pt.get_child("RunParams"),runStartEventContext); + if(!sor) { + ATH_MSG_ERROR(ST_WHERE << "setup of SOR from ptree failed"); + } + ATH_MSG_VERBOSE("end of " << __FUNCTION__); return sor; } -//========================================================================= -void HltEventLoopMgr::updInternal(const coral::AttributeList & sor_attrlist) +// ============================================================================= +void HltEventLoopMgr::updateInternal(const coral::AttributeList & sor_attrlist) { auto detMaskFst = sor_attrlist["DetectorMaskFst"].data<unsigned long long>(); auto detMaskSnd = sor_attrlist["DetectorMaskSnd"].data<unsigned long long>(); - updDetMask({detMaskFst, detMaskSnd}); + updateDetMask({detMaskFst, detMaskSnd}); - auto sorTime = sor_attrlist["SORTime"].data<unsigned long long>(); - updSorTime(sorTime); + // auto sorTime = sor_attrlist["SORTime"].data<unsigned long long>(); + // updSorTime(sorTime); if(msgLevel() <= MSG::DEBUG) { // save current stream flags for later reset // cast needed (stream thing returns long, but doesn't take it back) - auto previous_stream_flags = - static_cast<std::ios::fmtflags>(msgStream().flags()); - msgStream() << MSG::DEBUG << ST_WHERE - << "Full detector mask (128 bits) = 0x" - << MSG::hex << std::setfill('0') - << std::setw(8) << std::get<3>(m_detector_mask) - << std::setw(8) << std::get<2>(m_detector_mask) - << std::setw(8) << std::get<1>(m_detector_mask) - << std::setw(8) << std::get<0>(m_detector_mask) << endmsg; + auto previous_stream_flags = static_cast<std::ios::fmtflags>(msgStream().flags()); + ATH_MSG_DEBUG(ST_WHERE + << "Full detector mask (128 bits) = 0x" + << MSG::hex << std::setfill('0') + << std::setw(8) << std::get<3>(m_detector_mask) + << std::setw(8) << std::get<2>(m_detector_mask) + << std::setw(8) << std::get<1>(m_detector_mask) + << std::setw(8) << std::get<0>(m_detector_mask)); msgStream().flags(previous_stream_flags); - msgStream() << MSG::DEBUG << ST_WHERE - << "sorTimeStamp[0] [sec] = " << m_sorTime_stamp[0] << endmsg; - msgStream() << MSG::DEBUG << ST_WHERE - << "sorTimeStamp[1] [ns] = " << m_sorTime_stamp[1] << endmsg; + // ATH_MSG_DEBUG(ST_WHERE << "sorTimeStamp[0] [sec] = " << m_sorTime_stamp[0]); + // ATH_MSG_DEBUG(ST_WHERE << "sorTimeStamp[1] [ns] = " << m_sorTime_stamp[1]); } } -//========================================================================= -void HltEventLoopMgr::updMetadaStore(const coral::AttributeList & sor_attrlist) +// ============================================================================= +void HltEventLoopMgr::updateMetadataStore(const coral::AttributeList & sor_attrlist) const { // least significant part is "snd" in sor but "fst" for ByteStreamMetadata auto bs_dm_fst = sor_attrlist["DetectorMaskSnd"].data<unsigned long long>(); @@ -2523,613 +963,416 @@ void HltEventLoopMgr::updMetadaStore(const coral::AttributeList & sor_attrlist) std::vector<std::string>()); // Record ByteStreamMetadata in MetaData Store - if(m_inputMetaDataStore->record(metadata,"ByteStreamMetadata").isFailure()) - { - msgStream() << MSG::WARNING << ST_WHERE - << "Unable to record MetaData in InputMetaDataStore." - << endmsg; + if(m_inputMetaDataStore->record(metadata,"ByteStreamMetadata").isFailure()) { + ATH_MSG_WARNING(ST_WHERE << "Unable to record MetaData in InputMetaDataStore"); delete metadata; } - else - msgStream() << MSG::DEBUG << ST_WHERE - << "Recorded MetaData in InputMetaDataStore." << endmsg; + else { + ATH_MSG_DEBUG(ST_WHERE << "Recorded MetaData in InputMetaDataStore"); + } + } -//========================================================================= +// ============================================================================== StatusCode HltEventLoopMgr::clearTemporaryStores() { - //----------------------------------------------------------------------- + //---------------------------------------------------------------------------- // Clear the event store, if used in the event loop - //----------------------------------------------------------------------- + //---------------------------------------------------------------------------- auto sc = m_evtStore->clearStore(); - msgStream() << MSG::DEBUG << ST_WHERE - << "clear of Event Store " << sc << endmsg; + ATH_MSG_DEBUG(ST_WHERE << "clear of Event Store " << sc); if(sc.isFailure()) { - msgStream() << MSG::ERROR << ST_WHERE - << "clear of Event Store failed" << endmsg; + ATH_MSG_ERROR(ST_WHERE << "clear of Event Store failed"); return sc; } - //----------------------------------------------------------------------- + //---------------------------------------------------------------------------- // Clear the InputMetaDataStore - //----------------------------------------------------------------------- + //---------------------------------------------------------------------------- sc = m_inputMetaDataStore->clearStore(); - msgStream() << MSG::DEBUG << ST_WHERE - << "clear of InputMetaDataStore store " << sc << endmsg; + ATH_MSG_DEBUG(ST_WHERE << "clear of InputMetaDataStore store " << sc); if(sc.isFailure()) - msgStream() << MSG::ERROR << ST_WHERE - << "clear of InputMetaDataStore failed" << endmsg; + ATH_MSG_ERROR(ST_WHERE << "clear of InputMetaDataStore failed"); return sc; } -//========================================================================= -void HltEventLoopMgr::updDetMask(const std::pair<uint64_t, uint64_t>& dm) +// ============================================================================= +void HltEventLoopMgr::updateDetMask(const std::pair<uint64_t, uint64_t>& dm) { m_detector_mask = std::make_tuple( - // least significant 4 bytes - static_cast<EventID::number_type>(dm.second), - // next least significant 4 bytes - static_cast<EventID::number_type>(dm.second >> 32), - // next least significant 4 bytes - static_cast<EventID::number_type>(dm.first), - // most significant 4 bytes - static_cast<EventID::number_type>(dm.first >> 32)); + // least significant 4 bytes + static_cast<EventID::number_type>(dm.second), + // next least significant 4 bytes + static_cast<EventID::number_type>(dm.second >> 32), + // next least significant 4 bytes + static_cast<EventID::number_type>(dm.first), + // most significant 4 bytes + static_cast<EventID::number_type>(dm.first >> 32) + ); } -//========================================================================= -void HltEventLoopMgr::updSorTime(unsigned long long st) -{ - m_sorTime_stamp[0]=0; - m_sorTime_stamp[1]=0; - if(st) - { - m_sorTime_stamp[0] = (unsigned int)(st/1000000000); - m_sorTime_stamp[1] = (unsigned int)(st-m_sorTime_stamp[0]*1000000000); - } -} - -namespace -{ - // Helper to print SOR record - void printSORAttrList(const coral::AttributeList& atr, - MsgStream& log, const MSG::Level& lvl) - { - unsigned long long sorTime_ns(atr["SORTime"].data<unsigned long long>()); - - // Human readable format of SOR time if available - time_t sorTime_sec = sorTime_ns/1000000000; - const auto sorTime_readable = OWLTime(sorTime_sec); - - log << lvl << "SOR parameters:" << endmsg; - log << " RunNumber = " - << atr["RunNumber"].data<unsigned int>() << endmsg; - log << " SORTime [ns] = " - << sorTime_ns << " (" << sorTime_readable << ") " << endmsg; - - // save current stream flags for later reset - // cast needed (stream thing returns long, but doesn't take it back) - auto previous_stream_flags = static_cast<std::ios::fmtflags>(log.flags()); - auto dmfst = atr["DetectorMaskFst"].data<unsigned long long>(); - auto dmsnd = atr["DetectorMaskSnd"].data<unsigned long long>(); - log << MSG::hex << std::setfill('0'); - log << " DetectorMaskFst = 0x" << std::setw(16) << dmfst << endmsg; - log << " DetectorMaskSnd = 0x" << std::setw(16) << dmsnd << endmsg; - log << " (complete DetectorMask = 0x" - << std::setw(16) << dmfst << std::setw(16) << dmsnd << ")" << endmsg; - // reset stream flags - log.flags(previous_stream_flags); - - log << " RunType = " - << atr["RunType"].data<std::string>() << endmsg; - log << " RecordingEnabled = " - << (atr["RecordingEnabled"].data<bool>() ? "true" : "false") << endmsg; - } -} - -//========================================================================= -const coral::AttributeList & -HltEventLoopMgr::getSorAttrList(const SOR * sor) const +// ============================================================================== +const coral::AttributeList& HltEventLoopMgr::getSorAttrList(const SOR* sor) const { if(sor->size() != 1) { // This branch should never be entered (the CondAttrListCollection - //corresponding to the SOR should contain one single AttrList). Since - //that's required by code ahead but not checked at compile time, we - //explicitly guard against any potential future mistake with this check - msgStream() << MSG::ERROR << ST_WHERE - << "Wrong SOR: size = " << sor->size() << endmsg; - throw std::runtime_error("SOR record should have one and one only attribute" - " list, but it has " + sor->size()); + // corresponding to the SOR should contain one single AttrList). Since + // that's required by code ahead but not checked at compile time, we + // explicitly guard against any potential future mistake with this check + ATH_MSG_ERROR(ST_WHERE << "Wrong SOR: size = " << sor->size()); + throw std::runtime_error("SOR record should have one and one only attribute list, but it has " + sor->size()); } const auto & soral = sor->begin()->second; - printSORAttrList(soral, msgStream(), MSG::INFO); + printSORAttrList(soral); return soral; } -//========================================================================= -StatusCode HltEventLoopMgr::updHLTConfigSvc() -{ - // Get HLTConfigSvc if available and do sanity check - service("TrigConf::HLTConfigSvc/HLTConfigSvc", - m_hltConfigSvc, /*createIf=*/false).ignore(); - - if ( (m_hltConfigSvc==0) && (m_jobOptionsType.value()=="DB") ) { - msgStream() << MSG::ERROR << ST_WHERE - << "JobOptionsType==DB but could not retrieve HLTConfigSvc" - << endmsg; - return StatusCode::FAILURE; - } - - return StatusCode::SUCCESS; -} - -//========================================================================= -const EventInfo * HltEventLoopMgr::prepEventInfo() const -{ - const EventInfo * pEvent = - new EventInfo(new EventID(m_currentRun, - 0, - m_sorTime_stamp[0], - m_sorTime_stamp[1], - m_currentLB, - 0, - std::get<0>(m_detector_mask), - std::get<1>(m_detector_mask), - std::get<2>(m_detector_mask), - std::get<3>(m_detector_mask)), - new EventType()); - - // Record it in StoreGate - if(m_evtStore->record(pEvent,"EventInfo").isFailure()) - { - msgStream() << MSG::ERROR << ST_WHERE - << "Could not record EventInfo object" << endmsg; - return nullptr; - } - - msgStream() << MSG::DEBUG << ST_WHERE - << "Recorded EventInfo object: " - << *pEvent->event_ID() << endmsg; - - return pEvent; -} - -//========================================================================= -StatusCode HltEventLoopMgr::prepXAODEventInfo() const -{ - auto aux = new xAOD::EventAuxInfo; - auto ev = new xAOD::EventInfo; - ev->setStore(aux); - ev->setRunNumber(m_currentRun); - ev->setEventNumber(0); - ev->setLumiBlock(m_currentLB); - ev->setTimeStamp(m_sorTime_stamp[0]); - ev->setTimeStampNSOffset(m_sorTime_stamp[1]); - ev->setBCID(0); - ev->setDetectorMask0(std::get<0>(m_detector_mask)); - ev->setDetectorMask1(std::get<1>(m_detector_mask)); - ev->setDetectorMask2(std::get<2>(m_detector_mask)); - ev->setDetectorMask3(std::get<3>(m_detector_mask)); - - // Record it in StoreGate - if(m_evtStore->record(aux, "EventInfoAux.").isFailure() || - m_evtStore->record(ev, "EventInfo").isFailure()) - { - msgStream() << MSG::ERROR << ST_WHERE - << "Could not record xAOD::EventInfo object" << endmsg; - - return StatusCode::FAILURE; - } - - msgStream() << MSG::DEBUG << ST_WHERE - << "Recorded xAOD::EventInfo object: " - << *ev << endmsg; - - return StatusCode::SUCCESS; +// ============================================================================== +void HltEventLoopMgr::printSORAttrList(const coral::AttributeList& atr) const +{ + unsigned long long sorTime_ns(atr["SORTime"].data<unsigned long long>()); + + // Human readable format of SOR time if available + time_t sorTime_sec = sorTime_ns/1000000000; + const auto sorTime_readable = OWLTime(sorTime_sec); + + ATH_MSG_INFO("SOR parameters:"); + ATH_MSG_INFO(" RunNumber = " << atr["RunNumber"].data<unsigned int>()); + ATH_MSG_INFO(" SORTime [ns] = " << sorTime_ns << " (" << sorTime_readable << ") "); + + // Use string stream for fixed-width hex detector mask formatting + auto dmfst = atr["DetectorMaskFst"].data<unsigned long long>(); + auto dmsnd = atr["DetectorMaskSnd"].data<unsigned long long>(); + std::ostringstream ss; + ss.setf(std::ios_base::hex,std::ios_base::basefield); + ss << std::setw(16) << std::setfill('0') << dmfst; + ATH_MSG_INFO(" DetectorMaskFst = 0x" << ss.str()); + ss.str(""); // reset the string stream + ss << std::setw(16) << std::setfill('0') << dmsnd; + ATH_MSG_INFO(" DetectorMaskSnd = 0x" << ss.str()); + ss.str(""); // reset the string stream + ss << std::setw(16) << std::setfill('0') << dmfst; + ss << std::setw(16) << std::setfill('0') << dmsnd; + ATH_MSG_INFO(" Complete DetectorMask = 0x" << ss.str()); + + ATH_MSG_INFO(" RunType = " << atr["RunType"].data<std::string>()); + ATH_MSG_INFO(" RecordingEnabled = " << (atr["RecordingEnabled"].data<bool>() ? "true" : "false")); } -//========================================================================= -StatusCode HltEventLoopMgr::updMagField(const ptree& pt) const -{ - if(m_setMagFieldFromPtree && validPartition()) - { - try - { - auto tor_cur = pt.get<float>("Magnets.ToroidsCurrent.value"); - auto sol_cur = pt.get<float>("Magnets.SolenoidCurrent.value"); - - IProperty* magfsvc(0); - service("AtlasFieldSvc", magfsvc, /*createIf=*/false).ignore(); - if ( magfsvc==0 ) { - msgStream() << MSG::ERROR << ST_WHERE - << "Cannot retrieve AtlasFieldSvc" << endmsg; - return StatusCode::FAILURE; - } - - auto sc = Gaudi::Utils::setProperty(magfsvc, "UseSoleCurrent", sol_cur); - if ( sc.isFailure() ) { - msgStream() << MSG::ERROR << ST_WHERE - << "Cannot set property AtlasFieldSvc.UseSoleCurrent" - << endmsg; - return StatusCode::FAILURE; +// ============================================================================== +void HltEventLoopMgr::failedEvent(EventContext* eventContext, + const xAOD::EventInfo* eventInfo, + HLT::HLTResult* hltResult) const +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + + // in case EventInfo is unavailable we try to make a temporary one just to build the HLT result + // - this unique_ptr deletes it when going out of scope + std::unique_ptr<xAOD::EventInfo> tmpEventInfo; + + if (eventContext) { + // try to retrieve the event info from event store + if (m_whiteboard->selectStore(eventContext->slot()).isSuccess()) { + if (!eventInfo && m_evtStore->retrieve(eventInfo).isFailure()) { + EventIDBase eid = eventContext->eventID(); + ATH_MSG_WARNING("Failed to retrieve event info. Will try to build one from EventContext (" << *eventContext + << ") with eventID = " << eid); + tmpEventInfo = std::make_unique<xAOD::EventInfo>(); + tmpEventInfo->setRunNumber(eid.run_number()); + tmpEventInfo->setEventNumber(eid.event_number()); + tmpEventInfo->setTimeStamp(eid.time_stamp()); + tmpEventInfo->setTimeStampNSOffset(eid.time_stamp_ns_offset()); + tmpEventInfo->setLumiBlock(eid.lumi_block()); + tmpEventInfo->setBCID(eid.bunch_crossing_id()); + eventInfo = tmpEventInfo.get(); } - - sc = Gaudi::Utils::setProperty(magfsvc, "UseToroCurrent", tor_cur); - if ( sc.isFailure() ) { - msgStream() << MSG::ERROR << ST_WHERE - << "Cannot set property AtlasFieldSvc.UseToroCurrent" - << endmsg; - return StatusCode::FAILURE; + if (!hltResult && m_evtStore->retrieve(hltResult).isFailure()) { + ATH_MSG_DEBUG("Failed to retrieve HLT result"); } - - msgStream() << MSG::INFO << "*****************************************" << endmsg; - msgStream() << MSG::INFO << " Auto-configuration of magnetic field: " << endmsg; - msgStream() << MSG::INFO << " solenoid current from IS = " << sol_cur << endmsg; - msgStream() << MSG::INFO << " torroid current from IS = " << tor_cur << endmsg; - msgStream() << MSG::INFO << "*****************************************" << endmsg; } - catch(ptree_bad_path& e) - { - msgStream() << MSG::ERROR << ST_WHERE - << "Magnet auto-configuration failed: " << e.what() << endmsg; - return StatusCode::FAILURE; + else { + ATH_MSG_DEBUG("Failed to select whiteboard store for slot " << eventContext->slot()); } } - else - { - msgStream() << MSG::DEBUG << ST_WHERE - << "Magnetic fields not available" << endmsg; - } - return StatusCode::SUCCESS; -} + if (!eventContext && !eventInfo) { + ATH_MSG_ERROR("Failure occurred while we don't have either EventContext or EventInfo, so don't know which event " + << "was being processed. No result will be produced for this event."); + return; + } -//========================================================================= -StatusCode HltEventLoopMgr::resetCoolValidity() -{ - if ( m_coolHelper->resetBeginRunFolders(m_currentRun).isFailure() ) { - msgStream() << MSG::ERROR << ST_WHERE - << "Reset of at least one proxy failed" << endmsg; - return StatusCode::FAILURE; + if (eventContext && clearWBSlot(eventContext->slot()).isFailure()) { + ATH_MSG_WARNING("Failed to clear the whiteboard slot " << eventContext->slot()); } - return StatusCode::SUCCESS; -} + // need to create and return a result with debug stream flags + // for now, only creating a dummy result + std::unique_ptr<uint32_t[]> hltr = fullHltResult(eventInfo,hltResult); -//========================================================================= -void HltEventLoopMgr::readyMsg() const -{ - if (msgLevel() <= MSG::INFO) - { - LumiBlock lb; - lb.LumiBlockNumber = 0; - if(validPartition() && - m_isHelper->findValue(TrigISHelper::LumiBlock, lb).isFailure()) - { // Lumiblock only used for information. Do not make this a failure. - msgStream() << MSG::WARNING << ST_WHERE - << "Cannot read lumiblock number from IS" << endmsg; - } + // send the result + eventDone(std::move(hltr)); - const auto& ilbn = lb.LumiBlockNumber; - msgStream() << MSG::INFO << ST_WHERE - << "Ready to start event processing. Run = " - << m_currentRun << " (LB = " - << (ilbn ? boost::lexical_cast<string>(ilbn) : string{"??"}) - << ")" << endmsg; - } + ATH_MSG_VERBOSE("end of " << __FUNCTION__); } -//========================================================================= -void HltEventLoopMgr:: -setStreamTags(hltinterface::HLTResult& hltr, - const std::vector<TriggerInfo::StreamTag>& stream_tags) const +// ============================================================================== +std::unique_ptr<uint32_t[]> HltEventLoopMgr::fullHltResult(const xAOD::EventInfo* eventInfo, + HLT::HLTResult* hltResult) const { - hltr.stream_tag.reserve(stream_tags.size()); - for(const auto& st : stream_tags) - { - // get robs, filtering disabled ones - auto robs = filterRobs(st.robs()); - // get subdetectors, filtering disabled ones - auto dets = filterDets(st.dets()); - - hltr.stream_tag.emplace_back(st.name(), st.type(), st.obeysLumiblock(), - robs, dets); - } + // method to be removed + return nullptr; } -//========================================================================= -void HltEventLoopMgr:: -mergeStreamTags(hltinterface::HLTResult& hltr, - const std::vector<xAOD::EventInfo::StreamTag>& xsts) const +// ============================================================================== +// This method is now trivial and could be removed +void HltEventLoopMgr::eventDone(std::unique_ptr<uint32_t[]> hltResult) const { - auto& stags = hltr.stream_tag; - for(const auto& st : xsts) - { - // get robs, filtering disabled ones - auto robs = filterRobs(st.robs()); - // get subdetectors, filtering disabled ones - auto dets = filterDets(st.dets()); - - // is there already a tag with the same type, name and obeysLumi flag? - auto it = find_if(begin(stags), end(stags), - [&st](const eformat::helper::StreamTag& current){ - return current.name == st.name() && - current.type == st.type() && - current.obeys_lumiblock == st.obeysLumiblock(); - }); - - if(it != stags.end()) // if so, unite robs and dets - { - it->robs.insert(begin(robs), end(robs)); - it->dets.insert(begin(dets), end(dets)); - } - else // otherwise, add the tag - stags.emplace_back(st.name(), st.type(), st.obeysLumiblock(), robs, dets); - } + // method to be removed } -//========================================================================= -hltonl::AcceptFlag -HltEventLoopMgr::processHltDecision(hltinterface::HLTResult& hltr) const -{ - if(m_forceHltAccept) - { - // we force accept independently of what the Steering decided for the event - addDebugStreamTag(hltr, m_HltForcedStreamName.value()); - return hltonl::PSC_FORCED_ACCEPT; +// ============================================================================== +void HltEventLoopMgr::runEventTimer() +{ + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + auto softDuration = std::chrono::milliseconds(m_softTimeoutValue); + std::unique_lock<std::mutex> lock(m_timeoutMutex); + while (m_runEventTimer) { + m_timeoutCond.wait_for(lock,std::chrono::seconds(1)); + auto now=std::chrono::steady_clock::now(); + for (size_t i=0; i<m_eventTimerStartPoint.size(); ++i) { + // iterate over all slots and check for timeout + if (!m_isSlotProcessing.at(i)) continue; + if (now > m_eventTimerStartPoint.at(i) + softDuration) { + EventContext ctx(i,0); // we only need the slot number for Athena::Timeout instance + // don't duplicate the actions if the timeout was already reached + if (!Athena::Timeout::instance(ctx).reached()) { + auto procTime = now - m_eventTimerStartPoint.at(i); + auto procTimeMillisec = std::chrono::duration_cast<std::chrono::milliseconds>(procTime); + ATH_MSG_WARNING("Soft timeout in slot " << i << ". Processing time = " + << procTimeMillisec.count() << " ms"); + setTimeout(Athena::Timeout::instance(ctx)); + } + } + } } - - return hltr.stream_tag.size() ? hltonl::STEERING_ACCEPT - : hltonl::STEERING_REJECT; + ATH_MSG_VERBOSE("end of " << __FUNCTION__); } -//========================================================================= -hltonl::PSCErrorCode -HltEventLoopMgr::serializeRobs(hltinterface::HLTResult& hltr, bool& serOk, - HLT::HLTResult* dobj, uint32_t rn, uint32_t l1id, - uint32_t bcid, uint32_t l1tt, uint32_t dett) +// ============================================================================== +StatusCode HltEventLoopMgr::createEventContext(EventContext*& evtContext) const { - auto fp = hltr.fragment_pointer; - auto spaceleft = hltr.max_result_size; - - // obtain the module ids that need serialization - auto modids = dobj->listOfModIDs(); // hope for copy ellision + evtContext = new EventContext(m_nevt, m_whiteboard->allocateStore(m_nevt)); - if(find(begin(modids), end(modids), 0) == end(modids)) - { - const auto& sts = hltr.stream_tag; - using ST = decltype(sts[0]); - auto pred = [](const ST& st){ return st.type == "debug"; }; - - if (m_forceHltAccept || - find_if(begin(sts), end(sts), pred) != end(sts)) - { - modids.push_back(0); - } - } + m_aess->reset(*evtContext); - // loop over module ids and build a rob for each one - for(const auto& modid : modids) - { - // Initialize a ROB - auto robp = initRob(modid, rn, l1id, bcid, l1tt, dett, m_status_words); - auto initial_robsize = robp->size_word() + INITIAL_ROB_SIZE_MARGIN; - if(!checkRobSize(initial_robsize, spaceleft, hltr.max_result_size)) - return hltonl::PSC_ERROR_ROB_BUILD_FAILED; - - // serialize data and fill rob up - uint32_t* tmp{nullptr}; - serOk &= serializeRob(tmp, *robp, *dobj, modid, - spaceleft - initial_robsize); - - // Hold this until we've copied it into the HLTResult - auto tmpstor = std::unique_ptr<uint32_t[]>{tmp}; - - // copy it in and delete temporary data, updating spaceleft - addRobToHLTResult(hltr, *robp, fp, spaceleft); + StatusCode sc = m_whiteboard->selectStore(evtContext->slot()); + if (sc.isFailure()){ + ATH_MSG_WARNING("Slot " << evtContext->slot() << " could not be selected for the WhiteBoard"); + } else { + evtContext->setExtension( Atlas::ExtendedEventContext( m_evtStore->hiveProxyDict() ) ); + ATH_MSG_DEBUG("created EventContext, num: " << evtContext->evt() << " in slot: " << evtContext->slot()); } - - return hltonl::PSC_ERROR_UNCLASSIFIED; + return sc; } -//========================================================================= -bool HltEventLoopMgr::serializeRob(uint32_t*& tmpstor, - eformat::write::ROBFragment& rob, - HLT::HLTResult& dobj, - unsigned int modid, - int payload_max) +// ============================================================================== +int HltEventLoopMgr::drainScheduler() { - // find the remaining space for this rob's payload - int payload = 0; + ATH_MSG_VERBOSE("start of " << __FUNCTION__); - // serialize current rob - auto ret = dobj.serialize(tmpstor, payload, payload_max, modid); + // method copied from AthenaHiveEventLoopMgr - if(payload > payload_max) - { - msgStream() << MSG::ERROR << ST_WHERE - << "Serialized ROB's size (" << payload << ") is bigger " - "than max allowed size (" << payload_max << ")" - << endmsg; + StatusCode sc(StatusCode::SUCCESS); - payload = payload_max; - ret = false; - } + // maybe we can do better + std::vector<EventContext*> finishedEvtContexts; - if(!ret) // otherwise, it's already correct - { - m_status_words[0] = SW_TRUNCATION.code(); - m_status_words[1] = hltonl::NORMAL_HLT_RESULT_TRUNCATED; - rob.status(2, m_status_words); - rob.rod_status(2, m_status_words); - } + EventContext* finishedEvtContext(nullptr); - rob.rod_data(payload, tmpstor); + // Here we wait not to loose cpu resources + // ATH_MSG_DEBUG("drainScheduler: [" << finishedEvts << "] Waiting for a context"); + ATH_MSG_DEBUG("drainScheduler: Waiting for a context"); + sc = m_schedulerSvc->popFinishedEvent(finishedEvtContext); - return ret; -} + // We got past it: cache the pointer + if (sc.isSuccess()){ + ATH_MSG_DEBUG("drainScheduler: scheduler not empty: Context " + << finishedEvtContext); + finishedEvtContexts.push_back(finishedEvtContext); + } else{ + // no more events left in scheduler to be drained + ATH_MSG_DEBUG("drainScheduler: scheduler empty"); + return 0; + } -//========================================================================= -void HltEventLoopMgr::addRobToHLTResult(hltinterface::HLTResult& hltr, - eformat::write::ROBFragment& rob, - uint32_t*& next_fragment, // don't pass original fragment pointer! - uint32_t& spaceleft) -{ - // Store the HLT ROB fragment in the HLT result - // (Maximum possible space is already allocated by the HLTMPPU) - auto copied = eformat::write::copy(*rob.bind(), next_fragment, rob.size_word()); - hltr.hltResult_robs.emplace_back(next_fragment); - - next_fragment += copied; - spaceleft -= copied; - - if(copied == 0 || copied != rob.size_word()) { - msgStream() << MSG::ERROR - << "Memory copy operation for HLT result ROB failed. " - "Returned number of copied words = " << copied - << ". Number of words in ROB which should be copied = " - << rob.size_word() << "." << endmsg; + // Let's see if we can pop other event contexts + while (m_schedulerSvc->tryPopFinishedEvent(finishedEvtContext).isSuccess()){ + finishedEvtContexts.push_back(finishedEvtContext); } -} -//========================================================================= -void HltEventLoopMgr::recordEDMSizeInfo(size_t nav_size, - bool serializationOk) const -{ - if (m_evtStore->transientContains<HLT::TrigEDMSizes>("TrigEDMSizes")) { - const HLT::TrigEDMSizes* dobjNavSizes(0); - if ( m_evtStore->retrieve(dobjNavSizes).isSuccess() ) { - for(const auto& navSizeInfo : dobjNavSizes->info()) - { - std::string colname(navSizeInfo.collection+"__"+navSizeInfo.label); - // Protection for invalid collection names in TProfile - // (avoid bug in TProfile memory alloc) - auto it_col_name = std::find(m_hltEdmCollectionNames.value().begin(), - m_hltEdmCollectionNames.value().end(), - colname); - if(it_col_name == m_hltEdmCollectionNames.value().end()) - { - if ( msgLevel() <= MSG::DEBUG ) - msgStream() << MSG::DEBUG << "EDM collection name = " << colname - << " is not in the configured list of EDM collections." - << endmsg; - - colname=m_hltEdmCollectionNames.value().back(); - } + // Now we flush them + bool fail(false); + for (auto& thisFinishedEvtContext : finishedEvtContexts) { + if (!thisFinishedEvtContext) { + ATH_MSG_FATAL("Detected nullptr EventContext while clearing WB!"); + fail = true; + continue; + } - auto * edmhist = serializationOk ? m_hist_HltEdmSizes_No_Truncation - : m_hist_HltEdmSizes_With_Truncation; - fillEdmHist(edmhist, colname, navSizeInfo); + // Set ThreadLocalContext to the currently processed finished context + Gaudi::Hive::setCurrentContext(thisFinishedEvtContext); - if(!serializationOk) - { - edmhist = navSizeInfo.isTruncated(nav_size) ? - m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections : - m_hist_HltEdmSizes_TruncatedResult_Retained_Collections; - fillEdmHist(edmhist, colname, navSizeInfo); - } - } + if (m_aess->eventStatus(*thisFinishedEvtContext) != EventStatus::Success) { + ATH_MSG_FATAL("Failed event detected on " << thisFinishedEvtContext + << " with fail mode: " << m_aess->eventStatus(*thisFinishedEvtContext)); + delete thisFinishedEvtContext; + fail = true; + continue; } - else - msgStream() << MSG::WARNING << "cannot access EDM sizes information" - << endmsg; - } -} -//========================================================================= -bool HltEventLoopMgr::checkRobSize(uint32_t robsize, uint32_t spaceleft, - uint32_t maxsize) -{ - if(spaceleft <= robsize) - { - msgStream() << MSG::ERROR << ST_WHERE - << "Can not create HLT result ROB with available ROB " - "buffer size ! Total available buffer size = " - << maxsize << "; buffer size left = " << spaceleft - << "; Number of header words used by empty ROB = " - << robsize << endmsg; - - return false; - } + // EventID::number_type n_run(0); + // EventID::number_type n_evt(0); + + //------------------------------------------- + // Do we need the event info here ??? + //------------------------------------------- + + const xAOD::EventInfo* eventInfo = nullptr; + if (m_whiteboard->selectStore(thisFinishedEvtContext->slot()).isSuccess()) { + if (m_evtStore->retrieve(eventInfo).isFailure()) { + ATH_MSG_ERROR(__FUNCTION__ << ": Failed to retrieve EventInfo"); + delete thisFinishedEvtContext; + fail = true; + continue; + } else { + // n_run = eventInfo->runNumber(); + // n_evt = eventInfo->eventNumber(); + } + } else { + ATH_MSG_ERROR("DrainSched: unable to select store " << thisFinishedEvtContext->slot()); + delete thisFinishedEvtContext; + fail = true; + continue; + } - return true; -} + // m_incidentSvc->fireIncident(Incident(name(), IncidentType::EndEvent, + // *thisFinishedEvtContext )); -//========================================================================= -bool HltEventLoopMgr:: -checkEventIdConsistency(const hltinterface::EventId& evId) const -{ - if(evId.l1Id != m_lvl1id || evId.lbNumber != m_lumi_block) - { - msgStream() << MSG::WARNING << ST_WHERE - << "EventId information does not match CTP fragment contents: " - << "EventId = {globalId: " << evId.globalId << ", l1Id: " - << evId.l1Id << ", lbNumber: " << evId.lbNumber - << "}, but the CTP fragment included l1Id = " << m_lvl1id - << " and lumiblock = " << m_lumi_block << "." << endmsg; - return false; - } - return true; -} + // if (!hltResult) { + // failedEvent(thisFinishedEvtContext,eventInfo); + // continue; + // } -//========================================================================= -void HltEventLoopMgr::failedEvent(hltinterface::HLTResult& hlt_result, - hltonl::PSCErrorCode ecode, - const std::string& emsg, - bool empty_result) -{ - m_failed_evt++; + //------------------------------------------- + // HLT output handling goes here + // Call the conversion svc etc. + // Handle any possible errors + //------------------------------------------- + // Call the result builder to record HLTResultMT in SG + if (m_hltResultBuilder->buildResult(*thisFinishedEvtContext).isFailure()) { + ATH_MSG_ERROR("Failed to create the HLT result object"); + // what now? + } + // Connect output (create the output container) - the argument is currently not used + if (m_outputCnvSvc->connectOutput("").isFailure()) { + ATH_MSG_ERROR("Conversion service failed to connectOutput"); + // what now? + } + IOpaqueAddress* addr = nullptr; + // is this the best way? also maybe should be retrieved in initialize and stored? + auto hltResultCLID = ClassID_traits<HLT::HLTResultMT>::ID(); + DataObject* hltResultDO = m_evtStore->accessData(hltResultCLID,m_hltResultBuilder->resultName()); + if (!hltResultDO) { + ATH_MSG_ERROR("Failed to retrieve the HLTResult DataObject"); + // what now? + } + if (m_outputCnvSvc->createRep(hltResultDO,addr).isFailure()) { + ATH_MSG_ERROR("Conversion service failed to convert HLTResult"); + // what now? + } + // Commit output (write/send the output data) - the arguments are currently not used + if (m_outputCnvSvc->commitOutput("",true).isFailure()) { + ATH_MSG_ERROR("Conversion service failed to commitOutput"); + // what now? + } - addDebugStreamTag(hlt_result, m_HltDebugStreamName.value()); - if(empty_result) - { - HltEmptyResultROB(hlt_result, ecode); - fillHltResultHistograms(hlt_result); - } + { // flag idle slot to the timeout thread and reset the timer + std::unique_lock<std::mutex> lock(m_timeoutMutex); + m_eventTimerStartPoint[thisFinishedEvtContext->slot()] = std::chrono::steady_clock::now(); + m_isSlotProcessing[thisFinishedEvtContext->slot()] = false; + resetTimeout(Athena::Timeout::instance(*thisFinishedEvtContext)); + } + m_timeoutCond.notify_all(); - msgStream() << MSG::ERROR << ST_WHERE - << emsg << " PSC error code = " - << hltonl::PrintPscErrorCode(ecode) - << "\n" << hlt_result << "\n" << endmsg; -} + ATH_MSG_DEBUG("Clearing slot " << thisFinishedEvtContext->slot() + << " (event " << thisFinishedEvtContext->evt() << ") of the whiteboard"); -//========================================================================= -std::vector<uint32_t> HltEventLoopMgr:: -missingL1Robs(const std::vector<eformat::ROBFragment<const uint32_t*>>& l1r) -const -{ - using eformat::helper::SourceIdentifier; - using ROB = eformat::ROBFragment<const uint32_t*>; + StatusCode sc = clearWBSlot(thisFinishedEvtContext->slot()); + if (!sc.isSuccess()) { + ATH_MSG_ERROR("Whiteboard slot " << thisFinishedEvtContext->slot() << " could not be properly cleared"); + fail = true; + delete thisFinishedEvtContext; + continue; + } - std::vector<uint32_t> ret{}; - for(const auto& robid : m_mandatoryL1ROBs.value()) - { - if(isSubDetectorIn(SourceIdentifier(robid).subdetector_id())) - { - auto it = std::find_if(begin(l1r), end(l1r), [robid](const ROB& rob){ - return rob.rob_source_id() == robid; - }); - if(it == end(l1r)) - ret.push_back(robid); +/* + finishedEvts++; + + writeHistograms().ignore(); + ++m_proc; + + if (m_doEvtHeartbeat) { + if(!m_useTools) + ATH_MSG_INFO(" ===>>> done processing event #" << n_evt << ", run #" << n_run + << " on slot " << thisFinishedEvtContext->slot() << ", " + << m_proc << " events processed so far <<<==="); + else + ATH_MSG_INFO(" ===>>> done processing event #" << n_evt << ", run #" << n_run + << " on slot " << thisFinishedEvtContext->slot() << ", " + << m_nev << " events read and " << m_proc + << " events processed so far <<<==="); + std::ofstream outfile( "eventLoopHeartBeat.txt"); + if ( !outfile ) { + ATH_MSG_ERROR(" unable to open: eventLoopHeartBeat.txt"); + fail = true; + delete thisFinishedEvtContext; + continue; + } else { + outfile << " done processing event #" << n_evt << ", run #" << n_run + << " " << m_nev << " events read so far <<<===" << std::endl; + outfile.close(); + } } +*/ + ATH_MSG_DEBUG("drainScheduler thisFinishedEvtContext: " << thisFinishedEvtContext); + + + m_incidentSvc->fireIncident(Incident(name(), + IncidentType::EndProcessing, + *thisFinishedEvtContext)); + + delete thisFinishedEvtContext; + + // Set ThreadLocalContext to an invalid context as we entering a context-less environment + Gaudi::Hive::setCurrentContext( EventContext() ); } - return ret; + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return ( fail ? -1 : 1 ); } -//========================================================================= -bool HltEventLoopMgr::isSubDetectorIn(eformat::SubDetector sd) const +// ============================================================================== +StatusCode HltEventLoopMgr::clearWBSlot(int evtSlot) const { - uint64_t most = std::get<3>(m_detector_mask); - most <<= 32; - most |= std::get<2>(m_detector_mask); - - uint64_t least = std::get<1>(m_detector_mask); - least <<= 32; - least |= std::get<0>(m_detector_mask); - - return eformat::helper::DetectorMask{least, most}.is_set(sd); + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + StatusCode sc = m_whiteboard->clearStore(evtSlot); + if( !sc.isSuccess() ) { + ATH_MSG_WARNING("Clear of Event data store failed"); + } + ATH_MSG_VERBOSE("end of " << __FUNCTION__ << ", returning m_whiteboard->freeStore(evtSlot=" << evtSlot << ")"); + return m_whiteboard->freeStore(evtSlot); } diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx index 77d8f687d4a23b6fb51b032eeef9b99645a3d1e1..85a1766f21a13aea199ffccd7a64a2cb56eb65de 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx +++ b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx @@ -132,6 +132,8 @@ StatusCode TrigMonTHistSvc::regHist(const std::string& id, TH1* hist_ptr) { + + StatusCode TrigMonTHistSvc::regTree(const std::string& id) { return THistSvcHLT::regTree(id); } diff --git a/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx b/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx index 1bf48550a1225b2142e67a6b8b45b6bdd7a44d58..898cf7b342fafec0cdcd8cbb02b73fa2248ebca1 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx +++ b/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx @@ -5,7 +5,6 @@ #include "TrigServices/TrigIS.h" #include "TrigServices/TrigISHelper.h" #include "../TrigCOOLUpdateHelper.h" -#include "../THistSvcHLT.h" DECLARE_COMPONENT( TrigMessageSvc ) DECLARE_COMPONENT( TrigMonTHistSvc ) @@ -13,6 +12,5 @@ DECLARE_COMPONENT( TrigIS ) DECLARE_COMPONENT( HltEventLoopMgr ) DECLARE_COMPONENT( HltROBDataProviderSvc ) DECLARE_COMPONENT( TrigISHelper ) -DECLARE_COMPONENT( TrigCOOLUpdateHelper ) -DECLARE_COMPONENT( THistSvcHLT ) - +DECLARE_COMPONENT( TrigCOOLUpdateHelper ) +DECLARE_COMPONENT( THistSvcHLT ) diff --git a/Projects/Athena/package_filters.txt b/Projects/Athena/package_filters.txt index cd306a1de015fd862d2dfe4f39c8a9447d43972f..5f83a2584f5749e987a155036c0c6e311865ebfa 100644 --- a/Projects/Athena/package_filters.txt +++ b/Projects/Athena/package_filters.txt @@ -9,10 +9,11 @@ - Projects/.* # Remove most HLT packages -+ HLT/Trigger/TrigTransforms/TrigTransform -+ HLT/Event/ByteStreamEmonSvc -- HLT/.* -- Trigger/TrigValidation/TrigP1Test +# We currently build the HLT as part of Athena. Uncomment the following three lines to revert: +#+ HLT/Trigger/TrigTransforms/TrigTransform +#- HLT/.* +#- Trigger/TrigValidation/TrigP1Test +- HLT/HLTTestApps - HLT/HLToks - Trigger/ALP - Event/DFStreamEventSelector diff --git a/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResultMT.h b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResultMT.h new file mode 100644 index 0000000000000000000000000000000000000000..6cd6de32ca5acada8212497d2d04edf757d1ffbc --- /dev/null +++ b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResultMT.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGSTEERINGEVENT_HLTResultMT_H +#define TRIGSTEERINGEVENT_HLTResultMT_H + +#include "AthenaKernel/CLASS_DEF.h" +#include "eformat/StreamTag.h" +#include <vector> +#include <unordered_map> + +namespace HLT { + + /** @class HLTResultMT + * @brief A container class for data required to build online output from HLT. + * + * It is not intended to modify the stored data, but may perform extra checks and debug printouts in the + * getter/setter methods. + **/ + class HLTResultMT { + public: + /// Standard constructor + HLTResultMT(std::vector<eformat::helper::StreamTag> streamTags = {}, + std::vector<uint32_t> hltBits = {}, + std::unordered_map<uint16_t, std::vector<uint32_t> > data = {}); + /// Standard destructor + virtual ~HLTResultMT(); + + /// Stream tags getter + const std::vector<eformat::helper::StreamTag>& getStreamTags() const; + /// Stream tags setter + void setStreamTags(const std::vector<eformat::helper::StreamTag>& streamTags); + /// Append a stream tag + void addStreamTag(const eformat::helper::StreamTag& streamTag); + + /// HLT bits getter + const std::vector<uint32_t>& getHltBits() const; + /// HLT bits setter + void setHltBits(const std::vector<uint32_t>& bits); + /// Append a word with HLT bits + void addHltBitsWord(const uint32_t& word); + + /// Serialised data getter + const std::unordered_map<uint16_t, std::vector<uint32_t> >& getSerialisedData() const; + /// Serialised data getter for a given module ID + const std::vector<uint32_t>& getSerialisedData(uint16_t moduleId) const; + /// Serialised data setter + void setSerialisedData(const std::unordered_map<uint16_t, std::vector<uint32_t> >& data); + /// Append serialised data for a given module ID + void addSerialisedData(const uint16_t moduleId, const std::vector<uint32_t>& data); + + private: + /// Stream tags of the event + std::vector<eformat::helper::StreamTag> m_streamTags; + /// Serialised HLT bits (flagging which chains passed) + std::vector<uint32_t> m_hltBits; + /// Serialised result (ROBFragment payload) for each module ID (0 for full result, >0 for data scouting) + std::unordered_map<uint16_t, std::vector<uint32_t> > m_data; + }; +} // namespace HLT + +CLASS_DEF(HLT::HLTResultMT, 172156324, 1) + +#endif // TRIGSTEERINGEVENT_HLTResultMT_H diff --git a/Trigger/TrigEvent/TrigSteeringEvent/src/HltResultMT.cxx b/Trigger/TrigEvent/TrigSteeringEvent/src/HltResultMT.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2759bfc81b35c47ecb0e21aca9b9d2b79a43901a --- /dev/null +++ b/Trigger/TrigEvent/TrigSteeringEvent/src/HltResultMT.cxx @@ -0,0 +1,86 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigSteeringEvent/HLTResultMT.h" + +// ============================================================================= +// Standard constructor +// ============================================================================= +HLT::HLTResultMT::HLTResultMT(std::vector<eformat::helper::StreamTag> streamTags, + std::vector<uint32_t> hltBits, + std::unordered_map<uint16_t, std::vector<uint32_t> > data) +: m_streamTags(streamTags), + m_hltBits(hltBits), + m_data(data) {} + +// ============================================================================= +// Standard destructor +// ============================================================================= +HLT::HLTResultMT::~HLTResultMT() {} + +// ============================================================================= +// Getter/setter methods for stream tags +// ============================================================================= +const std::vector<eformat::helper::StreamTag>& HLT::HLTResultMT::getStreamTags() const { + return m_streamTags; +} + +// ----------------------------------------------------------------------------- +void HLT::HLTResultMT::setStreamTags(const std::vector<eformat::helper::StreamTag>& streamTags) { + // copy assignment + m_streamTags = streamTags; +} + +// ----------------------------------------------------------------------------- +void HLT::HLTResultMT::addStreamTag(const eformat::helper::StreamTag& streamTag) { + m_streamTags.push_back(streamTag); +} + +// ============================================================================= +// Getter/setter methods for trigger bits +// ============================================================================= +const std::vector<uint32_t>& HLT::HLTResultMT::getHltBits() const { + return m_hltBits; +} + +// ----------------------------------------------------------------------------- +void HLT::HLTResultMT::setHltBits(const std::vector<uint32_t>& bits) { + // copy assignment + m_hltBits = bits; +} + +// ----------------------------------------------------------------------------- +void HLT::HLTResultMT::addHltBitsWord(const uint32_t& word) { + m_hltBits.push_back(word); +} + +// ============================================================================= +// Getter/setter methods for serialised data +// ============================================================================= +/// Serialised data getter +const std::unordered_map<uint16_t, std::vector<uint32_t> >& HLT::HLTResultMT::getSerialisedData() const { + return m_data; +} + +// ----------------------------------------------------------------------------- +const std::vector<uint32_t>& HLT::HLTResultMT::getSerialisedData(uint16_t moduleId) const { + // this can throw std::out_of_range - implement messaging (std::cerr or ATH_MSG_ERR) to avoid exception + return m_data.at(moduleId); +} + +// ----------------------------------------------------------------------------- +void HLT::HLTResultMT::setSerialisedData(const std::unordered_map<uint16_t, std::vector<uint32_t> >& data) { + // copy assignment (WARNING, data may be large!) + m_data = data; +} + +// ----------------------------------------------------------------------------- +void HLT::HLTResultMT::addSerialisedData(const uint16_t moduleId, const std::vector<uint32_t>& data) { + if (m_data.find(moduleId)!=m_data.cend()) { + // implement error printout and handling here !!! use either std::cerr or ATH_MSG_ERR + } + else { + m_data[moduleId] = data; + } +} diff --git a/Trigger/TrigSteer/TrigHLTResultByteStream/TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h b/Trigger/TrigSteer/TrigHLTResultByteStream/TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h new file mode 100644 index 0000000000000000000000000000000000000000..64064674bae8b3d9a39653c235123bb952d56abb --- /dev/null +++ b/Trigger/TrigSteer/TrigHLTResultByteStream/TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGHLTRESULTBYTESTREAM_HLTResultMTByteStreamCnv_H +#define TRIGHLTRESULTBYTESTREAM_HLTResultMTByteStreamCnv_H + +#include "AthenaBaseComps/AthMessaging.h" +#include "GaudiKernel/Converter.h" + +// Externals +extern unsigned char ByteStream_StorageType; + +namespace HLT { + /** @class HLTResultMTByteStreamCnv + * @brief ByteStream converter for HLTResultMT + **/ + class HLTResultMTByteStreamCnv : public Converter, public AthMessaging { + public: + /// Standard constructor + HLTResultMTByteStreamCnv(ISvcLocator* svcLoc); + /// Standard destructor + virtual ~HLTResultMTByteStreamCnv(); + + // ------------------------- Converter methods ----------------------------- + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + + /// Create RDO (HLTResultMT) from ByteStream + virtual StatusCode createObj(IOpaqueAddress* pAddr, DataObject*& pObj) override; + /// Create ByteStream from RDO (HLTResultMT) + virtual StatusCode createRep(DataObject* pObj, IOpaqueAddress*& pAddr) override; + + // ------------------------- Converter definition helpers ------------------ + /// Storage type used by this converter + static unsigned char storageType() {return ByteStream_StorageType;} + /// CLID of the class HLTResultMT converted by this converter + static const CLID& classID(); + + long repSvcType() const override { return i_repSvcType(); } //!< return repSvcType + }; +} // namespace HLT + +#endif // TRIGHLTRESULTBYTESTREAM_HLTResultMTByteStreamCnv_H diff --git a/Trigger/TrigSteer/TrigHLTResultByteStream/src/HLTResultMTByteStreamCnv.cxx b/Trigger/TrigSteer/TrigHLTResultByteStream/src/HLTResultMTByteStreamCnv.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4430e93e7af14581a70916f19958f853af5bee27 --- /dev/null +++ b/Trigger/TrigSteer/TrigHLTResultByteStream/src/HLTResultMTByteStreamCnv.cxx @@ -0,0 +1,65 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h" +#include "TrigSteeringEvent/HLTResultMT.h" + +#include "AthenaBaseComps/AthMsgStreamMacros.h" +#include "AthenaKernel/ClassID_traits.h" + +// ============================================================================= +// Standard constructor +// ============================================================================= +HLT::HLTResultMTByteStreamCnv::HLTResultMTByteStreamCnv(ISvcLocator* svcLoc) : + Converter(ByteStream_StorageType, classID(), svcLoc), + AthMessaging(msgSvc(), "HLTResultMTByteStreamCnv") {} + +// ============================================================================= +// Standard destructor +// ============================================================================= +HLT::HLTResultMTByteStreamCnv::~HLTResultMTByteStreamCnv() {} + +// ============================================================================= +// Implementation of Converter::initialize +// ============================================================================= +StatusCode HLT::HLTResultMTByteStreamCnv::initialize() { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of Converter::finalize +// ============================================================================= +StatusCode HLT::HLTResultMTByteStreamCnv::finalize() { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of Converter::createObj +// ============================================================================= +StatusCode HLT::HLTResultMTByteStreamCnv::createObj(IOpaqueAddress* pAddr, DataObject*& pObj) { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of Converter::createRep +// ============================================================================= +StatusCode HLT::HLTResultMTByteStreamCnv::createRep(DataObject* pObj, IOpaqueAddress*& pAddr) { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// CLID +// ============================================================================= +const CLID& HLT::HLTResultMTByteStreamCnv::classID() { + return ClassID_traits<HLT::HLTResultMT>::ID(); +} + diff --git a/Trigger/TrigSteer/TrigHLTResultByteStream/src/components/TrigHLTResultByteStream_entries.cxx b/Trigger/TrigSteer/TrigHLTResultByteStream/src/components/TrigHLTResultByteStream_entries.cxx index fbcb8e97fa2fec95b0ae970bc610eedafc514bb7..65f438152d9d5f2157fc6a645e23bf1088e7fa39 100644 --- a/Trigger/TrigSteer/TrigHLTResultByteStream/src/components/TrigHLTResultByteStream_entries.cxx +++ b/Trigger/TrigSteer/TrigHLTResultByteStream/src/components/TrigHLTResultByteStream_entries.cxx @@ -1,7 +1,9 @@ #include "TrigHLTResultByteStream/HLTResultByteStreamCnv.h" +#include "TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h" #include "TrigHLTResultByteStream/HLTResultByteStreamTool.h" DECLARE_CONVERTER( HLT::HLTResultByteStreamCnv ) +DECLARE_CONVERTER( HLT::HLTResultMTByteStreamCnv ) DECLARE_COMPONENT( HLT::HLTResultByteStreamTool ) diff --git a/Trigger/TrigSteer/TrigSteering/TrigSteering/ResultBuilderMT.h b/Trigger/TrigSteer/TrigSteering/TrigSteering/ResultBuilderMT.h new file mode 100644 index 0000000000000000000000000000000000000000..8a475954210929aabb8bc5bb3cf8baade7042781 --- /dev/null +++ b/Trigger/TrigSteer/TrigSteering/TrigSteering/ResultBuilderMT.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGSTEERING_RESULTBUILDERMT_H +#define TRIGSTEERING_RESULTBUILDERMT_H + +#include "TrigSteeringEvent/HLTResultMT.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "StoreGate/WriteHandle.h" + +namespace HLT { + /** @class ResultBuilderMT + * @brief Tool to create the HLTResultMT at the end of each event + **/ + class ResultBuilderMT : public AthAlgTool { + public: + /// Standard constructor + ResultBuilderMT(const std::string& type, const std::string& name, const IInterface* parent); + /// Standard destructor + virtual ~ResultBuilderMT(); + + // ------------------------- IStateful methods ----------------------------- + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + + // ------------------------- Specific methods of this tool ----------------- + /// Builds the HLTResultMT and records it in the event store + StatusCode buildResult(const EventContext& eventContext) const; + /// Return name of the HLTResultMT + const std::string& resultName() const {return m_hltResultWHKey.key();} + + private: + /// StoreGate key for the HLTResultMT + SG::WriteHandleKey<HLT::HLTResultMT> m_hltResultWHKey; + }; +} // namespace HLT + +#endif // TRIGSTEERING_RESULTBUILDERMT_H diff --git a/Trigger/TrigSteer/TrigSteering/src/ResultBuilderMT.cxx b/Trigger/TrigSteer/TrigSteering/src/ResultBuilderMT.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6c619ebc7788cb9058bd74e7f30090aac276d5b3 --- /dev/null +++ b/Trigger/TrigSteer/TrigSteering/src/ResultBuilderMT.cxx @@ -0,0 +1,49 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigSteering/ResultBuilderMT.h" + +// ============================================================================= +// Standard constructor +// ============================================================================= +HLT::ResultBuilderMT::ResultBuilderMT(const std::string& type, const std::string& name, const IInterface* parent) + : AthAlgTool(type, name, parent) { + declareProperty("HLTResultWHKey", m_hltResultWHKey="HLTResult"); +} + +// ============================================================================= +// Standard destructor +// ============================================================================= +HLT::ResultBuilderMT::~ResultBuilderMT() {} + +// ============================================================================= +// Implementation of IStateful::initialize +// ============================================================================= +StatusCode HLT::ResultBuilderMT::initialize() { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + ATH_CHECK(m_hltResultWHKey.initialize()); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// Implementation of IStateful::finalize +// ============================================================================= +StatusCode HLT::ResultBuilderMT::finalize() { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// The main method of the tool +// ============================================================================= +StatusCode HLT::ResultBuilderMT::buildResult(const EventContext& eventContext) const { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); + auto hltResult = SG::makeHandle(m_hltResultWHKey,eventContext); + ATH_CHECK( hltResult.record(std::make_unique<HLT::HLTResultMT>()) ); + ATH_MSG_DEBUG("Recorded HLTResultMT with key " << m_hltResultWHKey.key()); + ATH_MSG_VERBOSE("end of " << __FUNCTION__); + return StatusCode::SUCCESS; +} diff --git a/Trigger/TrigSteer/TrigSteering/src/components/TrigSteering_entries.cxx b/Trigger/TrigSteer/TrigSteering/src/components/TrigSteering_entries.cxx index 1a4885a3b340871659d78bcc6c99c8d37218eb89..399686097590d30a578ab14ea076a1ef9c47b511 100644 --- a/Trigger/TrigSteer/TrigSteering/src/components/TrigSteering_entries.cxx +++ b/Trigger/TrigSteer/TrigSteering/src/components/TrigSteering_entries.cxx @@ -6,6 +6,7 @@ #include "TrigSteering/LoopbackConverterFromPersistency.h" #include "TrigSteering/Lvl2ConverterFromPersistency.h" #include "TrigSteering/ResultBuilder.h" +#include "TrigSteering/ResultBuilderMT.h" #include "TrigSteering/RandomScaler.h" //#include "TrigSteering/PeriodicScaler.h" #include "TrigSteering/ScalerSvc.h" @@ -26,6 +27,7 @@ DECLARE_COMPONENT( HLT::TrigSteer ) DECLARE_COMPONENT( HLT::ScalerSvc ) DECLARE_COMPONENT( HLT::ResultBuilder ) +DECLARE_COMPONENT( HLT::ResultBuilderMT ) DECLARE_COMPONENT( HLT::RandomScaler ) DECLARE_COMPONENT( HLT::Lvl1ResultAccessTool ) DECLARE_COMPONENT( HLT::HLTResultAccessTool )