From 2ee0c347fc702400e3faf667f150dd4cda774331 Mon Sep 17 00:00:00 2001
From: Rafal Bielski <rafal.bielski@cern.ch>
Date: Tue, 3 Mar 2020 17:05:10 +0100
Subject: [PATCH 1/4] Add hooks for L1TriggerResult BS Converter

---
 .../TrigControl/TrigServices/CMakeLists.txt   |  2 +-
 .../TrigServices/src/HltEventLoopMgr.cxx      | 25 ++++++
 .../TrigServices/src/HltEventLoopMgr.h        |  8 ++
 .../IL1TriggerByteStreamTool.h                |  2 +-
 .../L1TriggerResultByteStreamCnv.h            | 57 ++++++++++++
 .../src/L1TriggerResultByteStreamCnv.cxx      | 90 +++++++++++++++++++
 .../TrigT1ResultByteStream_entries.cxx        |  3 +-
 7 files changed, 184 insertions(+), 3 deletions(-)
 create mode 100644 Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h
 create mode 100644 Trigger/TrigT1/TrigT1ResultByteStream/src/L1TriggerResultByteStreamCnv.cxx

diff --git a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt
index 2d4a6096c81f..3d20158c9555 100644
--- a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt
+++ b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt
@@ -22,7 +22,7 @@ atlas_add_component( TrigServices
                      ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} ${CORAL_LIBRARIES}
                      AthenaBaseComps AthenaInterprocess AthenaKernel AthenaMonitoringKernelLib AthenaPoolUtilities
                      ByteStreamCnvSvcBaseLib ByteStreamData EventInfoUtils GaudiKernel RDBAccessSvcLib StoreGateLib TrigKernel
