From 717dbbcded6028160a8ed670e06ed7f4b298449c Mon Sep 17 00:00:00 2001
From: scott snyder <sss@karma>
Date: Wed, 21 Oct 2020 10:51:31 -0400
Subject: [PATCH] LArByteStream: Enable thread-safety checking.

Enable thread-safety checking.
Fix identified issues.
Also more constness fixes.

Use conditions data in converters rather than relying on obsolete tools.
Make pointers to block structure objects slot-specific.
---
 .../LArByteStream/ATLAS_CHECK_THREAD_SAFETY   |   1 +
 ...ArAccumulatedCalibDigitContByteStreamCnv.h |   3 +
 .../LArCalibDigitContByteStreamCnv.h          |   5 +
 .../LArRawDataContByteStreamTool.h            |  19 +-
 .../LArRawDataContByteStreamTool.icc          |  10 +-
 .../LArByteStream/LArRodDecoder.h             | 146 ++-----
 .../LArByteStream/LArRodEncoder.h             |   2 +-
 ...AccumulatedCalibDigitContByteStreamCnv.cxx |  11 +-
 .../src/LArCalibDigitContByteStreamCnv.cxx    |  16 +-
 .../src/LArRawDataContByteStreamTool.cxx      |  46 +--
 .../LArByteStream/src/LArRodDecoder.cxx       | 378 +++++++++---------
 .../LArByteStream/src/LArRodEncoder.cxx       |  11 +-
 12 files changed, 293 insertions(+), 355 deletions(-)
 create mode 100644 LArCalorimeter/LArCnv/LArByteStream/LArByteStream/ATLAS_CHECK_THREAD_SAFETY

diff --git a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/ATLAS_CHECK_THREAD_SAFETY b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/ATLAS_CHECK_THREAD_SAFETY
new file mode 100644
index 00000000000..21d22932892
--- /dev/null
+++ b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/ATLAS_CHECK_THREAD_SAFETY
@@ -0,0 +1 @@
+LArCalorimeter/LArCnv/LArByteStream
diff --git a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArAccumulatedCalibDigitContByteStreamCnv.h b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArAccumulatedCalibDigitContByteStreamCnv.h
index a59f302c842..ecc3245d4b1 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArAccumulatedCalibDigitContByteStreamCnv.h
+++ b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArAccumulatedCalibDigitContByteStreamCnv.h
@@ -13,6 +13,7 @@
 #include "AthenaBaseComps/AthConstConverter.h"
 #include "ByteStreamData/RawEvent.h" 
 #include "ByteStreamCnvSvcBase/ByteStreamAddress.h"
+#include "StoreGate/ReadCondHandleKey.h"
 #include "GaudiKernel/ToolHandle.h"
 #include "GaudiKernel/ServiceHandle.h"
 
@@ -24,6 +25,7 @@ class LArAccumulatedCalibDigitContainer;
 class LArRawDataContByteStreamTool ; 
 class IROBDataProviderSvc; 
 class ByteStreamCnvSvc;
+class LArCalibLineMapping;
 
 /** This class is the converter to read/write LArAccumulatedCalibDigitContainer from/to ByteStream
    * @author W. Lampl, R. Lafaye
@@ -53,6 +55,7 @@ public:
 private: 
    ToolHandle<BYTESTREAMTOOL> m_tool;
    ServiceHandle<IROBDataProviderSvc> m_rdpSvc;
+   SG::ReadCondHandleKey<LArCalibLineMapping> m_calibLineMappingKey;
 };
 #endif
 
diff --git a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArCalibDigitContByteStreamCnv.h b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArCalibDigitContByteStreamCnv.h
index 55feb530de4..b10b6eb9c8d 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArCalibDigitContByteStreamCnv.h
+++ b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArCalibDigitContByteStreamCnv.h
@@ -13,6 +13,7 @@
 #include "AthenaBaseComps/AthConstConverter.h"
 #include "ByteStreamData/RawEvent.h" 
 #include "ByteStreamCnvSvcBase/ByteStreamAddress.h"
+#include "StoreGate/ReadCondHandleKey.h"
 #include "GaudiKernel/ToolHandle.h"
 #include "GaudiKernel/ServiceHandle.h"
 
@@ -24,6 +25,8 @@ class LArCalibDigitContainer;
 class LArRawDataContByteStreamTool ; 
 class IROBDataProviderSvc; 
 class ByteStreamCnvSvc;
+class LArCalibLineMapping;
+class LArOnOffIdMapping;
 
 /** This class is the converter to read/write LArCalibDigitContainer from/to ByteStream
    * @author W. Lampl, R. Lafaye
@@ -54,6 +57,8 @@ private:
   ServiceHandle<IROBDataProviderSvc> m_rdpSvc;
   ServiceHandle<IByteStreamEventAccess> m_byteStreamEventAccess;
   ByteStreamCnvSvc* m_byteStreamCnvSvc;
+  SG::ReadCondHandleKey<LArCalibLineMapping> m_calibLineMappingKey;
+  SG::ReadCondHandleKey<LArOnOffIdMapping> m_onOffIdMappingKey;
 };
 #endif
 
diff --git a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRawDataContByteStreamTool.h b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRawDataContByteStreamTool.h
index 4a417c9e83e..c0b207938e8 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRawDataContByteStreamTool.h
+++ b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRawDataContByteStreamTool.h
@@ -82,8 +82,11 @@ public:
    * to get all ROD fragments belonging to LAr. Methods from @c LArRodDecoder 
    * are used to deal with the individual ROD fragments. 
   */
-  template <class COLLECTION >
-  StatusCode convert(const RawEvent* re, COLLECTION* digit_cont, CaloGain::CaloGain gain) const;
+  template <class COLLECTION, typename ...ARGS >
+  StatusCode convert(const RawEvent* re,
+                     COLLECTION* digit_cont,
+                     CaloGain::CaloGain gain,
+                     ARGS&&... args) const;
 
   /** 
    * @brief Fill channels from LArDigitContainer to a FullEvent
@@ -118,7 +121,6 @@ private:
   /** Prepare ROB index before conversion */
   StatusCode prepareRobIndex (const RawEvent* event, RobIndex_t& robIndex) const;
  
-
   /** Construct a RodBlockStructure instance of the proper concrete type. */
   std::unique_ptr<LArRodBlockStructure> makeRodBlockStructure() const;
 
@@ -131,17 +133,12 @@ private:
   template <class COLLECTION >
     bool checkGainConsistency(const COLLECTION* coll) const;
  
-  CxxUtils::CachedUniquePtr<Hid2RESrcID> m_hid2re;       //!< Contains the mapping from channel to ROD (writing only)
-  LArRodDecoder *m_decoder;   //!< Pointer to RodDecoder class
   const Hid2RESrcID& getHid2RESrcID (const LArFebRodMapping& rodMapping) const;
 
-  /** Pointer to @c LArRodBlockStructure base class. 
-      Which concrete implementation is used depends on the value of 
-      @c m_DSPRunMode and @c m_RodBlockVersion. Ony for writing. 
-  */
-  LArRodBlockStructure *m_RodBlockStructure;
+  CxxUtils::CachedUniquePtr<Hid2RESrcID> m_hid2re;       //!< Contains the mapping from channel to ROD (writing only)
+  LArRodDecoder *m_decoder;   //!< Pointer to RodDecoder class
 
-  /** Indicateds which version of DSP code should be used for writing.
+  /** Indicates which version of DSP code should be used for writing.
       This is equivalent to the DetectorEventType word in the ROD block header.
       Only for writing. 
    */
diff --git a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRawDataContByteStreamTool.icc b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRawDataContByteStreamTool.icc
index 39f70ee129d..aaecc640319 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRawDataContByteStreamTool.icc
+++ b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRawDataContByteStreamTool.icc
@@ -32,8 +32,11 @@ bool LArRawDataContByteStreamTool::checkGainConsistency(const COLLECTION* coll)
 // The Following collection types are included :
 // LArAccumulatedCalibDigit, LArAccumulatedDigit, LArCalibDigit, LArDigit,
 // LArFebHeader and LArRawChannel
