diff --git a/Event/ByteStreamCnvSvcBase/ByteStreamCnvSvcBase/ByteStreamCnvSvcBase.h b/Event/ByteStreamCnvSvcBase/ByteStreamCnvSvcBase/ByteStreamCnvSvcBase.h index 53e2a00c37d627d5b0776f1941b9978f7bacec39..ea564f11670f66b0d3bfbd2b4b7bd6979989ea8d 100755 --- a/Event/ByteStreamCnvSvcBase/ByteStreamCnvSvcBase/ByteStreamCnvSvcBase.h +++ b/Event/ByteStreamCnvSvcBase/ByteStreamCnvSvcBase/ByteStreamCnvSvcBase.h @@ -11,13 +11,9 @@ #include "ByteStreamData/RawEvent.h" /** - @class ByteStreamCnvSvcBase - @brief base class for ByteStream conversion service. - - description - This class is used as a conversion service in online HLT - and it is the base class for offline bytestream conversion service. -*/ + * @class ByteStreamCnvSvcBase + * @brief The base class for offline and HLT ByteStream conversion services + */ class ByteStreamCnvSvcBase : public ::AthCnvSvc, public virtual IIncidentListener, public virtual IByteStreamEventAccess { diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx index 56b749809ac314e6b3f8f5b91bb09ec3bd45c899..1d947bebe7bcbedafca88bf45ba6817e9ae0b2a4 100644 --- a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx +++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx @@ -84,7 +84,7 @@ namespace { // Standard constructor // ============================================================================= TrigByteStreamCnvSvc::TrigByteStreamCnvSvc(const std::string& name, ISvcLocator* svcLoc) -: ByteStreamCnvSvc(name, svcLoc) {} +: ByteStreamCnvSvcBase(name, svcLoc) {} // ============================================================================= // Standard destructor @@ -96,7 +96,7 @@ TrigByteStreamCnvSvc::~TrigByteStreamCnvSvc() {} // ============================================================================= StatusCode TrigByteStreamCnvSvc::initialize() { ATH_MSG_VERBOSE("start of " << __FUNCTION__); - ATH_CHECK(ByteStreamCnvSvc::initialize()); + ATH_CHECK(ByteStreamCnvSvcBase::initialize()); ATH_CHECK(m_evtStore.retrieve()); ATH_CHECK(m_robDataProviderSvc.retrieve()); if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve()); @@ -114,7 +114,7 @@ StatusCode TrigByteStreamCnvSvc::finalize() { if (m_evtStore.release().isFailure()) ATH_MSG_WARNING("Failed to release service " << m_evtStore.typeAndName()); ATH_MSG_VERBOSE("end of " << __FUNCTION__); - ATH_CHECK(ByteStreamCnvSvc::finalize()); + ATH_CHECK(ByteStreamCnvSvcBase::finalize()); return StatusCode::SUCCESS; } @@ -122,22 +122,19 @@ StatusCode TrigByteStreamCnvSvc::finalize() { // Implementation of IConversionSvc::connectOutput // The argument outputFile is not used // ============================================================================= -StatusCode TrigByteStreamCnvSvc::connectOutput(const std::string& /*outputFile*/) { - ATH_MSG_VERBOSE("start of " << __FUNCTION__); +StatusCode TrigByteStreamCnvSvc::connectOutput(const std::string& outputFile) { + const EventContext* eventContext = currentContext(); + if (eventContext == nullptr) return StatusCode::FAILURE; + return connectOutput(outputFile, *eventContext); +} - // Get the EventContext via event store because the interface doesn't allow passing it explicitly as an argument - // and we don't want to use ThreadLocalContext. Don't use ReadHandle here because it calls ThreadLocalContext if - // not given a context (which we want to retrieve). - const EventContext* eventContext = nullptr; - if (m_evtStore->retrieve(eventContext).isFailure()) { - ATH_MSG_ERROR("Failed to retrieve EventContext from the event store"); - return StatusCode::FAILURE; - } +StatusCode TrigByteStreamCnvSvc::connectOutput(const std::string& /*outputFile*/, const EventContext& eventContext) { + ATH_MSG_VERBOSE("start of " << __FUNCTION__); - ATH_MSG_DEBUG("Creating new RawEventWrite for EventContext = " << *eventContext); + ATH_MSG_DEBUG("Creating new RawEventWrite for EventContext = " << eventContext); // Create a new RawEventWrite and copy the header from the input RawEvent - RawEventWrite* re = setRawEvent (std::make_unique<RawEventWrite>()); - const uint32_t* inputRawEvent = m_robDataProviderSvc->getEvent(*eventContext)->start(); + RawEventWrite* re = setRawEvent(std::make_unique<RawEventWrite>(), eventContext); + const uint32_t* inputRawEvent = m_robDataProviderSvc->getEvent(eventContext)->start(); if (!inputRawEvent) { ATH_MSG_ERROR("Input RawEvent is nullptr, cannot create output"); return StatusCode::FAILURE; @@ -163,12 +160,18 @@ StatusCode TrigByteStreamCnvSvc::connectOutput(const std::string& outputFile, co // The arguments outputFile and do_commit are not used // NOTE: In online HLT, m_rawEventWrite is not a full event, it contains only the HLTResult ROBFragments // ============================================================================= -StatusCode TrigByteStreamCnvSvc::commitOutput(const std::string& /*outputFile*/, bool /*do_commit*/) { +StatusCode TrigByteStreamCnvSvc::commitOutput(const std::string& outputFile, bool do_commit) { + const EventContext* eventContext = currentContext(); + if (eventContext == nullptr) return StatusCode::FAILURE; + return commitOutput(outputFile, do_commit, *eventContext); +} + +StatusCode TrigByteStreamCnvSvc::commitOutput(const std::string& /*outputFile*/, bool /*do_commit*/, const EventContext& eventContext) { ATH_MSG_VERBOSE("start of " << __FUNCTION__); - if (msgLvl(MSG::DEBUG)) printRawEvent(); + if (msgLvl(MSG::DEBUG)) printRawEvent(eventContext); - RawEventWrite* re = getRawEvent(); + RawEventWrite* re = getRawEvent(eventContext); // Serialise the output FullEventFragment std::unique_ptr<uint32_t[]> rawEventPtr; @@ -184,10 +187,12 @@ StatusCode TrigByteStreamCnvSvc::commitOutput(const std::string& /*outputFile*/, } catch (const std::exception& e) { ATH_MSG_ERROR("FullEventFragment serialisation failed, caught an unexpected std::exception " << e.what()); + clearRawEvent(eventContext); return StatusCode::FAILURE; } catch (...) { ATH_MSG_ERROR("FullEventFragment serialisation failed, caught an unexpected exception"); + clearRawEvent(eventContext); return StatusCode::FAILURE; } @@ -215,12 +220,48 @@ StatusCode TrigByteStreamCnvSvc::commitOutput(const std::string& /*outputFile*/, result = StatusCode::FAILURE; } - setRawEvent (std::unique_ptr<RawEventWrite>()); + clearRawEvent(eventContext); ATH_MSG_VERBOSE("end of " << __FUNCTION__); return result; } +// ============================================================================= +const EventContext* TrigByteStreamCnvSvc::currentContext() const { + // Get the EventContext via event store because the base class doesn't allow passing it explicitly as an argument + // and we don't want to use ThreadLocalContext. Don't use ReadHandle here because it calls ThreadLocalContext if + // not given a context (which we want to retrieve). This relies on IHiveWhiteBoard::selectStore being called on the + // current thread before we arrive here (it is done in HltEventLoopMgr). + const EventContext* eventContext = nullptr; + if (m_evtStore->retrieve(eventContext).isFailure()) { + ATH_MSG_ERROR("Failed to retrieve EventContext from the event store"); + } + return eventContext; +} + +// ============================================================================= +RawEventWrite* TrigByteStreamCnvSvc::getRawEvent() { + const EventContext* eventContext = currentContext(); + if (eventContext == nullptr) return nullptr; + return getRawEvent(*eventContext); +} + +// ============================================================================= +RawEventWrite* TrigByteStreamCnvSvc::getRawEvent(const EventContext& eventContext) const { + return m_rawEventWriteCache.get(eventContext)->get(); +} + +// ============================================================================= +RawEventWrite* TrigByteStreamCnvSvc::setRawEvent(std::unique_ptr<RawEventWrite>&& rawEventWrite, const EventContext& eventContext) { + *(m_rawEventWriteCache.get(eventContext)) = std::move(rawEventWrite); + return getRawEvent(eventContext); +} + +// ============================================================================= +void TrigByteStreamCnvSvc::clearRawEvent(const EventContext& eventContext) { + m_rawEventWriteCache.get(eventContext)->reset(); +} + // ============================================================================= void TrigByteStreamCnvSvc::monitorRawEvent(const std::unique_ptr<uint32_t[]>& rawEventPtr) const { // Create a read fragment from the pointer @@ -346,8 +387,8 @@ void TrigByteStreamCnvSvc::monitorRawEvent(const std::unique_ptr<uint32_t[]>& ra } // ============================================================================= -void TrigByteStreamCnvSvc::printRawEvent() { - RawEventWrite* re = getRawEvent(); +void TrigByteStreamCnvSvc::printRawEvent(const EventContext& eventContext) const { + RawEventWrite* re = getRawEvent(eventContext); if (!re) { ATH_MSG_WARNING("RawEventWrite pointer is null"); diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h index 55e6e0d026e72b8f855d191427a97fddff0c2717..3f3cb49387bf81b1664ea6bc843c60815983e52f 100644 --- a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h +++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h @@ -5,8 +5,9 @@ #ifndef TRIGBYTESTREAMCNVSVC_H #define TRIGBYTESTREAMCNVSVC_H -#include "ByteStreamCnvSvc/ByteStreamCnvSvc.h" +#include "ByteStreamCnvSvcBase/ByteStreamCnvSvcBase.h" #include "AthenaMonitoringKernel/Monitored.h" +#include "AthenaKernel/SlotSpecificObj.h" // Forward declarations class StoreGateSvc; @@ -17,11 +18,8 @@ class IROBDataProviderSvc; * * It overrides the connectOutput and commitOutput methods of the base class. In this implementation, they create * the specific online HLT output and send it out directly to the TDAQ infrastructure without using an output service. - * - * It needs to inherit from ByteStreamCnvSvc rather than ByteStreamCnvSvcBase, because some elements of the athena - * framework (particularly converters) rely on the properties or functionality of the offline ByteStreamCnvSvc. **/ -class TrigByteStreamCnvSvc : public ByteStreamCnvSvc { +class TrigByteStreamCnvSvc : public ByteStreamCnvSvcBase { public: /// Standard constructor TrigByteStreamCnvSvc(const std::string& name, ISvcLocator* svcLoc); @@ -34,24 +32,42 @@ public: // ------------------------- IConversionSvc methods -------------------------- /// In the case of online BS data, this method creates the output FullEventFragment and fills its header - using ByteStreamCnvSvcBase::connectOutput; virtual StatusCode connectOutput(const std::string& outputFile) override; + /// In the case of online BS data, this method creates the output FullEventFragment and fills its header + StatusCode connectOutput(const std::string& outputFile, const EventContext& eventContext); /// This overload is kept only for interface compatibility virtual StatusCode connectOutput(const std::string& outputFile, const std::string& openMode) 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; + /// In the case of online BS data, this method binds and sends out the output FullEventFragment + StatusCode commitOutput(const std::string& outputFile, bool do_commit, const EventContext& eventContext); + + // ------------------------- IByteStreamEventAccess methods ------------------ + /// Return a pointer to the raw event for the current event context + virtual RawEventWrite* getRawEvent() override; + /// Return a pointer to the raw event for the given event context + RawEventWrite* getRawEvent(const EventContext& eventContext) const; private: // ------------------------- Helper methods ---------------------------------- - /// Print contents of m_rawEventWrite - void printRawEvent(); + /// Store new raw event in the cache + RawEventWrite* setRawEvent(std::unique_ptr<RawEventWrite>&& rawEventWrite, const EventContext& eventContext); + /// Delete raw event from the cache + void clearRawEvent(const EventContext& eventContext); + /// Print contents of the raw event + void printRawEvent(const EventContext& eventContext) const; /// Fill histograms from contents of a FullEventFragment void monitorRawEvent(const std::unique_ptr<uint32_t[]>& rawEventPtr) const; + /// Hack used in HLT to avoid using ThreadLocalContext, see explanation in the implementation + const EventContext* currentContext() const; // ------------------------- Service / Tool handles -------------------------- ServiceHandle<StoreGateSvc> m_evtStore {this, "EventStore", "StoreGateSvc"}; ServiceHandle<IROBDataProviderSvc> m_robDataProviderSvc {this, "ROBDataProvider", "ROBDataProviderSvc"}; ToolHandle<GenericMonitoringTool> m_monTool {this, "MonTool", "" , "Monitoring tool"}; + + // ------------------------- Other private members --------------------------- + SG::SlotSpecificObj<std::unique_ptr<RawEventWrite>> m_rawEventWriteCache; }; #endif // TRIGBYTESTREAMCNVSVC_H