-                     TrigOutputHandlingLib TrigSteeringEvent xAODEventInfo )
+                     TrigOutputHandlingLib TrigSteeringEvent xAODEventInfo xAODTrigger )
 
 # Install files from the package:
 atlas_install_python_modules( python/*.py
diff --git a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
index ecda27029d09..da1f5678a833 100644
--- a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
+++ b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
@@ -202,6 +202,8 @@ StatusCode HltEventLoopMgr::initialize()
   // HLTResultMT ReadHandle (created dynamically from the result builder property)
   m_hltResultRHKey = m_hltResultMaker->resultName();
   ATH_CHECK(m_hltResultRHKey.initialize());
+  // L1TriggerResult ReadHandle
+  ATH_CHECK(m_l1TriggerResultRHKey.initialize(m_rewriteLVL1.value()));
 
   ATH_MSG_VERBOSE("end of " << __FUNCTION__);
   return StatusCode::SUCCESS;
@@ -1280,6 +1282,28 @@ HltEventLoopMgr::DrainSchedulerStatusCode HltEventLoopMgr::drainScheduler()
     HLT_DRAINSCHED_CHECK(sc, "Conversion service failed to convert HLTResult",
                          HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
 
+    // Retrieve and convert the L1 result to the output data format
+    IOpaqueAddress* l1addr = nullptr;
+    if (m_rewriteLVL1) {
+      auto l1TriggerResult = SG::makeHandle(m_l1TriggerResultRHKey, *thisFinishedEvtContext);
+      if (!l1TriggerResult.isValid()) markFailed();
+      HLT_DRAINSCHED_CHECK(sc, "Failed to retrieve the L1 Trigger Result for RewriteLVL1",
+                          HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
+
+      DataObject* l1TriggerResultDO = m_evtStore->accessData(l1TriggerResult.clid(),l1TriggerResult.key());
+      if (!l1TriggerResultDO) markFailed();
+      HLT_DRAINSCHED_CHECK(sc, "Failed to retrieve the L1 Trigger Result DataObject for RewriteLVL1",
+                          HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
+
+      sc = m_outputCnvSvc->createRep(l1TriggerResultDO,l1addr);
+      if (sc.isFailure()) {
+        delete l1addr;
+        atLeastOneFailed = true;
+      }
+      HLT_DRAINSCHED_CHECK(sc, "Conversion service failed to convert L1 Trigger Result for RewriteLVL1",
+                          HLT::OnlineErrorCode::OUTPUT_BUILD_FAILURE, thisFinishedEvtContext);
+    }
+
     // Save event processing time before sending output
     bool eventAccepted = !hltResult->getStreamTags().empty();
     auto eventTime = std::chrono::steady_clock::now() - m_eventTimerStartPoint[thisFinishedEvtContext->slot()];
@@ -1296,6 +1320,7 @@ HltEventLoopMgr::DrainSchedulerStatusCode HltEventLoopMgr::drainScheduler()
 
     // The output has been sent out, the ByteStreamAddress can be deleted
     delete addr;
+    delete l1addr;
 
     //--------------------------------------------------------------------------
     // Flag idle slot to the timeout thread and reset the timer
diff --git a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.h b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.h
index b797037052d2..8933575fa87f 100644
--- a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.h
+++ b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.h
@@ -17,6 +17,7 @@
 #include "AthenaMonitoringKernel/Monitored.h"
 #include "CxxUtils/checker_macros.h"
 #include "xAODEventInfo/EventInfo.h"
+#include "xAODTrigger/TrigCompositeContainer.h"
 #include "StoreGate/ReadHandleKey.h"
 #include "StoreGate/WriteHandleKey.h"
 
@@ -235,12 +236,19 @@ private:
   Gaudi::Property<unsigned long long> m_forceSOR_ns{
     this, "forceStartOfRunTime", 0, "Override SOR time during prepareForRun (epoch in nano-seconds)"};
 
+  Gaudi::Property<bool> m_rewriteLVL1{
+    this, "RewriteLVL1", false,
+    "Encode L1 results to ByteStream and write to the output. Possible only with athenaHLT, not online."};
+
   SG::WriteHandleKey<EventContext> m_eventContextWHKey{
     this, "EventContextWHKey", "EventContext", "StoreGate key for recording EventContext"};
 
   SG::ReadHandleKey<xAOD::EventInfo> m_eventInfoRHKey{
     this, "EventInfoRHKey", "EventInfo", "StoreGate key for reading xAOD::EventInfo"};
 
+  SG::ReadHandleKey<xAOD::TrigCompositeContainer> m_l1TriggerResultRHKey{
+    this, "L1TriggerResultRHKey", "L1TriggerResult", "StoreGate key for reading L1TriggerResult for RewriteLVL1"};
+
   SG::ReadHandleKey<HLT::HLTResultMT> m_hltResultRHKey;    ///< StoreGate key for reading the HLT result
 
   // ------------------------- Other private members ---------------------------
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
index 300b84b6efa4..7dc2720e1217 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
@@ -5,8 +5,8 @@
 #define TRIGT1RESULTBYTESTREAM_IL1TRIGGERBYTESTREAMTOOL_H
 
 #include "ByteStreamData/RawEvent.h"
-#include "xAODTrigger/TrigComposite.h"
 #include "GaudiKernel/IAlgTool.h"
+#include "GaudiKernel/EventContext.h"
 
 /**
  * @class IL1TriggerByteStreamTool
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h
new file mode 100644
index 000000000000..2bc7e8b2a1d2
--- /dev/null
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGT1RESULTBYTESTREAM_L1TRIGGERRESULTBYTESTREAMCNV_H
+#define TRIGT1RESULTBYTESTREAM_L1TRIGGERRESULTBYTESTREAMCNV_H
+
+// Trigger includes
+// #include "TrigHLTResultByteStream/HLTSrcIdMap.h"
+
+// Athena includes
+#include "AthenaBaseComps/AthMessaging.h"
+#include "ByteStreamCnvSvcBase/IByteStreamEventAccess.h"
+#include "ByteStreamCnvSvcBase/FullEventAssembler.h"
+
+// Gaudi includes
+#include "GaudiKernel/Converter.h"
+
+/** @class L1TriggerResultByteStreamCnv
+ *  @brief ByteStream converter for L1TriggerResult
+ **/
+class L1TriggerResultByteStreamCnv : public Converter, public AthMessaging {
+public:
+  /// Standard constructor
+  L1TriggerResultByteStreamCnv(ISvcLocator* svcLoc);
+  /// Standard destructor
+  virtual ~L1TriggerResultByteStreamCnv();
+
+  // ------------------------- Converter methods -----------------------------
+  virtual StatusCode initialize() override;
+  virtual StatusCode finalize() override;
+
+  /// Create xAOD (L1TriggerResult) from ByteStream
+  virtual StatusCode createObj(IOpaqueAddress* pAddr, DataObject*& pObj) override;
+  /// Create ByteStream from xAOD (L1TriggerResult)
+  virtual StatusCode createRep(DataObject* pObj, IOpaqueAddress*& pAddr) override;
+
+  // ------------------------- Converter definition helpers ------------------
+  /// Storage type used by this converter
+  static long storageType();
+  /// CLID of the class of the L1TriggerResult converted by this converter (xAOD::TrigCompositeContainer)
+  static const CLID& classID();
+
+  long repSvcType() const override { return i_repSvcType(); } //!< return repSvcType
+
+private:
+  /// Helper to obtain the RawEvent pointer
+  ServiceHandle<IByteStreamEventAccess> m_ByteStreamEventAccess;
+
+  /// Helper for filling ROBFragments
+  // FullEventAssembler<HLTSrcIdMap> m_fullEventAssembler;
+
+  /// Buffer for serialised StreamTag data
+  std::unique_ptr<uint32_t[]> m_streamTagData;
+};
+
+#endif // TRIGT1RESULTBYTESTREAM_L1TRIGGERRESULTBYTESTREAMCNV_H
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/src/L1TriggerResultByteStreamCnv.cxx b/Trigger/TrigT1/TrigT1ResultByteStream/src/L1TriggerResultByteStreamCnv.cxx
new file mode 100644
index 000000000000..46ae5e49a77e
--- /dev/null
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/src/L1TriggerResultByteStreamCnv.cxx
@@ -0,0 +1,90 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Trigger includes
+#include "TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h"
+#include "xAODTrigger/TrigCompositeContainer.h"
+
+// Athena includes
+#include "AthenaBaseComps/AthCheckMacros.h"
+#include "AthenaKernel/ClassID_traits.h"
+#include "AthenaKernel/StorableConversions.h"
+#include "ByteStreamCnvSvcBase/ByteStreamAddress.h"
+#include "ByteStreamData/RawEvent.h"
+
+// Gaudi includes
+#include "GaudiKernel/IRegistry.h"
+
+// TDAQ includes
+#include "eformat/Issue.h"
+#include "eformat/SourceIdentifier.h"
+
+// =============================================================================
+// Standard constructor
+// =============================================================================
+L1TriggerResultByteStreamCnv::L1TriggerResultByteStreamCnv(ISvcLocator* svcLoc) :
+  Converter(storageType(), classID(), svcLoc),
+  AthMessaging(msgSvc(), "L1TriggerResultByteStreamCnv"),
+  m_ByteStreamEventAccess("ByteStreamCnvSvc", "L1TriggerResultByteStreamCnv") {
+    // m_fullEventAssembler.idMap().setDetId(eformat::TDAQ_HLT);
+    // m_fullEventAssembler.setRodMinorVersion(hltRodMinorVersion);
+   }
+
+// =============================================================================
+// Standard destructor
+// =============================================================================
+L1TriggerResultByteStreamCnv::~L1TriggerResultByteStreamCnv() {}
+
+// =============================================================================
+// Implementation of Converter::initialize
+// =============================================================================
+StatusCode L1TriggerResultByteStreamCnv::initialize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  ATH_CHECK(m_ByteStreamEventAccess.retrieve());
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of Converter::finalize
+// =============================================================================
+StatusCode L1TriggerResultByteStreamCnv::finalize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  if (m_ByteStreamEventAccess.release().isFailure())
+    ATH_MSG_WARNING("Failed to release service " << m_ByteStreamEventAccess.typeAndName());
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of Converter::createObj
+// =============================================================================
+StatusCode L1TriggerResultByteStreamCnv::createObj(IOpaqueAddress* /*pAddr*/, DataObject*& /*pObj*/) {
+  ATH_MSG_ERROR("L1TriggerResult cannot be created directly from ByteStream!"
+                << " Use the L1TriggerResultMaker algorithm instead");
+  return StatusCode::FAILURE;
+}
+
+// =============================================================================
+// Implementation of Converter::createRep
+// =============================================================================
+StatusCode L1TriggerResultByteStreamCnv::createRep(DataObject* pObj, IOpaqueAddress*& pAddr) {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+
+  ATH_MSG_INFO("RB: Hello, this is " << __FUNCTION__);
+
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// CLID / storageType
+// =============================================================================
+const CLID& L1TriggerResultByteStreamCnv::classID() {
+  return ClassID_traits<xAOD::TrigCompositeContainer>::ID();
+}
+
+long L1TriggerResultByteStreamCnv::storageType() {
+  return ByteStreamAddress::storageType();
+}
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/src/components/TrigT1ResultByteStream_entries.cxx b/Trigger/TrigT1/TrigT1ResultByteStream/src/components/TrigT1ResultByteStream_entries.cxx
index 8c5b33ce982b..2f65b961e984 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/src/components/TrigT1ResultByteStream_entries.cxx
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/src/components/TrigT1ResultByteStream_entries.cxx
@@ -1,4 +1,4 @@
-
+#include "TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h"
 #include "TrigT1ResultByteStream/RoIBResultByteStreamCnv.h"
 #include "TrigT1ResultByteStream/RecRoIBResultByteStreamCnv.h"
 
@@ -26,6 +26,7 @@ typedef RoIBResultByteStreamCnv<ROBF> RoIBResultByteStreamCnvT ;
 typedef RecRoIBResultByteStreamCnv<ROBF> RecRoIBResultByteStreamCnvT ;
 
 // declare 
+DECLARE_CONVERTER( L1TriggerResultByteStreamCnv )
 DECLARE_CONVERTER( RoIBResultByteStreamCnvT )
 DECLARE_CONVERTER( RecRoIBResultByteStreamCnvT )
 DECLARE_CONVERTER( MuCTPIByteStreamCnv )
-- 
GitLab


From 30229b2de717fdc45615bc2bd390142f9681db94 Mon Sep 17 00:00:00 2001
From: Rafal Bielski <rafal.bielski@cern.ch>
Date: Tue, 3 Mar 2020 18:23:09 +0100
Subject: [PATCH 2/4] Implement L1 BS encoding example

---
 .../TrigServices/src/HltEventLoopMgr.cxx      |  5 ++
 .../IL1TriggerByteStreamTool.h                |  2 +-
 .../L1TriggerResultByteStreamCnv.h            | 16 ++---
 .../python/TrigT1ResultByteStreamConfig.py    | 44 ++++++++++---
 .../src/ExampleL1TriggerByteStreamTool.cxx    | 27 +++++++-
 .../src/ExampleL1TriggerByteStreamTool.h      |  2 +-
 .../src/L1TriggerResultByteStreamCnv.cxx      | 61 +++++++++++++++++--
 .../TriggerJobOpts/python/Modifiers.py        | 27 ++------
 8 files changed, 138 insertions(+), 46 deletions(-)

diff --git a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
index da1f5678a833..f8db3ec7761d 100644
--- a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
+++ b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
@@ -130,6 +130,11 @@ StatusCode HltEventLoopMgr::initialize()
   ATH_MSG_INFO(" ---> AlgErrorDebugStreamName   = " << m_algErrorDebugStreamName.value());
   ATH_MSG_INFO(" ---> TimeoutDebugStreamName    = " << m_timeoutDebugStreamName.value());
   ATH_MSG_INFO(" ---> TruncationDebugStreamName = " << m_truncationDebugStreamName.value());
+  ATH_MSG_INFO(" ---> SORPath                   = " << m_sorPath.value());
+  ATH_MSG_INFO(" ---> setMagFieldFromPtree      = " << m_setMagFieldFromPtree.value());
+  ATH_MSG_INFO(" ---> forceRunNumber            = " << m_forceRunNumber.value());
+  ATH_MSG_INFO(" ---> forceStartOfRunTime       = " << m_forceSOR_ns.value());
+  ATH_MSG_INFO(" ---> RewriteLVL1               = " << m_rewriteLVL1.value());
   ATH_MSG_INFO(" ---> EventContextWHKey         = " << m_eventContextWHKey.key());
   ATH_MSG_INFO(" ---> EventInfoRHKey            = " << m_eventInfoRHKey.key());
 
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
index 7dc2720e1217..306f3883370a 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
@@ -32,7 +32,7 @@ public:
    * The implementation should take the xAOD RoI object from the event store using a ReadHandle it declares,
    * convert it to raw data, and fill the vrobf vector.
    **/
-  virtual StatusCode convertToBS(std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*>& vrobf,
+  virtual StatusCode convertToBS(std::vector<OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment*>& vrobf,
                                  const EventContext& eventContext) const = 0;
 
   /**
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h
index 2bc7e8b2a1d2..d069fb6c0500 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/L1TriggerResultByteStreamCnv.h
@@ -1,12 +1,12 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef TRIGT1RESULTBYTESTREAM_L1TRIGGERRESULTBYTESTREAMCNV_H
 #define TRIGT1RESULTBYTESTREAM_L1TRIGGERRESULTBYTESTREAMCNV_H
 
 // Trigger includes
-// #include "TrigHLTResultByteStream/HLTSrcIdMap.h"
+#include "TrigT1ResultByteStream/IL1TriggerByteStreamTool.h"
 
 // Athena includes
 #include "AthenaBaseComps/AthMessaging.h"
@@ -47,11 +47,13 @@ private:
   /// Helper to obtain the RawEvent pointer
   ServiceHandle<IByteStreamEventAccess> m_ByteStreamEventAccess;
 
-  /// Helper for filling ROBFragments
-  // FullEventAssembler<HLTSrcIdMap> m_fullEventAssembler;
-
-  /// Buffer for serialised StreamTag data
-  std::unique_ptr<uint32_t[]> m_streamTagData;
+  // Tools performing the decoding work - *public* tools hard-coded in C++ because of Converter interface limitations
+  /// Encoder tool for L1Muon RoIs
+  ToolHandle<IL1TriggerByteStreamTool> m_muonEncoderTool;
+  // Placeholder for other L1 xAOD outputs:
+  // - CTP result
+  // - L1Topo result
+  // - L1Calo (Run3) RoIs
 };
 
 #endif // TRIGT1RESULTBYTESTREAM_L1TRIGGERRESULTBYTESTREAMCNV_H
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/python/TrigT1ResultByteStreamConfig.py b/Trigger/TrigT1/TrigT1ResultByteStream/python/TrigT1ResultByteStreamConfig.py
index f746167aab49..80ca34dac0d1 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/python/TrigT1ResultByteStreamConfig.py
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/python/TrigT1ResultByteStreamConfig.py
@@ -14,17 +14,30 @@ def RoIBResultDecoderCfg(flags):
   acc.addEventAlgo(decoderAlg)
   return acc
 
+from TrigT1ResultByteStream.TrigT1ResultByteStreamConf import ExampleL1TriggerByteStreamTool as _ExampleL1TriggerByteStreamTool
+class ExampleL1TriggerByteStreamTool(_ExampleL1TriggerByteStreamTool):
+  def __init__(self, name, writeBS=False, *args, **kwargs):
+    super(ExampleL1TriggerByteStreamTool, self).__init__(name, *args, **kwargs)
+    from libpyeformat_helper import SourceIdentifier,SubDetector
+    muctpi_moduleid = 1
+    muctpi_robid = int(SourceIdentifier(SubDetector.TDAQ_MUON_CTP_INTERFACE, muctpi_moduleid))
+    self.MUCTPIModuleId = muctpi_moduleid
+    self.ROBIDs = [muctpi_robid]
+    if writeBS:
+      # write BS == read xAOD
+      self.MuonRoIContainerReadKey="LVL1MuonRoIs"
+      self.MuonRoIContainerWriteKey=""
+    else:
+      # read BS == write xAOD
+      self.MuonRoIContainerReadKey=""
+      self.MuonRoIContainerWriteKey="LVL1MuonRoIs"
+
 def L1TriggerByteStreamDecoderCfg(flags):
-  from TrigT1ResultByteStream.TrigT1ResultByteStreamConf import L1TriggerByteStreamDecoderAlg,ExampleL1TriggerByteStreamTool
-  from libpyeformat_helper import SourceIdentifier,SubDetector
+  from TrigT1ResultByteStream.TrigT1ResultByteStreamConf import L1TriggerByteStreamDecoderAlg
+  from TrigT1ResultByteStream.TrigT1ResultByteStreamConfig import ExampleL1TriggerByteStreamTool
 
   # Placeholder for real decoder tools - now it's just an example
-  muctpi_moduleid = 1
-  muctpi_robid = int(SourceIdentifier(SubDetector.TDAQ_MUON_CTP_INTERFACE, muctpi_moduleid))
-  exampleTool = ExampleL1TriggerByteStreamTool(ROBIDs=[muctpi_robid],
-                                               MUCTPIModuleId=muctpi_moduleid,
-                                               MuonRoIContainerWriteKey="LVL1MuonRoIs")
-
+  exampleTool = ExampleL1TriggerByteStreamTool(name="L1MuonBSDecoderTool", writeBS=False)
   decoderTools = [exampleTool]
 
   decoderAlg = L1TriggerByteStreamDecoderAlg(name="L1TriggerByteStreamDecoder",
@@ -35,6 +48,15 @@ def L1TriggerByteStreamDecoderCfg(flags):
   acc.addEventAlgo(decoderAlg)
   return acc
 
+def L1TriggerByteStreamEncoderCfg(flags):
+  from TrigT1ResultByteStream.TrigT1ResultByteStreamConfig import ExampleL1TriggerByteStreamTool
+  exampleTool = ExampleL1TriggerByteStreamTool(name="L1MuonBSEncoderTool", writeBS=True)
+
+  from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+  acc = ComponentAccumulator()
+  acc.addPublicTool(exampleTool)
+  return acc
+
 def L1ByteStreamDecodersRecExSetup(enableRun2L1=True, enableRun3L1=True):
   # Use new-style config from the above functions and import into old-style JO
   from AthenaConfiguration.ComponentAccumulator import CAtoGlobalWrapper
@@ -43,3 +65,9 @@ def L1ByteStreamDecodersRecExSetup(enableRun2L1=True, enableRun3L1=True):
     CAtoGlobalWrapper(RoIBResultDecoderCfg,ConfigFlags)
   if enableRun3L1:
     CAtoGlobalWrapper(L1TriggerByteStreamDecoderCfg,ConfigFlags)
+
+def L1ByteStreamEncodersRecExSetup():
+  # Use new-style config from the above functions and import into old-style JO
+  from AthenaConfiguration.ComponentAccumulator import CAtoGlobalWrapper
+  from AthenaConfiguration.AllConfigFlags import ConfigFlags
+  CAtoGlobalWrapper(L1TriggerByteStreamEncoderCfg,ConfigFlags)
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.cxx b/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.cxx
index 716f047ce303..63e20d66a8db 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.cxx
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.cxx
@@ -6,8 +6,10 @@
 #include "xAODTrigger/MuonRoI.h"
 #include "xAODTrigger/MuonRoIAuxContainer.h"
 #include "eformat/SourceIdentifier.h"
+#include "eformat/Status.h"
 
 using ROBF = OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment;
+using WROBF = OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment;
 
 ExampleL1TriggerByteStreamTool::ExampleL1TriggerByteStreamTool(const std::string& type,
                                                                const std::string& name,
@@ -55,6 +57,7 @@ StatusCode ExampleL1TriggerByteStreamTool::convertFromBS(const std::vector<const
   const uint32_t* data = rob->rod_data();
   ATH_MSG_DEBUG("Starting to decode " << ndata << " ROD words");
   for (uint32_t i=0; i<ndata; ++i, ++data) {
+    ATH_MSG_DEBUG("Muon RoI raw word: " << *data);
     // Here comes the decoding
     // Using some dummy values as this is not real decoding, just an example
     handle->push_back(new xAOD::MuonRoI);
@@ -66,13 +69,33 @@ StatusCode ExampleL1TriggerByteStreamTool::convertFromBS(const std::vector<const
 }
 
 /// xAOD->BS conversion
-StatusCode ExampleL1TriggerByteStreamTool::convertToBS(std::vector<const ROBF*>& /*vrobf*/,
+StatusCode ExampleL1TriggerByteStreamTool::convertToBS(std::vector<WROBF*>& vrobf,
                                                        const EventContext& eventContext) const {
   // Retrieve the RoI container
   auto muonRoIs = SG::makeHandle(m_roiReadKey, eventContext);
   ATH_CHECK(muonRoIs.isValid());
 
-  // TODO: implement this part when new code requesting the xAOD->BS conversion is implemented (ATR-19542)
+  ATH_MSG_DEBUG("Converting " << muonRoIs->size() << " L1 Muon RoIs to ByteStream");
+  std::unique_ptr<uint32_t[]> data = std::make_unique<uint32_t[]>(muonRoIs->size());
+  for (size_t i=0; i<muonRoIs->size(); ++i) {
+    data[i] = muonRoIs->at(i)->roiWord();
+  }
+
+  const eformat::helper::SourceIdentifier sid(eformat::TDAQ_MUON_CTP_INTERFACE, m_muCTPIModuleID.value());
+  const EventIDBase& eid = eventContext.eventID();
+  // The WROBF allocated here and the data buffer inside it have to be deleted
+  // by the TrigByteStreamCnvSvc after writing to the output file
+  vrobf.push_back(new WROBF(
+    sid.code(),
+    eid.run_number(),
+    eid.event_number(),
+    eid.bunch_crossing_id(),
+    0, // lvl1_type will be overwritten downstream from full event fragment
+    0, // detev_type is system-specific
+    muonRoIs->size(),
+    std::move(data.release()),
+    eformat::STATUS_BACK // status_position is system-specific
+  ));
 
   return StatusCode::SUCCESS;
 }
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.h b/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.h
index dd6c72cf0c7a..cee710ee3a6d 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.h
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.h
@@ -37,7 +37,7 @@ public:
   virtual StatusCode convertFromBS(const std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*>& vrobf,
                                    const EventContext& eventContext) const override;
   /// xAOD->BS conversion
-  virtual StatusCode convertToBS(std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*>& vrobf,
+  virtual StatusCode convertToBS(std::vector<OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment*>& vrobf,
                                  const EventContext& eventContext) const override;
   /// Declare ROB IDs for conversion
   virtual const std::vector<uint32_t> robIds() const override {return m_robIds.value();}
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/src/L1TriggerResultByteStreamCnv.cxx b/Trigger/TrigT1/TrigT1ResultByteStream/src/L1TriggerResultByteStreamCnv.cxx
index 46ae5e49a77e..67f6170e9e41 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/src/L1TriggerResultByteStreamCnv.cxx
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/src/L1TriggerResultByteStreamCnv.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 // Trigger includes
@@ -15,21 +15,22 @@
 
 // Gaudi includes
 #include "GaudiKernel/IRegistry.h"
+#include "GaudiKernel/ThreadLocalContext.h"
 
 // TDAQ includes
 #include "eformat/Issue.h"
 #include "eformat/SourceIdentifier.h"
 
+using WROBF = OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment;
+
 // =============================================================================
 // Standard constructor
 // =============================================================================
 L1TriggerResultByteStreamCnv::L1TriggerResultByteStreamCnv(ISvcLocator* svcLoc) :
   Converter(storageType(), classID(), svcLoc),
   AthMessaging(msgSvc(), "L1TriggerResultByteStreamCnv"),
-  m_ByteStreamEventAccess("ByteStreamCnvSvc", "L1TriggerResultByteStreamCnv") {
-    // m_fullEventAssembler.idMap().setDetId(eformat::TDAQ_HLT);
-    // m_fullEventAssembler.setRodMinorVersion(hltRodMinorVersion);
-   }
+  m_ByteStreamEventAccess("ByteStreamCnvSvc", "L1TriggerResultByteStreamCnv"),
+  m_muonEncoderTool("ExampleL1TriggerByteStreamTool/ToolSvc.L1MuonBSEncoderTool") {}
 
 // =============================================================================
 // Standard destructor
@@ -42,6 +43,8 @@ L1TriggerResultByteStreamCnv::~L1TriggerResultByteStreamCnv() {}
 StatusCode L1TriggerResultByteStreamCnv::initialize() {
   ATH_MSG_VERBOSE("start of " << __FUNCTION__);
   ATH_CHECK(m_ByteStreamEventAccess.retrieve());
+  ATH_CHECK(m_muonEncoderTool.retrieve());
+
   ATH_MSG_VERBOSE("end of " << __FUNCTION__);
   return StatusCode::SUCCESS;
 }
@@ -53,6 +56,8 @@ StatusCode L1TriggerResultByteStreamCnv::finalize() {
   ATH_MSG_VERBOSE("start of " << __FUNCTION__);
   if (m_ByteStreamEventAccess.release().isFailure())
     ATH_MSG_WARNING("Failed to release service " << m_ByteStreamEventAccess.typeAndName());
+  if (m_muonEncoderTool.release().isFailure())
+    ATH_MSG_WARNING("Failed to release tool " << m_muonEncoderTool.typeAndName());
   ATH_MSG_VERBOSE("end of " << __FUNCTION__);
   return StatusCode::SUCCESS;
 }
@@ -72,7 +77,51 @@ StatusCode L1TriggerResultByteStreamCnv::createObj(IOpaqueAddress* /*pAddr*/, Da
 StatusCode L1TriggerResultByteStreamCnv::createRep(DataObject* pObj, IOpaqueAddress*& pAddr) {
   ATH_MSG_VERBOSE("start of " << __FUNCTION__);
 
-  ATH_MSG_INFO("RB: Hello, this is " << __FUNCTION__);
+  // Cast the DataObject to L1TriggerResult
+  xAOD::TrigCompositeContainer* l1TriggerResult = nullptr;
+  bool castSuccessful = SG::fromStorable(pObj, l1TriggerResult);
+  if (!castSuccessful || !l1TriggerResult) {
+    ATH_MSG_ERROR("Failed to convert DataObject to xAOD::TrigCompositeContainer for L1TriggerResult");
+    return StatusCode::FAILURE;
+  }
+
+  // Obtain the RawEventWrite (aka eformat::write::FullEventFragment) pointer
+  RawEventWrite* re = m_ByteStreamEventAccess->getRawEvent();
+  if (!re) {
+    ATH_MSG_ERROR("Failed to obtain a pointer to RawEventWrite");
+    return StatusCode::FAILURE;
+  }
+  ATH_MSG_VERBOSE("Obtained RawEventWrite pointer = " << re);
+
+  // CTP encoding should come here when implemented and update full event header (L1 trigger bits)
+  // in addition to encoding the corresponding ROBFragment.
+  // The xAOD CTP result object holding the bits will be obtained here via ElementLink from l1TriggerResult
+
+  // Example muon RoI encoding - placeholder for concrete implementation
+  std::vector<WROBF*> muon_robs;
+  ATH_CHECK(m_muonEncoderTool->convertToBS(muon_robs, Gaudi::Hive::currentContext())); // TODO: find a way to avoid ThreadLocalContext
+  ATH_MSG_DEBUG("Created " << muon_robs.size() << " L1Muon ROB Fragments");
+  for (WROBF* rob : muon_robs) {
+    if (msgLvl(MSG::DEBUG)) {
+      const uint32_t ndata = rob->rod_ndata();
+      const uint32_t* data = rob->rod_data();
+      ATH_MSG_DEBUG("This ROB has " << ndata << " data words");
+      for (uint32_t i=0; i<ndata; ++i, ++data) {
+        ATH_MSG_DEBUG("--- " << MSG::hex << *data << MSG::dec);
+      }
+    }
+    // Set LVL1 Trigger Type from the full event
+    rob->rod_lvl1_type(re->lvl1_trigger_type());
+    // Add the ROBFragment to the full event
+    re->append(rob);
+    ATH_MSG_DEBUG("Added ROB fragment " << MSG::hex << rob->source_id() << MSG::dec << " to the output raw event");
+  }
+
+  // Placeholder for other systems: L1Topo, L1Calo
+
+  // Create a ByteStreamAddress for L1TriggerResult
+  ByteStreamAddress* bsAddr = new ByteStreamAddress(classID(), pObj->registry()->name(), "");
+  pAddr = static_cast<IOpaqueAddress*>(bsAddr);
 
   ATH_MSG_VERBOSE("end of " << __FUNCTION__);
   return StatusCode::SUCCESS;
diff --git a/Trigger/TriggerCommon/TriggerJobOpts/python/Modifiers.py b/Trigger/TriggerCommon/TriggerJobOpts/python/Modifiers.py
index 21ccb15e1517..932b1d6de013 100644
--- a/Trigger/TriggerCommon/TriggerJobOpts/python/Modifiers.py
+++ b/Trigger/TriggerCommon/TriggerJobOpts/python/Modifiers.py
@@ -770,33 +770,18 @@ class rewriteLVL1(_modifier):
     Rewrite LVL1 (use together with rerunLVL1)
     """
     # Example:
-    # athena -c "testPhysicsV3=1;rerunLVL1=1;rewriteLVL1=1;doLVL2=False;doEF=False;BSRDOInput='input.data'" TriggerJobOpts/runHLT_standalone.py
+    # athenaHLT -c "setMenu='PhysicsP1_pp_run3_v1';rerunLVL1=True;rewriteLVL1=True;" --filesInput=input.data TriggerJobOpts/runHLT_standalone.py
+
+    def preSetup(self):
+        from TrigT1ResultByteStream.TrigT1ResultByteStreamConfig import L1ByteStreamEncodersRecExSetup
+        L1ByteStreamEncodersRecExSetup()
 
     def postSetup(self):
         from AthenaCommon.AppMgr import ServiceMgr as svcMgr
-        from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
         from TriggerJobOpts.TriggerFlags import TriggerFlags
 
-        # Process all events
-        theApp.EvtMax = -1
         TriggerFlags.writeBS = True
-
-        athenaCommonFlags.BSRDOOutput = 'AppName=Athena, OutputDirectory=./, FileTag=testWrite'
-        # Persistent BS construction and intialization
-        from ByteStreamCnvSvc import WriteByteStream
-        StreamBSFileOutput = WriteByteStream.getStream("EventStorage","StreamBSFileOutput")
-
-        # Bytestream conversion
-        StreamBSFileOutput.ItemList += [ "ROIB::RoIBResult#*" ]
-
-        # Merge with original bytestream
-        from ByteStreamCnvSvc.ByteStreamCnvSvcConf import ByteStreamMergeOutputSvc
-        svcMgr += ByteStreamMergeOutputSvc(ByteStreamOutputSvc='ByteStreamEventStorageOutputSvc',
-                                           ByteStreamInputSvc='ByteStreamInputSvc',
-                                           overWriteHeader=True)
-
-        StreamBSFileOutput.OutputFile = "ByteStreamMergeOutputSvc"
-        svcMgr.ByteStreamCnvSvc.ByteStreamOutputSvcList=['ByteStreamMergeOutputSvc']
+        svcMgr.HltEventLoopMgr.RewriteLVL1 = True
 
 
 class writeBS(_modifier):
-- 
GitLab


From ecddb8ed4dfac0b1b92fc191c4cfaae7fc1da17f Mon Sep 17 00:00:00 2001
From: Rafal Bielski <rafal.bielski@cern.ch>
Date: Mon, 9 Mar 2020 14:16:53 +0100
Subject: [PATCH 3/4] Implement cache for output ByteStream data

---
 .../IL1TriggerByteStreamTool.h                | 43 ++++++++++++++++++-
 .../src/ExampleL1TriggerByteStreamTool.cxx    | 16 ++++---
 .../src/ExampleL1TriggerByteStreamTool.h      |  2 +-
 3 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
index 306f3883370a..473e51dc80f3 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
@@ -5,6 +5,7 @@
 #define TRIGT1RESULTBYTESTREAM_IL1TRIGGERBYTESTREAMTOOL_H
 
 #include "ByteStreamData/RawEvent.h"
+#include "AthenaKernel/SlotSpecificObj.h"
 #include "GaudiKernel/IAlgTool.h"
 #include "GaudiKernel/EventContext.h"
 
@@ -30,10 +31,12 @@ public:
    * @brief Convert xAOD -> BS
    *
    * The implementation should take the xAOD RoI object from the event store using a ReadHandle it declares,
-   * convert it to raw data, and fill the vrobf vector.
+   * convert it to raw data, and fill the vrobf vector. The function is not const, as it needs to rely on
+   * the internal cache to track data allocated for BS representation. The provided helpers clearCache,
+   * newRodData, newRobFragment should be used to allocate memory for the BS representation.
    **/
   virtual StatusCode convertToBS(std::vector<OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment*>& vrobf,
-                                 const EventContext& eventContext) const = 0;
+                                 const EventContext& eventContext) = 0;
 
   /**
    * @brief List of IDs of ROBs which the convert methods expect in the vrobf input/output parameter
@@ -43,6 +46,42 @@ public:
    * in the interface, so it is delegated to the implementation.
    **/
   virtual const std::vector<uint32_t> robIds() const = 0;
+
+protected:
+  /// Helper to clear the ByteStream data cache for a given event slot
+  inline void clearCache(const EventContext& eventContext) {
+    m_cache[eventContext.slot()].clear();
+  }
+  /// Allocate new array of raw ROD words for output ByteStream data
+  inline uint32_t* newRodData(const EventContext& eventContext, const size_t size) {
+    m_cache[eventContext.slot()].rodData.push_back(std::make_unique<uint32_t[]>(size));
+    return m_cache[eventContext.slot()].rodData.back().get();
+  }
+  /// Allocate new ROBFragment for output ByteStream data
+  template<typename ...Ts> inline OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment* newRobFragment(const EventContext& eventContext, Ts... args) {
+    m_cache[eventContext.slot()].robFragments.push_back(std::make_unique<OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment>(args...));
+    return m_cache[eventContext.slot()].robFragments.back().get();
+  }
+private:
+  /**
+   * @brief Cache which tracks memory allocated for ByteStream data representation in the convertToBS method.
+   *
+   * The raw ROD data and the ROBFragment object need to remain valid until they are packed into the output
+   * full event at the very end of event processing. Due to this requirement, the cache is cleared only on the
+   * next event by calling the clearCache method.
+   **/
+  struct Cache {
+    std::vector<std::unique_ptr<uint32_t[]>> rodData;
+    std::vector<std::unique_ptr<OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment>> robFragments;
+    ~Cache() {clear();}
+    void clear() {
+      for (auto& ptr : rodData) ptr.reset();
+      rodData.clear();
+      for (auto& ptr : robFragments) ptr.reset();
+      robFragments.clear();
+    }
+  };
+  std::unordered_map<EventContext::ContextID_t, Cache> m_cache; // one cache per event slot
 };
 
 #endif // TRIGT1RESULTBYTESTREAM_IL1TRIGGERBYTESTREAMTOOL_H
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.cxx b/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.cxx
index 63e20d66a8db..95901cf65bfc 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.cxx
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.cxx
@@ -70,22 +70,26 @@ StatusCode ExampleL1TriggerByteStreamTool::convertFromBS(const std::vector<const
 
 /// xAOD->BS conversion
 StatusCode ExampleL1TriggerByteStreamTool::convertToBS(std::vector<WROBF*>& vrobf,
-                                                       const EventContext& eventContext) const {
+                                                       const EventContext& eventContext) {
   // Retrieve the RoI container
   auto muonRoIs = SG::makeHandle(m_roiReadKey, eventContext);
   ATH_CHECK(muonRoIs.isValid());
 
+  // Clear BS data cache
+  clearCache(eventContext);
+
+  // Create raw ROD data words
   ATH_MSG_DEBUG("Converting " << muonRoIs->size() << " L1 Muon RoIs to ByteStream");
-  std::unique_ptr<uint32_t[]> data = std::make_unique<uint32_t[]>(muonRoIs->size());
+  uint32_t* data = newRodData(eventContext, muonRoIs->size());
   for (size_t i=0; i<muonRoIs->size(); ++i) {
     data[i] = muonRoIs->at(i)->roiWord();
   }
 
+  // Create ROBFragment containing the ROD words
   const eformat::helper::SourceIdentifier sid(eformat::TDAQ_MUON_CTP_INTERFACE, m_muCTPIModuleID.value());
   const EventIDBase& eid = eventContext.eventID();
-  // The WROBF allocated here and the data buffer inside it have to be deleted
-  // by the TrigByteStreamCnvSvc after writing to the output file
-  vrobf.push_back(new WROBF(
+  vrobf.push_back(newRobFragment(
+    eventContext,
     sid.code(),
     eid.run_number(),
     eid.event_number(),
@@ -93,7 +97,7 @@ StatusCode ExampleL1TriggerByteStreamTool::convertToBS(std::vector<WROBF*>& vrob
     0, // lvl1_type will be overwritten downstream from full event fragment
     0, // detev_type is system-specific
     muonRoIs->size(),
-    std::move(data.release()),
+    data,
     eformat::STATUS_BACK // status_position is system-specific
   ));
 
diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.h b/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.h
index cee710ee3a6d..eb13d733f3d4 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.h
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/src/ExampleL1TriggerByteStreamTool.h
@@ -38,7 +38,7 @@ public:
                                    const EventContext& eventContext) const override;
   /// xAOD->BS conversion
   virtual StatusCode convertToBS(std::vector<OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment*>& vrobf,
-                                 const EventContext& eventContext) const override;
+                                 const EventContext& eventContext) override;
   /// Declare ROB IDs for conversion
   virtual const std::vector<uint32_t> robIds() const override {return m_robIds.value();}
 
-- 
GitLab


From 4df75229139434c6a74533a14ba2b4140b87d30a Mon Sep 17 00:00:00 2001
From: Rafal Bielski <rafal.bielski@cern.ch>
Date: Mon, 9 Mar 2020 14:36:00 +0100
Subject: [PATCH 4/4] Remove unused header

---
 .../TrigT1ResultByteStream/IL1TriggerByteStreamTool.h            | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
index 473e51dc80f3..cd0ea734e55b 100644
--- a/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
+++ b/Trigger/TrigT1/TrigT1ResultByteStream/TrigT1ResultByteStream/IL1TriggerByteStreamTool.h
@@ -5,7 +5,6 @@
 #define TRIGT1RESULTBYTESTREAM_IL1TRIGGERBYTESTREAMTOOL_H
 
 #include "ByteStreamData/RawEvent.h"
-#include "AthenaKernel/SlotSpecificObj.h"
 #include "GaudiKernel/IAlgTool.h"
 #include "GaudiKernel/EventContext.h"
 
-- 
GitLab