-template <class COLLECTION >
-StatusCode LArRawDataContByteStreamTool::convert(const RawEvent* re, COLLECTION* coll, CaloGain::CaloGain gain) const
+template <class COLLECTION, typename ...ARGS >
+StatusCode LArRawDataContByteStreamTool::convert(const RawEvent* re,
+                                                 COLLECTION* coll,
+                                                 CaloGain::CaloGain gain,
+                                                 ARGS&&... args) const
 {
         RobIndex_t robIndex;
 	if (prepareRobIndex(re, robIndex).isFailure()){
@@ -74,7 +77,8 @@ StatusCode LArRawDataContByteStreamTool::convert(const RawEvent* re, COLLECTION*
               ATH_MSG_VERBOSE ( "Calling RodDecoder for source ID " << MSG::hex 
                                 << robFrag.rod_source_id() << MSG::dec );
 	      m_decoder->fillCollection(robFrag,
-                                        p,n,*coll,gain); // ..and decode them.
+                                        p,n,*coll,gain,
+                                        std::forward<ARGS>(args)...); // ..and decode them.
             }
             catch (eformat::Issue& ex) {
               ATH_MSG_WARNING ( " exception thrown by ROBFragment, badly corrupted event. Abort decoding " );
diff --git a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRodDecoder.h b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRodDecoder.h
index 19890c6e622..a3d405f1eb1 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRodDecoder.h
+++ b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRodDecoder.h
@@ -28,7 +28,6 @@
 #include "LArRecEvent/LArCellCollection.h"
 
 
-#include "LArCabling/LArCablingLegacyService.h"
 #include "LArByteStream/LArRodBlockStructure.h"
 #include "LArRecUtils/MakeLArCellFromRaw.h"
 #include "LArRecConditions/ILArBadChannelMasker.h"
@@ -42,12 +41,17 @@
 
 #include "StoreGate/ReadHandleKey.h"
 #include "xAODEventInfo/EventInfo.h"
+#include "AthenaKernel/SlotSpecificObj.h"
+#include "CxxUtils/checker_macros.h"
 
 #include "eformat/Version.h"
 #include "eformat/Issue.h"
 #include <vector>
 #include <string>
 
+class LArCalibLineMapping;
+class LArOnOffIdMapping;
+
 /** This class provides conversion between ROD data and LArRawChannels
    * @author H. Ma
    * @version  0-0-1 , Oct 7, 2002
@@ -142,15 +146,14 @@ public:
    */ 
   virtual ~LArRodDecoder(); 
 
-  virtual StatusCode initialize();
-  virtual StatusCode finalize();
+  virtual StatusCode initialize ATLAS_NOT_THREAD_SAFE () override;
 
   // Simple method to associate the second feb
   inline void setsecfeb (HWIdentifier feb) {m_febIdHLT = feb.get_identifier32().get_compact();};
 
   // fast decoding for trigger
   inline uint32_t fillCollectionHLT (const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
-                                     const uint32_t* p, uint32_t n, LArCellCollection& coll);
+                                     const uint32_t* p, uint32_t n, LArCellCollection& coll) const;
 
   void fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
                       const uint32_t* p, uint32_t n, LArRawChannelContainer& coll, const CaloGain::CaloGain gain) const; 
@@ -164,7 +167,8 @@ public:
                       const uint32_t* p,
                       uint32_t n,
                       LArAccumulatedCalibDigitContainer& coll,
-                      const CaloGain::CaloGain gain);
+                      const CaloGain::CaloGain gain,
+                      const LArCalibLineMapping& calibLineMapping) const;
 
   //Specialized method to convert ROD Accumulated Digit words into LArAccumulatedDigit
   void fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
@@ -175,7 +179,9 @@ public:
                       const uint32_t* p,
                       uint32_t n,
                       LArCalibDigitContainer& coll,
-                      const CaloGain::CaloGain gain);
+                      const CaloGain::CaloGain gain,
+                      const LArCalibLineMapping& calibLineMapping,
+                      const LArOnOffIdMapping& onOffIdMapping) const;
 
   //Specialized method to convert ROD Data words to read the headers of the Feb
   void fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
@@ -183,11 +189,11 @@ public:
 
   //fast convert ROD Data words to read the headers of the Feb
   inline uint32_t fillCollectionHLTFeb(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
-                                       const uint32_t* p, uint32_t n, LArFebEnergyCollection& coll);
+                                       const uint32_t* p, uint32_t n, LArFebEnergyCollection& coll) const;
                                                       
   //fast convert ROD Data words to read the headers of the Feb coming from ROS
   inline uint32_t fillCollectionHLTROSFeb(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
-                                          const uint32_t* p, uint32_t n, LArFebEnergyCollection& coll);
+                                          const uint32_t* p, uint32_t n, LArFebEnergyCollection& coll) const;
                                                       
   //Send an error reported by the eformat package to a MsgStream.
   //inline void report_error (const ers::Issue& error, MsgStream& log);
@@ -203,12 +209,17 @@ public:
     
     
 private:
+  LArRodBlockStructure* prepareBlockStructure1(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag) const;
   LArRodBlockStructure* prepareBlockStructure(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
                                               const uint32_t* p, uint32_t n, const CaloGain::CaloGain RequestedGain) const;
+
+  std::unique_ptr<LArRodBlockStructure>
+  makeBlockStructure (unsigned int rodBlockType,
+                      unsigned int rodMinorVersion) const;
+
   inline void setCellEnergy(
    LArCell* element, int energy, int time,
    int quality, CaloGain::CaloGain gain) const ;
-  LArRodBlockStructure* m_larblockstruct;
 
   inline void writeFebInfo(
      LArCellCollection& m_coll, LArFebEnergy& febene) const;
@@ -216,7 +227,6 @@ private:
   //  inline void writeFebInfo(LArRawChannelContainer& m_coll, LArFebEnergy& febene);
 
   
-  ToolHandle<LArCablingLegacyService> m_larCablingSvc;
   SG::ReadHandleKey<xAOD::EventInfo>    m_evt  {this, "EvtInfo", "EventInfo", "EventInfo name"};
   float	m_LArCellEthreshold ;
   bool m_larCell; // set to True if it is used for ConvertingLArCell 
@@ -244,23 +254,11 @@ private:
   std::vector<const CaloCellCorrection*> m_LArCellCorrTools;
   
   bool m_doBadChanMasking;
-  ILArBadChannelMasker* m_badChannelMasker;
+  const ILArBadChannelMasker* m_badChannelMasker;
   
   double m_delayScale;
-  std::vector<std::vector<LArRodBlockStructure*> > m_BlStructArray;
-  LArRodBlockStructure* m_rodTranspV0 ;
-  LArRodBlockStructure* m_rodCalibV0  ;
-  LArRodBlockStructure* m_rodCalibV1  ;
-  LArRodBlockStructure* m_rodCalibV2  ;
-  LArRodBlockStructure* m_rodCalibV3  ;
-  LArRodBlockStructure* m_rodAccumV3  ;
-  LArRodBlockStructure* m_rodPhysicsV0;
-  LArRodBlockStructure* m_rodPhysicsV1;
-  LArRodBlockStructure* m_rodPhysicsV2;
-  LArRodBlockStructure* m_rodPhysicsV3;
-  LArRodBlockStructure* m_rodPhysicsV4;
-  LArRodBlockStructure* m_rodPhysicsV5;
-  LArRodBlockStructure* m_rodPhysicsV6;
+  mutable SG::SlotSpecificObj<std::vector<std::unique_ptr<LArRodBlockStructure> > >
+    m_blstructs ATLAS_THREAD_SAFE;
 
   bool m_MultiDSPMode;
   bool m_CheckSum;
@@ -305,7 +303,7 @@ inline void LArRodDecoder::report_error (const ers::Issue& error, MsgStream& log
 
 uint32_t LArRodDecoder::fillCollectionHLT(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
                                           const uint32_t* p, uint32_t n,
-                                          LArCellCollection& coll)
+                                          LArCellCollection& coll) const
 {
   LArCell *collElem=0; //Pointer to a new element to be added to the collection
   uint32_t error = 0;
@@ -326,36 +324,11 @@ uint32_t LArRodDecoder::fillCollectionHLT(const OFFLINE_FRAGMENTS_NAMESPACE::ROB
     return error;
   }
 
-  if ( m_larblockstruct == (LArRodBlockStructure*)NULL ||  m_MultiDSPMode ){
-  // If you don't know the format, find it out!
-  eformat::helper::Version ver(robFrag.rod_version());
-  const uint16_t& rodMinorVersion= ver.minor_version();
-  const uint32_t& rodBlockType=robFrag.rod_detev_type()&0xff;
-#ifndef NDEBUG
-  ATH_MSG_VERBOSE("RodBlockType=" << (int)rodBlockType << " Version: "<< rodMinorVersion);
-#endif
-
-
-  if (rodBlockType>=m_BlStructArray.size() || m_BlStructArray[rodBlockType].size()==0)
-    {msg(MSG::ERROR) << "Unknown Rod block type " << (int)rodBlockType << endmsg;
-     // Second Bit is block empty or unknown
-     error|= 0x2;
-     return error;
-    }
-  if (rodMinorVersion>=m_BlStructArray[rodBlockType].size() || m_BlStructArray[rodBlockType][rodMinorVersion]==NULL)
-    {msg(MSG::ERROR) << "No version " << rodMinorVersion  << " of Rod Block Type  " << (int)rodBlockType << "known." << endmsg;
-     // Second Bit is block empty or unknown
-     error|= 0x2;
-     return error;
-    }
-#ifndef NDEBUG
-  else
-    ATH_MSG_VERBOSE("Found version " << rodMinorVersion << " of Rod block type " << (int)rodBlockType);
-#endif
-  m_larblockstruct=m_BlStructArray[rodBlockType][rodMinorVersion];
-  } // end of if larblockstruct
-
-  LArRodBlockStructure* BlStruct=m_larblockstruct;
+  LArRodBlockStructure* BlStruct = prepareBlockStructure1 (robFrag);
+  if (!BlStruct) {
+    // Second Bit is block empty or unknown
+    error|= 0x2;
+  }
 
   BlStruct->setFragment(p,n);
   for(LArCellCollection::iterator ii=coll.begin();ii!=coll.end();++ii)
@@ -372,6 +345,7 @@ uint32_t LArRodDecoder::fillCollectionHLT(const OFFLINE_FRAGMENTS_NAMESPACE::ROB
   if(!BlStruct->setGain(calogain)){
     ATH_MSG_DEBUG("Setting the Gain Problem");
   }
+
   //LArRoI_Map::TT_ID ttId;
   int feb_number=0;
   do //Loop over FEB's
@@ -439,7 +413,7 @@ uint32_t LArRodDecoder::fillCollectionHLT(const OFFLINE_FRAGMENTS_NAMESPACE::ROB
 
 uint32_t LArRodDecoder::fillCollectionHLTFeb(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
                                              const uint32_t* p, uint32_t n,
-                                             LArFebEnergyCollection& coll)
+                                             LArFebEnergyCollection& coll) const
 {
 #ifndef NDEBUG
   ATH_MSG_VERBOSE("Prepare LArRodBlockStructure. Got a fragment of size " << n);
@@ -454,33 +428,10 @@ uint32_t LArRodDecoder::fillCollectionHLTFeb(const OFFLINE_FRAGMENTS_NAMESPACE::
      return 0;
     }
 
-  if ( m_larblockstruct == (LArRodBlockStructure*)NULL){
-  // If you don't know the format, find it out!
-  eformat::helper::Version ver(robFrag.rod_version());
-  const uint16_t& rodMinorVersion= ver.minor_version();
-  const uint32_t& rodBlockType=robFrag.rod_detev_type()&0xff;
-#ifndef NDEBUG
-  ATH_MSG_VERBOSE("RodBlockType=" << (int)rodBlockType << " Version: "<< rodMinorVersion);
-#endif
-
-
-  if (rodBlockType>=m_BlStructArray.size() || m_BlStructArray[rodBlockType].size()==0)
-    {msg(MSG::ERROR) << "Unknown Rod block type " << (int)rodBlockType << endmsg;
-     return 0;
-    }
-  if (rodMinorVersion>=m_BlStructArray[rodBlockType].size() || m_BlStructArray[rodBlockType][rodMinorVersion]==NULL)
-    {msg(MSG::ERROR) << "No version " << rodMinorVersion  << " of Rod Block Type  " << (int)rodBlockType << "known." << endmsg;
+  LArRodBlockStructure* BlStruct = prepareBlockStructure1 (robFrag);
+  if (!BlStruct) {
     return 0;
-    }
-#ifndef NDEBUG
-  else
-    ATH_MSG_VERBOSE("Found version " << rodMinorVersion << " of Rod block type " << (int)rodBlockType);
-#endif
-  m_larblockstruct=m_BlStructArray[rodBlockType][rodMinorVersion];
-  } // end of if larblockstruct
-
-  LArRodBlockStructure* BlStruct=m_larblockstruct;
-
+  }
   BlStruct->setFragment(p,n);
 
   uint32_t NWtot=0;
@@ -538,7 +489,7 @@ uint32_t LArRodDecoder::fillCollectionHLTFeb(const OFFLINE_FRAGMENTS_NAMESPACE::
 
 uint32_t LArRodDecoder::fillCollectionHLTROSFeb(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
                                                 const uint32_t* p, uint32_t n,
-                                                LArFebEnergyCollection& coll)
+                                                LArFebEnergyCollection& coll) const
 {
 #ifndef NDEBUG
   ATH_MSG_VERBOSE("Prepare LArRodBlockStructure. Got a fragment of size " << n);
@@ -547,32 +498,11 @@ uint32_t LArRodDecoder::fillCollectionHLTROSFeb(const OFFLINE_FRAGMENTS_NAMESPAC
     {msg(MSG::WARNING) << "Got empty Rod Fragment!" << endmsg;
      return 0;
     }
-  if ( m_larblockstruct == (LArRodBlockStructure*)NULL){
-  // If you don't know the format, find it out!
-  eformat::helper::Version ver(robFrag.rod_version());
-  const uint16_t& rodMinorVersion= ver.minor_version();
-  const uint32_t& rodBlockType=robFrag.rod_detev_type()&0xff;
-#ifndef NDEBUG
-  ATH_MSG_VERBOSE("RodBlockType=" << (int)rodBlockType << " Version: "<< rodMinorVersion);
-#endif
-
 
-  if (rodBlockType>=m_BlStructArray.size() || m_BlStructArray[rodBlockType].size()==0)
-    {msg(MSG::ERROR) << "Unknown Rod block type " << (int)rodBlockType << endmsg;
-     return 0;
-    }
-  if (rodMinorVersion>=m_BlStructArray[rodBlockType].size() || m_BlStructArray[rodBlockType][rodMinorVersion]==NULL)
-    {msg(MSG::ERROR) << "No version " << rodMinorVersion  << " of Rod Block Type  " << (int)rodBlockType << "known." << endmsg;
+  LArRodBlockStructure* BlStruct = prepareBlockStructure1 (robFrag);
+  if (!BlStruct) {
     return 0;
-    }
-#ifndef NDEBUG
-  else
-    ATH_MSG_VERBOSE("Found version " << rodMinorVersion << " of Rod block type " << (int)rodBlockType);
-#endif
-  m_larblockstruct=m_BlStructArray[rodBlockType][rodMinorVersion];
-  } // end of if larblockstruct
-
-  LArRodBlockStructure* BlStruct=m_larblockstruct;
+  }
 
   LArFebEnergy* febenergy;
   int nfebs = BlStruct->setFragmentVirtualROB(p,n);
diff --git a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRodEncoder.h b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRodEncoder.h
index a7602151477..5c9fafa9b8a 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRodEncoder.h
+++ b/LArCalorimeter/LArCnv/LArByteStream/LArByteStream/LArRodEncoder.h
@@ -112,7 +112,7 @@ private:
   //std::vector<FebData> m_vFEB;
   std::map<uint32_t,FebData_t> m_mFEB;
 
-  const LArOnlineID&    m_onlineHelper; 
+  const LArOnlineID&         m_onlineHelper; 
   const CaloDetDescrManager& m_CaloDetDescrManager;
   const LArOnOffIdMapping&   m_onOffIdMapping;
   LArRodBlockStructure* m_BlStruct;
diff --git a/LArCalorimeter/LArCnv/LArByteStream/src/LArAccumulatedCalibDigitContByteStreamCnv.cxx b/LArCalorimeter/LArCnv/LArByteStream/src/LArAccumulatedCalibDigitContByteStreamCnv.cxx
index f7e3a8cac50..86f81f46804 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/src/LArAccumulatedCalibDigitContByteStreamCnv.cxx
+++ b/LArCalorimeter/LArCnv/LArByteStream/src/LArAccumulatedCalibDigitContByteStreamCnv.cxx
@@ -19,8 +19,10 @@
 #include "GaudiKernel/IRegistry.h"
 
 #include "LArRawEvent/LArAccumulatedCalibDigitContainer.h"
+#include "LArRecConditions/LArCalibLineMapping.h"
 
 #include "StoreGate/StoreGateSvc.h"
+#include "StoreGate/ReadCondHandle.h"
 #include "AthenaKernel/CLASS_DEF.h"
 
 // Tool 
@@ -34,7 +36,8 @@
 LArAccumulatedCalibDigitContByteStreamCnv::LArAccumulatedCalibDigitContByteStreamCnv(ISvcLocator* svcloc) :
   AthConstConverter(storageType(), classID(),svcloc,"LArAccumulatedCalibDigitContByteStreamCnv"),
   m_tool("LArRawDataContByteStreamTool"),
-  m_rdpSvc("ROBDataProviderSvc", name())
+  m_rdpSvc("ROBDataProviderSvc", name()),
+  m_calibLineMappingKey ("LArCalibLineMap")
 {}
 
 const CLID& LArAccumulatedCalibDigitContByteStreamCnv::classID(){
@@ -55,6 +58,7 @@ LArAccumulatedCalibDigitContByteStreamCnv::initialize()
   }
 
   ATH_CHECK( m_tool.retrieve() );
+  ATH_CHECK( m_calibLineMappingKey.initialize() );
 
   return StatusCode::SUCCESS;
 }
@@ -90,10 +94,13 @@ LArAccumulatedCalibDigitContByteStreamCnv::createObjConst(IOpaqueAddress* pAddr,
   else if (key=="LOW")
     gain=CaloGain::LARLOWGAIN;
 
+  SG::ReadCondHandle<LArCalibLineMapping> calibLineMapping (m_calibLineMappingKey);
+
   // Convert the RawEvent to  LArAccumulatedCalibDigitContainer
   ATH_MSG_DEBUG(  "Converting LArAccumulatedCalibDigits (from ByteStream). key=" << key << " ,gain=" << gain );
   LArAccumulatedCalibDigitContainer *DigitContainer=new LArAccumulatedCalibDigitContainer;
-  StatusCode sc=m_tool->convert(re,DigitContainer,gain);
+  StatusCode sc=m_tool->convert(re,DigitContainer,gain,
+                                **calibLineMapping);
   if (sc!=StatusCode::SUCCESS) {
     ATH_MSG_WARNING(  "Conversion tool returned an error. LArAccumulatedCalibDigitContainer might be empty." );
   }
diff --git a/LArCalorimeter/LArCnv/LArByteStream/src/LArCalibDigitContByteStreamCnv.cxx b/LArCalorimeter/LArCnv/LArByteStream/src/LArCalibDigitContByteStreamCnv.cxx
index 5c3850234e6..c08bc9bfe13 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/src/LArCalibDigitContByteStreamCnv.cxx
+++ b/LArCalorimeter/LArCnv/LArByteStream/src/LArCalibDigitContByteStreamCnv.cxx
@@ -12,7 +12,10 @@
 #include "ByteStreamData/RawEvent.h" 
 
 #include "LArRawEvent/LArCalibDigitContainer.h"
+#include "LArRecConditions/LArCalibLineMapping.h"
+#include "LArCabling/LArOnOffIdMapping.h"
 
+#include "StoreGate/ReadCondHandle.h"
 #include "AthenaKernel/StorableConversions.h"
 
 //STL-Stuff
@@ -25,7 +28,9 @@ LArCalibDigitContByteStreamCnv::LArCalibDigitContByteStreamCnv(ISvcLocator* svcl
   m_tool("LArRawDataContByteStreamTool"),
   m_rdpSvc("ROBDataProviderSvc", name()),
   m_byteStreamEventAccess("ByteStreamCnvSvc", name()),
-  m_byteStreamCnvSvc(nullptr)
+  m_byteStreamCnvSvc(nullptr),
+  m_calibLineMappingKey ("LArCalibLineMap"),
+  m_onOffIdMappingKey ("LArOnOffIdMap")
 {}
 
 LArCalibDigitContByteStreamCnv::~LArCalibDigitContByteStreamCnv() {
@@ -49,6 +54,8 @@ LArCalibDigitContByteStreamCnv::initialize()
   m_byteStreamCnvSvc = dynamic_cast<ByteStreamCnvSvc*>(&*m_byteStreamEventAccess);
 
   ATH_CHECK( m_tool.retrieve() );
+  ATH_CHECK( m_calibLineMappingKey.initialize() );
+  ATH_CHECK( m_onOffIdMappingKey.initialize() );
   
   return StatusCode::SUCCESS;
 }
@@ -87,8 +94,13 @@ LArCalibDigitContByteStreamCnv::createObjConst(IOpaqueAddress* pAddr, DataObject
   // Convert the RawEvent to  LArCalibDigitContainer
   ATH_MSG_DEBUG( "Converting LArCalibDigits (from ByteStream). key=" << key << " ,gain=" << gain );
  
+  SG::ReadCondHandle<LArCalibLineMapping> calibLineMapping (m_calibLineMappingKey);
+  SG::ReadCondHandle<LArOnOffIdMapping> onOffIdMapping (m_onOffIdMappingKey);
+
   LArCalibDigitContainer *CalibDigitContainer=new LArCalibDigitContainer;
-  StatusCode sc=m_tool->convert(re,CalibDigitContainer,gain);
+  StatusCode sc=m_tool->convert(re,CalibDigitContainer,gain,
+                                **calibLineMapping,
+                                **onOffIdMapping);
   if (sc!=StatusCode::SUCCESS) {
     ATH_MSG_WARNING( "Conversion tool returned an error. LArCalibDigitContainer might be empty." );
   }
diff --git a/LArCalorimeter/LArCnv/LArByteStream/src/LArRawDataContByteStreamTool.cxx b/LArCalorimeter/LArCnv/LArByteStream/src/LArRawDataContByteStreamTool.cxx
index 024fbb38ec2..1efe3c421e5 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/src/LArRawDataContByteStreamTool.cxx
+++ b/LArCalorimeter/LArCnv/LArByteStream/src/LArRawDataContByteStreamTool.cxx
@@ -23,6 +23,7 @@
 #include "LArByteStream/LArRodBlockPhysicsV5.h"
 #include "LArByteStream/LArRodBlockPhysicsV6.h"
 #include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/ThreadLocalContext.h"
 
 #include "StoreGate/ReadCondHandle.h"
 
@@ -50,7 +51,6 @@ LArRawDataContByteStreamTool::LArRawDataContByteStreamTool
   declareProperty("SubDetectorId",m_subDetId=0);
   declareProperty("IncludeDigits",m_includeDigits=false);
   declareProperty("DigitsContainer",m_DigitContName="LArDigitContainer_MC_Thinned");
-  m_RodBlockStructure=NULL;
 }
 
 LArRawDataContByteStreamTool::~LArRawDataContByteStreamTool() {
@@ -66,42 +66,11 @@ LArRawDataContByteStreamTool::initialize()
   ATH_CHECK( toolSvc()->retrieveTool("LArRodDecoder",m_decoder) );
 
   if (m_initializeForWriting) {
-   //Set LArRodBlockStructure according to jobOpts.
-   switch(m_DSPRunMode)
-     {case 0:  //Obsolete mode 
-	m_RodBlockStructure=NULL;
-	ATH_MSG_ERROR ( "LArRodBlockStructure type 0 is obsolete and can't be used any more." );
-	return StatusCode::FAILURE;
-      break;
-     case 2:  //Transparent mode, DSP just copies FEB-data                                            
-       m_RodBlockStructure=new LArRodBlockTransparentV0<LArRodBlockHeaderTransparentV0>;
-       ATH_MSG_DEBUG ( "Set Rod Block Type to LArRodBlockTransparent (#2)" );
-      break;
-     case 7: //Calibration mode
-       m_RodBlockStructure=new LArRodBlockCalibrationV0<LArRodBlockHeaderCalibrationV0>;
-       ATH_MSG_DEBUG ( "Set Rod Block Type to LArRodBlockCalibration (#7)" );
-       break;
-     case 4: //Physics assembly mode
-       if ( m_RodBlockVersion == 10 ){
-         m_RodBlockStructure=new LArRodBlockPhysicsV5;
-         ATH_MSG_DEBUG ( "Set Rod Block Type to LArRodBlockPhysics (#5)" );
-       } else if ( m_RodBlockVersion == 12 ){
-         m_RodBlockStructure=new LArRodBlockPhysicsV6;
-         ATH_MSG_DEBUG ( "Set Rod Block Type to LArRodBlockPhysics (#6)" );
-       } else {
-         m_RodBlockStructure=new LArRodBlockPhysicsV0;
-         ATH_MSG_DEBUG ( "Set Rod Block Type to LArRodBlockPhysics (#4)" );
-       }
-       break;
-     case 5: //Physics assembly mode
-       m_RodBlockStructure=new LArRodBlockPhysicsV3;
-       ATH_MSG_DEBUG ( "Set Rod Block Type to LArRodBlockPhysics (#5)" );
-       break;
-     default:
-       m_RodBlockStructure=new LArRodBlockPhysicsV0;
-       ATH_MSG_WARNING ( "DSP runmode " << m_DSPRunMode << " is unknown. Using physics assembly mode (#4) by default" );
-       break;
-     }
+   if (m_DSPRunMode == 0) {
+     // Obsolete mode 
+     ATH_MSG_ERROR ( "LArRodBlockStructure type 0 is obsolete and can't be used any more." );
+     return StatusCode::FAILURE;
+   }
 
    ATH_CHECK( detStore()->retrieve (m_onlineHelper, "LArOnlineID") );
 
@@ -122,7 +91,6 @@ LArRawDataContByteStreamTool::initialize()
 StatusCode
 LArRawDataContByteStreamTool::finalize()
 {
-  delete m_RodBlockStructure;
   ATH_CHECK( AthAlgTool::finalize() );
   return StatusCode::SUCCESS;
 }
@@ -158,7 +126,7 @@ LArRawDataContByteStreamTool::WriteLArDigits(const LArDigitContainer* digitCont,
  LArDigitContainer::const_iterator it_b=digitCont->begin();
  LArDigitContainer::const_iterator it_e=digitCont->end();
  if (it_b==it_e) {
-   ATH_MSG_WARNING ( "Attempt to persistify a empty LArDigitContainer to ByteStream" );
+   ATH_MSG_WARNING ( "Attempt to persistify an empty LArDigitContainer to ByteStream" );
    return StatusCode::SUCCESS;
  }
 
diff --git a/LArCalorimeter/LArCnv/LArByteStream/src/LArRodDecoder.cxx b/LArCalorimeter/LArCnv/LArByteStream/src/LArRodDecoder.cxx
index 762f24de746..2fe484b4983 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/src/LArRodDecoder.cxx
+++ b/LArCalorimeter/LArCnv/LArByteStream/src/LArRodDecoder.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
 */
 
 // Implementation of LArRodDecoder class 
@@ -31,33 +31,20 @@
 #include <fstream>
 
 #include "LArRawConditions/LArCalibParams.h"
+#include "LArRecConditions/LArCalibLineMapping.h"
+#include "LArCabling/LArOnOffIdMapping.h"
 
 static const InterfaceID IID_ILArRodDecoder
             ("LArRodDecoder", 1, 0);
 
 LArRodDecoder::LArRodDecoder ( const std::string& type, const std::string& name,const IInterface* parent )
   : AthAlgTool(type,name,parent),
-    m_larblockstruct(0),
-    m_larCablingSvc("LArCablingLegacyService"),
     m_LArCellEthreshold(-100.),
     m_larCell(false), 
     m_readtdc(false),
     m_onlineHelper(0),
     m_doBadChanMasking(false),
-    m_badChannelMasker(0),
-    m_rodTranspV0(0),
-    m_rodCalibV0(0),
-    m_rodCalibV1(0),
-    m_rodCalibV2(0),
-    m_rodCalibV3(0),
-    m_rodAccumV3(0),
-    m_rodPhysicsV0(0),
-    m_rodPhysicsV1(0),
-    m_rodPhysicsV2(0),
-    m_rodPhysicsV3(0),
-    m_rodPhysicsV4(0),
-    m_rodPhysicsV5(0),
-    m_rodPhysicsV6(0)
+    m_badChannelMasker(0)
  {
   declareInterface< LArRodDecoder  >( this );
   declareProperty("IgnoreCheckFEBs",m_IgnoreCheckFEBs);
@@ -89,7 +76,7 @@ const InterfaceID& LArRodDecoder::interfaceID( )
 { return IID_ILArRodDecoder;  }
 
 StatusCode
-LArRodDecoder::initialize()
+LArRodDecoder::initialize ATLAS_NOT_THREAD_SAFE ()
 {
  // Before anything, access message service
   m_StatusNMask = !m_StatusMask;
@@ -108,12 +95,6 @@ LArRodDecoder::initialize()
     return sc;
    }
   
-  sc=m_larCablingSvc.retrieve();
-  if (sc.isFailure()) {
-    msg(MSG::ERROR) << "Unable to retrieve LArCablingLegacyService" << endmsg;
-    return StatusCode::FAILURE;
-  }
-  
  sc = toolSvc->retrieveTool("LArBadChannelMasker/LArRodDecoder_Masker", m_badChannelMasker);
  if(sc.isFailure()) {
    msg(MSG::ERROR) << "Failed to retrieve the LArBadChannelMasker named 'LArRodDecoder_Masker'." << endmsg;
@@ -154,107 +135,6 @@ LArRodDecoder::initialize()
      m_makeCell.initialize( roiMap, &m_LArCellCorrTools ); 
    }	
 
-   //Fill Map for RodBlockStructure/Version number
-   m_BlStructArray.resize(12); //Reserve space for 11 block types some of the do not (yet) exist.
-
-   m_rodTranspV0  = (LArRodBlockStructure *) new LArRodBlockTransparentV0<LArRodBlockHeaderTransparentV0>;
-   m_rodCalibV0   = (LArRodBlockStructure *) new LArRodBlockCalibrationV0<LArRodBlockHeaderCalibrationV0>;
-   m_rodCalibV1   = (LArRodBlockStructure *) new LArRodBlockCalibrationV1;
-   m_rodCalibV2   = (LArRodBlockStructure *) new LArRodBlockCalibrationV2;
-   m_rodCalibV3   = (LArRodBlockStructure *) new LArRodBlockCalibrationV3;
-   m_rodAccumV3   = (LArRodBlockStructure *) new LArRodBlockAccumulatedV3;
-   m_rodPhysicsV0 = (LArRodBlockStructure *) new LArRodBlockPhysicsV0;
-   m_rodPhysicsV1 = (LArRodBlockStructure *) new LArRodBlockPhysicsV1;
-   m_rodPhysicsV2 = (LArRodBlockStructure *) new LArRodBlockPhysicsV2;
-   m_rodPhysicsV3 = (LArRodBlockStructure *) new LArRodBlockPhysicsV3;
-   m_rodPhysicsV4 = (LArRodBlockStructure *) new LArRodBlockPhysicsV4;
-   m_rodPhysicsV5 = (LArRodBlockStructure *) new LArRodBlockPhysicsV5;
-   m_rodPhysicsV6 = (LArRodBlockStructure *) new LArRodBlockPhysicsV6;
-   // Only implemented for physics V5
-   if (m_requiredPhysicsNSamples > 0) {
-	((LArRodBlockPhysicsV5*)m_rodPhysicsV5)->setRequiredNSamples(m_requiredPhysicsNSamples);
-	((LArRodBlockPhysicsV6*)m_rodPhysicsV6)->setRequiredNSamples(m_requiredPhysicsNSamples);
-   }
-   //m_BlStructArray[0].push_back();                               // obsolete old type
-   //m_BlStructArray[1] does not exists
-
-   // RodBlockType 2 = Transparent mode only
-   m_BlStructArray[2].push_back(m_rodTranspV0);  //0  Transparent mode v0 05.01.2004
-   m_BlStructArray[2].push_back(m_rodTranspV0);  //1  Transparent mode v0
-   m_BlStructArray[2].push_back(m_rodTranspV0);  //2  Transparent mode v0
-   m_BlStructArray[2].push_back(m_rodTranspV0);  //3  Transparent mode v0
-   m_BlStructArray[2].push_back(m_rodTranspV0);  //4  Transparent mode v0
-   m_BlStructArray[2].push_back(m_rodCalibV1);   //5  Calibration (Transparent mode) v1 17.01.2006
-   m_BlStructArray[2].push_back(m_rodCalibV3);   //6  Calibration (Transparent mode) v3 31.05.2006
-   m_BlStructArray[2].push_back(m_rodCalibV3);   //7  Calibration (Transparent mode) v3
-   m_BlStructArray[2].push_back(m_rodCalibV3);   //8  Calibration (Transparent mode) v3
-   m_BlStructArray[2].push_back(m_rodCalibV3);   //9  Calibration (Transparent mode) v3
-   m_BlStructArray[2].push_back(m_rodCalibV3);   //10 Calibration (Transparent mode) v3
-   m_BlStructArray[2].push_back(m_rodCalibV3);   //11 Calibration (Transparent mode) v3
-   m_BlStructArray[2].push_back(m_rodCalibV3);   //12 Calibration (Transparent mode) v3
-
-   // RodBlockType 3 = Test mode
-   m_BlStructArray[3].push_back(m_rodTranspV0);  //Test mode (same output as above)
-
-   // RodBlockType 4 = Physics mode
-   m_BlStructArray[4].push_back(m_rodPhysicsV0); //0  Physics mode v0 05.01.2004 first draft
-   m_BlStructArray[4].push_back(m_rodPhysicsV1); //1  Physics mode v1 19.08.2004 only small differences
-   m_BlStructArray[4].push_back(m_rodPhysicsV2); //2  Physics mode v2 05.10.2004 adapted to real DSP data
-   m_BlStructArray[4].push_back(m_rodPhysicsV2); //3  Physics mode v2 
-   m_BlStructArray[4].push_back(m_rodPhysicsV2); //4  Physics mode v2 
-   m_BlStructArray[4].push_back(m_rodPhysicsV2); //5  Physics mode v2 
-   m_BlStructArray[4].push_back(m_rodPhysicsV2); //6  Physics mode v2 
-   m_BlStructArray[4].push_back(m_rodPhysicsV2); //7  Physics mode v2 
-   m_BlStructArray[4].push_back(m_rodPhysicsV2); //8  Physics mode v2 
-   m_BlStructArray[4].push_back(m_rodPhysicsV4); //9  Physics mode v4 10.07.2007 for commissioning
-   m_BlStructArray[4].push_back(m_rodPhysicsV5); //10 Physics mode v5 16.06.2008 for LHC 
-   m_BlStructArray[4].push_back(m_rodPhysicsV5); //11 Physics mode v5 16.06.2008 for LHC 
-   m_BlStructArray[4].push_back(m_rodPhysicsV6); //12 Physics mode v5 09.03.2011 for LHC 
-
-   // RodBlockType 5 = Physics simulation mode
-   m_BlStructArray[5].push_back(m_rodPhysicsV3); //0  Physics mode v3 11.04.2005 for simulation
-
-   // RodBlockType 6 = Physics test mode
-   m_BlStructArray[6].push_back(m_rodPhysicsV0); //1  Physics mode v0 05.01.2004 first draft
-   m_BlStructArray[6].push_back(m_rodPhysicsV2); //2  Physics mode v2 05.10.2004 adapted to real DSP data
-   m_BlStructArray[6].push_back(m_rodPhysicsV2); //3  Physics mode v2
-
-   // RodBlockType 7 = Calibration mode
-   m_BlStructArray[7].push_back(m_rodCalibV0);  //0  Calibration mode v0  05.01.2004
-   m_BlStructArray[7].push_back(m_rodCalibV1);  //1  Calibration mode v1  17.01.2006
-   m_BlStructArray[7].push_back(m_rodCalibV1);  //2  Calibration mode v1 
-   m_BlStructArray[7].push_back(m_rodCalibV1);  //3  Calibration mode v1
-   m_BlStructArray[7].push_back(m_rodCalibV1);  //4  Calibration mode v1
-   m_BlStructArray[7].push_back(m_rodCalibV2);  //5  Calibration mode v2  26.04.2006
-   m_BlStructArray[7].push_back(m_rodCalibV3);  //6  Calibration mode v3  31.05.2006
-   m_BlStructArray[7].push_back(m_rodCalibV3);  //7  Calibration mode v3
-   m_BlStructArray[7].push_back(m_rodCalibV3);  //8  Calibration mode v3
-   m_BlStructArray[7].push_back(m_rodCalibV3);  //9  Calibration mode v3
-   m_BlStructArray[7].push_back(m_rodCalibV3);  //10 Calibration mode v3
-   m_BlStructArray[7].push_back(m_rodCalibV3);  //11 Calibration mode v3
-   m_BlStructArray[7].push_back(m_rodCalibV3);  //12 Calibration mode v3
-
-   //m_BlStructArray[8] does not exists
-   //m_BlStructArray[9] does not exists
-
-   // RodBlockType 10 = Accumulated mode (used for pre-processed pedestal runs)
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //0  Accumulated mode v3 10.06.2008
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //1  Accumulated mode v3
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //2  Accumulated mode v3
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //3  Accumulated mode v3
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //4  Accumulated mode v3
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //5  Accumulated mode v3
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //6  Accumulated mode v3
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //7  Accumulated mode v3
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //8  Accumulated mode v3
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //9  Accumulated mode v3 
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //10 Accumulated mode v3 
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //11 Accumulated mode v3 
-   m_BlStructArray[10].push_back(m_rodAccumV3);  //12 Accumulated mode v3 
-
-   m_larblockstruct = (LArRodBlockStructure*)NULL;
-
-
    //Build list of preselected Feedthroughs
    if (m_vBEPreselection.size() &&  m_vPosNegPreselection.size() && m_vFTPreselection.size()) {
      ATH_MSG_INFO("Building list of selected feedthroughs");
@@ -289,27 +169,6 @@ LArRodDecoder::initialize()
 
 
 
-StatusCode LArRodDecoder::finalize()
-{ // Clean up matrix of RodBlockStructures
- delete m_rodTranspV0 ;
- delete m_rodCalibV0  ;
- delete m_rodCalibV1  ;
- delete m_rodCalibV2  ;
- delete m_rodCalibV3  ;
- delete m_rodAccumV3  ;
- delete m_rodPhysicsV0;
- delete m_rodPhysicsV1;
- delete m_rodPhysicsV2;
- delete m_rodPhysicsV3;
- delete m_rodPhysicsV4;
- delete m_rodPhysicsV5;
- delete m_rodPhysicsV6;
-
- ATH_MSG_VERBOSE("Cleanup of LArRodBlockStructures finished");
- return StatusCode::SUCCESS;
-}
-
-
 void LArRodDecoder::fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
                                    const uint32_t* p, uint32_t n, LArDigitContainer& coll, CaloGain::CaloGain RequestedGain) const
 { // Digit pointer
@@ -517,7 +376,9 @@ void LArRodDecoder::fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragmen
                                    const uint32_t* p,
                                    uint32_t n,
                                    LArCalibDigitContainer& coll,
-                                   CaloGain::CaloGain RequestedGain)
+                                   CaloGain::CaloGain RequestedGain,
+                                   const LArCalibLineMapping& calibLineMapping,
+                                   const LArOnOffIdMapping& onOffIdMapping) const
 { // CalibDigit pointer
   LArCalibDigit * dg=0 ;
   uint32_t gain;
@@ -622,7 +483,7 @@ void LArRodDecoder::fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragmen
   else {//Not a calibration data block, try to get from database
     ATH_MSG_VERBOSE("Not LArCalibDigit data block found. Building it using DB values");
     //1st step, get Calib board config object
-    const DataHandle<LArCalibParams> calibParams;
+    const LArCalibParams* calibParams = nullptr;
     StatusCode sc=detStore()->retrieve(calibParams);
     if (sc.isFailure())
       {msg(MSG::ERROR) << "Cannot load LArCalibParams from DetStore!" << endmsg;
@@ -668,10 +529,10 @@ void LArRodDecoder::fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragmen
       do { //Search for the first connected channel of this FEB (probably the first one...)
 	fcNb++; 
 	cId = m_onlineHelper->channel_Id(fId,fcNb);
-	calibChannelIDs=&m_larCablingSvc->calibSlotLine(cId);
-	//std::cout << m_larCablingSvc->isOnlineConnected(cId) << " "  << calibChannelIDs->size() << " " << fcNb << std::endl ;
+	calibChannelIDs=&calibLineMapping.calibSlotLine(cId);
+	//std::cout << onOffIdMapping.isOnlineConnected(cId) << " "  << calibChannelIDs->size() << " " << fcNb << std::endl ;
       }
-      while ( (!m_larCablingSvc->isOnlineConnected(cId) || calibChannelIDs->size()==0) && fcNb<128); // This is the right  conditions to exit the loop!
+      while ( (!onOffIdMapping.isOnlineConnected(cId) || calibChannelIDs->size()==0) && fcNb<128); // This is the right  conditions to exit the loop!
       
       if ( calibChannelIDs->size()==0 ) {
 	msg(MSG::ERROR) << "Cannot get calibration Channel ID for FEB " << std::hex << fId32 << std::dec << endmsg;
@@ -698,10 +559,10 @@ void LArRodDecoder::fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragmen
 	  if (fcNb>=NthisFebChannel) continue;
 	  if (samples.size()==0) continue; // Ignore missing cells
 	  cId = m_onlineHelper->channel_Id(fId,fcNb);
-	  calibChannelIDs=&m_larCablingSvc->calibSlotLine(cId);
+	  calibChannelIDs=&calibLineMapping.calibSlotLine(cId);
 	  //if (calibChannelIDs->size()==0) 
 	  //continue; //Disconnected channel
-	  //For the time beeing, I assume we are in H8 and have only one calib channel per FEB channel
+	  //For the time being, I assume we are in H8 and have only one calib channel per FEB channel
 
 	  if (calibChannelIDs->size()!=0) {
 	    csl_it=calibChannelIDs->begin();
@@ -728,7 +589,8 @@ void LArRodDecoder::fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragmen
                                    const uint32_t* p,
                                    uint32_t n,
                                    LArAccumulatedCalibDigitContainer& coll,
-                                   CaloGain::CaloGain RequestedGain)
+                                   CaloGain::CaloGain RequestedGain,
+                                   const LArCalibLineMapping& calibLineMapping) const
 { // Accumulated Digit pointer
   LArAccumulatedCalibDigit * dg=0 ;
   CaloGain::CaloGain calogain;
@@ -828,7 +690,7 @@ void LArRodDecoder::fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragmen
 	  if(!NStep) NStep=1; // To be able to decode v6 code
 	  StepIndex=BlStruct->getStepIndex();
 	  // 08.08.2005 IWS get calib line
-	  const std::vector<HWIdentifier>& calibChannelIDs=m_larCablingSvc->calibSlotLine(cId);
+	  const std::vector<HWIdentifier>& calibChannelIDs = calibLineMapping.calibSlotLine(cId);
 	  if (calibChannelIDs.size()==0) { 
 	        samplesSum.clear();
 	        samples2Sum.clear();
@@ -1044,52 +906,71 @@ void LArRodDecoder::fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragmen
 
 
 LArRodBlockStructure*
-LArRodDecoder::prepareBlockStructure(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
-                                     const uint32_t* p, uint32_t n, const CaloGain::CaloGain RequestedGain) const
+LArRodDecoder::prepareBlockStructure1 (const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag) const
 { 
-#ifndef NDEBUG
-  ATH_MSG_DEBUG("Prepare LArRodBlockStructure. Got a fragement of size " << n);
-#endif
-  //if (n<2) //Avoid segmentation fault
-  //  {msg(MSG::WARNING) << "Got empty Rod Fragment!" << endmsg;
-  //   return NULL;
-  //  }  
-  //uint32_t blocksize=p[0]; //First word contains block size
-  //if (blocksize>n)
-  //  {(*m_log) << MSG::ERROR << "Got truncated ROD Fragment!" << endmsg;
-  //   return NULL;
-  //  }
   //Get version and blocktype form header
   eformat::helper::Version ver(robFrag.rod_version());
   const uint16_t rodMinorVersion=ver.minor_version();
   const uint32_t rodBlockType=robFrag.rod_detev_type()&0xff;
-  if (rodBlockType>=m_BlStructArray.size() || m_BlStructArray[rodBlockType].size()==0)
-    {msg(MSG::ERROR) << "Unknown Rod block type " <<  rodBlockType << endmsg;
-     return NULL;
-    }
-  if (rodMinorVersion>=m_BlStructArray[rodBlockType].size() || m_BlStructArray[rodBlockType][rodMinorVersion]==NULL)
-    {msg(MSG::ERROR) << "No version " << rodMinorVersion <<  " of Rod Block Type  " <<  rodBlockType << "known." << endmsg;
-    return NULL;
-    }
+
+  const unsigned MAXMINOR = 12;
+  const unsigned MAXTYPE = 10;
+
+  if (rodMinorVersion > MAXMINOR || rodBlockType > MAXTYPE) {
+    msg(MSG::ERROR) << "Bad Rod block type " <<  rodBlockType
+                    << " / " << rodMinorVersion << endmsg;
+    return nullptr;
+  }
+  std::vector<std::unique_ptr<LArRodBlockStructure> >& blstructs =
+    *m_blstructs.get();
+  unsigned int index = rodBlockType * (MAXMINOR+1) + rodMinorVersion;
+  if (blstructs.empty()) {
+    blstructs.resize ((MAXMINOR+1)*(MAXTYPE+1));
+  }
+  if (!blstructs[index]) {
+    blstructs[index] = makeBlockStructure (rodBlockType, rodMinorVersion);
+  }
+  if (!blstructs[index]) {
+    msg(MSG::ERROR) << "Bad Rod block type " <<  rodBlockType
+                    << " / " << rodMinorVersion << endmsg;
+    return nullptr;
+  }
+
+#ifndef NDEBUG
+  ATH_MSG_DEBUG("Found version " << rodMinorVersion << " of Rod block type " << rodBlockType);
+#endif
+
+  return blstructs[index].get();
+}
+
+
+LArRodBlockStructure*
+LArRodDecoder::prepareBlockStructure(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment& robFrag,
+                                     const uint32_t* p, uint32_t n, const CaloGain::CaloGain RequestedGain) const
+{ 
 #ifndef NDEBUG
-  else
-    ATH_MSG_DEBUG("Found version " << rodMinorVersion << " of Rod block type " << rodBlockType);
+  ATH_MSG_DEBUG("Prepare LArRodBlockStructure. Got a fragement of size " << n);
 #endif
 
-  LArRodBlockStructure* BlStruct=m_BlStructArray[rodBlockType][rodMinorVersion];
+  LArRodBlockStructure* BlStruct = prepareBlockStructure1 (robFrag);
+  if (!BlStruct) {
+    return nullptr;
+  }
+
   //BlStruct->dumpFragment(v); // For testing purpose
   if (!BlStruct->setFragment(p,n)) {
-    static int nMess = 1, maxMess = 100;
-    if (nMess < maxMess) {
+    constexpr int maxMess = 100;
+    static std::atomic<int> nMess = 1;
+    int thismess = nMess++;
+    if (thismess < maxMess) {
       msg(MSG::ERROR) << "Could not set fragment (wrong number of samples in data ?) - container will not be filled" << endmsg;
-      nMess++;
-      if (nMess == maxMess)
+      if (thismess == maxMess)
         msg(MSG::ERROR) << "This message will not be repeated" << endmsg;
     }
     return NULL;
   }
 #ifndef NDEBUG
-  ATH_MSG_VERBOSE("Set Fragment at address "<<  (uint32_t *) &(p[0]) << " " << p[5]);
+  ATH_MSG_VERBOSE("Set Fragment at address "<<  &(p[0]) << " " << p[5]);
 #endif
 
   BlStruct->setGain(RequestedGain); //Will be ignored if BlockStructure does not support fixed gains.    
@@ -1100,3 +981,130 @@ LArRodDecoder::prepareBlockStructure(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragm
   return BlStruct;
 }
 
+
+std::unique_ptr<LArRodBlockStructure>
+LArRodDecoder::makeBlockStructure (unsigned int rodBlockType,
+                                   unsigned int rodMinorVersion) const
+{
+  switch (rodBlockType) {
+  case 2:
+    // RodBlockType 2 = Transparent mode only
+    switch (rodMinorVersion) {
+    case 0: // Transparent mode v0 05.01.2004
+    case 1: // Transparent mode v0
+    case 2: // Transparent mode v0
+    case 3: // Transparent mode v0
+    case 4: // Transparent mode v0
+      return std::make_unique<LArRodBlockTransparentV0<LArRodBlockHeaderTransparentV0> >();
+    case 5: // Calibration (Transparent mode) v1 17.01.2006
+      return std::make_unique<LArRodBlockCalibrationV1>();
+    case 6: // Calibration (Transparent mode) v3 31.05.2006
+    case 7: // Calibration (Transparent mode) v3
+    case 8: // Calibration (Transparent mode) v3
+    case 9: // Calibration (Transparent mode) v3
+    case 10:// Calibration (Transparent mode) v3
+    case 11:// Calibration (Transparent mode) v3
+    case 12:// Calibration (Transparent mode) v3
+      return std::make_unique<LArRodBlockCalibrationV3>();
+    default:
+      break;
+    }
+    break;
+
+  case 3:
+    // RodBlockType 3 = Test mode
+    return std::make_unique<LArRodBlockTransparentV0<LArRodBlockHeaderTransparentV0> >();
+
+  case 4:
+    // RodBlockType 4 = Physics mode
+    switch (rodMinorVersion) {
+    case 0: // Physics mode v0 05.01.2004 first draft
+      return std::make_unique<LArRodBlockPhysicsV0>();
+    case 1: // Physics mode v1 19.08.2004 only small differences
+      return std::make_unique<LArRodBlockPhysicsV1>();
+    case 2: // Physics mode v2 05.10.2004 adapted to real DSP data
+    case 3: // Physics mode v2
+    case 4: // Physics mode v2
+    case 5: // Physics mode v2
+    case 6: // Physics mode v2
+    case 7: // Physics mode v2
+    case 8: // Physics mode v2
+      return std::make_unique<LArRodBlockPhysicsV2>();
+    case 9: // Physics mode v4 10.07.2007 for commissioning
+      return std::make_unique<LArRodBlockPhysicsV4>();
+    case 10: // Physics mode v5 16.06.2008 for LHC 
+    case 11: // Physics mode v5 16.06.2008 for LHC
+      {
+        auto bl = std::make_unique<LArRodBlockPhysicsV5>();
+        if (m_requiredPhysicsNSamples > 0) {
+          bl->setRequiredNSamples(m_requiredPhysicsNSamples);
+        }
+        return bl;
+      }
+    case 12: // Physics mode v5 09.03.2011 for LHC
+      {
+        auto bl = std::make_unique<LArRodBlockPhysicsV6>();
+        if (m_requiredPhysicsNSamples > 0) {
+          bl->setRequiredNSamples(m_requiredPhysicsNSamples);
+        }
+        return bl;
+      }
+    default:
+      break;
+    }
+    break;
+
+  case 5:
+    // RodBlockType 5 = Physics simulation mode
+    // Physics mode v3 11.04.2005 for simulation
+    return std::make_unique<LArRodBlockPhysicsV3>();
+
+  case 6:
+    // RodBlockType 6 = Physics test mode
+    switch (rodMinorVersion) {
+    case 0: // Physics mode v0 05.01.2004 first draft
+      return std::make_unique<LArRodBlockPhysicsV0>();
+    case 1: // Physics mode v2 05.10.2004 adapted to real DSP data
+    case 2: // Physics mode v2
+      return std::make_unique<LArRodBlockPhysicsV2>();
+    default:
+      break;
+    }
+    break;
+
+  case 7:
+    // RodBlockType 7 = Calibration mode
+    switch (rodMinorVersion) {
+    case 0: // Calibration mode v0  05.01.2004
+      return std::make_unique<LArRodBlockCalibrationV0<LArRodBlockHeaderCalibrationV0> >();
+    case 1: // Calibration mode v1  17.01.2006
+    case 2: // Calibration mode v1 
+    case 3: // Calibration mode v1 
+    case 4: // Calibration mode v1 
+      return std::make_unique<LArRodBlockCalibrationV1>();
+    case 5: // Calibration mode v2  26.04.2006
+      return std::make_unique<LArRodBlockCalibrationV2>();
+    case 6: // Calibration mode v3  31.05.2006
+    case 7: // Calibration mode v3
+    case 8: // Calibration mode v3
+    case 9: // Calibration mode v3
+    case 10:// Calibration mode v3
+    case 11:// Calibration mode v3
+    case 12:// Calibration mode v3
+      return std::make_unique<LArRodBlockCalibrationV2>();
+    default:
+      break;
+    }
+    break;
+
+  case 10:
+    // RodBlockType 10 = Accumulated mode (used for pre-processed pedestal runs)
+    // Accumulated mode v3 10.06.2008
+    return std::make_unique<LArRodBlockAccumulatedV3>();
+
+  default:
+    break;
+  }
+
+  return std::unique_ptr<LArRodBlockStructure>();
+}
diff --git a/LArCalorimeter/LArCnv/LArByteStream/src/LArRodEncoder.cxx b/LArCalorimeter/LArCnv/LArByteStream/src/LArRodEncoder.cxx
index 7182e95be34..b5efc04aa66 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/src/LArRodEncoder.cxx
+++ b/LArCalorimeter/LArCnv/LArByteStream/src/LArRodEncoder.cxx
@@ -48,17 +48,20 @@ void LArRodEncoder::add(const LArRawChannel* rc)
 
 // Add free gain digits
 void LArRodEncoder::add(const LArDigit* dg)
-{uint32_t FEB_ID = (m_onlineHelper.feb_Id(dg->hardwareID()).get_identifier32().get_compact());
+{
+ uint32_t FEB_ID = (m_onlineHelper.feb_Id(dg->hardwareID()).get_identifier32().get_compact());
  m_mFEB[FEB_ID].vLArDigit.push_back(dg);
 }
 //Add fixed gain digits
 void LArRodEncoder::add(const LArDigit* dg, const int gain)
-{uint32_t FEB_ID = (m_onlineHelper.feb_Id(dg->hardwareID()).get_identifier32().get_compact());
+{
+ uint32_t FEB_ID = (m_onlineHelper.feb_Id(dg->hardwareID()).get_identifier32().get_compact());
  m_mFEB[FEB_ID].vLArDigitFixed[gain].push_back(dg);
 }
 //Add calibration digits
 void LArRodEncoder::add(const LArCalibDigit* dg, const int gain)
-{uint32_t FEB_ID = (m_onlineHelper.feb_Id(dg->hardwareID()).get_identifier32().get_compact());
+{
+ uint32_t FEB_ID = (m_onlineHelper.feb_Id(dg->hardwareID()).get_identifier32().get_compact());
  m_mFEB[FEB_ID].vLArCalibDigit[gain].push_back(dg);
 }
 
@@ -215,7 +218,7 @@ void LArRodEncoder::fillROD(std::vector<uint32_t>& v, MsgStream& logstr, const C
 	  m_BlStruct->setDAC((*digit_it)->DAC());
 	  m_BlStruct->setDelay((*digit_it)->delay());
 	  for (;digit_it!=digit_it_end;digit_it++) { 
-	    int cId =  m_cablingSvc.channel((*digit_it)->channelID()); 
+	    int cId =  m_onOffIdMapping.channel((*digit_it)->channelID()); 
 	    cId = m_BlStruct->FebToRodChannel(cId);
 	    m_BlStruct->setRawData(cId, (*digit_it)->samples(), (*digit_it)->gain());
 	    m_BlStruct->setIsPulsed(cId);
-- 
GitLab