From 18b75bbfd758ade8df034f45f40fa31aad5108e3 Mon Sep 17 00:00:00 2001
From: Attila Krasznahorkay <krasznaa@cern.ch>
Date: Tue, 31 May 2016 11:23:48 +0200
Subject: [PATCH] Adding xAODMaker::ElementLinkResetAlg to the trunk as well
 (xAODCoreCnv-00-01-02)

	* Adding the xAODMaker::ElementLinkResetAlg algorithm from
	  xAODCoreCnv-00-00-07-branch.
	* Updated the package's CMT and CMake configuration to build
	  the new code correctly.
	* Tagging as xAODCoreCnv-00-01-02


Former-commit-id: 26e5f0ab0649ef211f8712ebd08a8a8d89a3b747
---
 Event/xAOD/xAODCoreCnv/CMakeLists.txt         |   3 +-
 Event/xAOD/xAODCoreCnv/cmt/requirements       |   5 +-
 .../xAODCoreCnv/src/ElementLinkResetAlg.cxx   | 149 ++++++++++++++++++
 .../xAODCoreCnv/src/ElementLinkResetAlg.h     |  75 +++++++++
 .../src/components/xAODCoreCnv_entries.cxx    |   7 +-
 5 files changed, 233 insertions(+), 6 deletions(-)
 create mode 100644 Event/xAOD/xAODCoreCnv/src/ElementLinkResetAlg.cxx
 create mode 100644 Event/xAOD/xAODCoreCnv/src/ElementLinkResetAlg.h

diff --git a/Event/xAOD/xAODCoreCnv/CMakeLists.txt b/Event/xAOD/xAODCoreCnv/CMakeLists.txt
index 30798230743..d8ebff32460 100644
--- a/Event/xAOD/xAODCoreCnv/CMakeLists.txt
+++ b/Event/xAOD/xAODCoreCnv/CMakeLists.txt
@@ -11,6 +11,7 @@ atlas_depends_on_subdirs(
    PRIVATE
    Control/AthContainers
    Control/AthContainersInterfaces
+   Control/AthLinks
    Control/AthenaBaseComps
    Control/AthenaKernel
    Control/SGTools
@@ -20,7 +21,7 @@ atlas_depends_on_subdirs(
 # Component(s) in the package:
 atlas_add_component( xAODCoreCnv
    src/*.h src/*.cxx src/components/*.cxx
-   LINK_LIBRARIES AthContainers AthenaBaseComps AthenaKernel SGTools
+   LINK_LIBRARIES AthContainers AthLinks AthenaBaseComps AthenaKernel SGTools
    xAODCore GaudiKernel )
 
 # Install files from the package:
diff --git a/Event/xAOD/xAODCoreCnv/cmt/requirements b/Event/xAOD/xAODCoreCnv/cmt/requirements
index 7d7f0d32b4c..be7aa53adb7 100644
--- a/Event/xAOD/xAODCoreCnv/cmt/requirements
+++ b/Event/xAOD/xAODCoreCnv/cmt/requirements
@@ -1,5 +1,5 @@
 package xAODCoreCnv
-# $Id: requirements 742532 2016-04-25 07:57:58Z krasznaa $
+# $Id: requirements 751107 2016-05-31 11:23:23Z krasznaa $
 
 author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
 
@@ -16,6 +16,7 @@ use AthenaBaseComps         AthenaBaseComps-*         Control
 use AthenaKernel            AthenaKernel-*            Control
 use AthContainers           AthContainers-*           Control
 use AthContainersInterfaces AthContainersInterfaces-* Control
+use AthLinks                AthLinks-*                Control
 use SGTools                 SGTools-*                 Control
 
 # EDM package(s):
@@ -29,5 +30,3 @@ apply_pattern component_library
 
 # Install the jobOptions:
 apply_pattern declare_joboptions files=*.py
-
-# Useless comment, to allow modifying the CMakeLists.txt file
diff --git a/Event/xAOD/xAODCoreCnv/src/ElementLinkResetAlg.cxx b/Event/xAOD/xAODCoreCnv/src/ElementLinkResetAlg.cxx
new file mode 100644
index 00000000000..d0a3fdc46cc
--- /dev/null
+++ b/Event/xAOD/xAODCoreCnv/src/ElementLinkResetAlg.cxx
@@ -0,0 +1,149 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ElementLinkResetAlg.cxx 751107 2016-05-31 11:23:23Z krasznaa $
+
+// EDM include(s):
+#include "AthContainersInterfaces/IConstAuxStore.h"
+#include "AthContainers/AuxTypeRegistry.h"
+#include "AthContainers/normalizedTypeinfoName.h"
+#include "AthLinks/ElementLinkBase.h"
+
+// Local include(s):
+#include "ElementLinkResetAlg.h"
+
+namespace xAODMaker {
+
+   ElementLinkResetAlg::ElementLinkResetAlg( const std::string& name,
+                                             ISvcLocator* svcLoc )
+      : AthAlgorithm( name, svcLoc ) {
+
+      declareProperty( "SGKeys", m_keys );
+   }
+
+   StatusCode ElementLinkResetAlg::initialize() {
+
+      // Tell the user what's happening:
+      ATH_MSG_INFO( "Initialising - Package version: " << PACKAGE_VERSION );
+      ATH_MSG_DEBUG( "SGKeys = " << m_keys );
+
+      // Return gracefully:
+      return StatusCode::SUCCESS;
+   }
+
+   StatusCode ElementLinkResetAlg::execute() {
+
+      // Collect all the container(s):
+      std::vector< const SG::IConstAuxStore* > stores;
+      if( m_keys.size() ) {
+         for( const std::string& key : m_keys ) {
+            const SG::IConstAuxStore* store = 0;
+            ATH_CHECK( evtStore()->retrieve( store, key ) );
+            stores.push_back( store );
+         }
+      } else {
+         SG::ConstIterator< SG::IConstAuxStore > begin, end;
+         ATH_CHECK( evtStore()->retrieve( begin, end ) );
+         for( auto itr = begin; itr != end; ++itr ) {
+            const SG::IConstAuxStore* store = 0;
+            ATH_CHECK( evtStore()->retrieve( store, itr.key() ) );
+            stores.push_back( store );
+         }
+      }
+      ATH_MSG_DEBUG( "Number of IConstAuxStore objects retrieved: "
+                     << stores.size() );
+
+      // Reset the ElementLinks in all of them:
+      for( const SG::IConstAuxStore* store : stores ) {
+         ATH_MSG_VERBOSE( "Reseting element links in store: " << store );
+         ATH_CHECK( reset( *store ) );
+      }
+
+      // Return gracefully:
+      return StatusCode::SUCCESS;
+   }
+
+   StatusCode ElementLinkResetAlg::reset( const SG::IConstAuxStore& store ) {
+
+      // Get all the IDs stored in this object:
+      const SG::auxid_set_t& auxids = store.getAuxIDs();
+
+      // The auxiliary type registry:
+      SG::AuxTypeRegistry& reg = SG::AuxTypeRegistry::instance();
+
+      // Loop over them:
+      for( SG::auxid_t auxid : auxids ) {
+
+         // Check/cache its type:
+         if( m_typeCache.size() <= auxid ) {
+            m_typeCache.resize( auxid + 1 );
+         }
+         if( ! m_typeCache[ auxid ].isSet ) {
+            const std::string tname =
+               SG::normalizedTypeinfoName( *( reg.getType( auxid ) ) );
+            static const std::string pat1 = "ElementLink<";
+            static const std::string pat2 = "std::vector<ElementLink<";
+            if( tname.substr( 0, pat1.size() ) == pat1 ) {
+               m_typeCache[ auxid ].isEL = true;
+            } else if( tname.substr( 0, pat2.size() ) == pat2 ) {
+               m_typeCache[ auxid ].isELVec = true;
+            }
+            m_typeCache[ auxid ].isSet = true;
+            ATH_MSG_VERBOSE( "Type for \"" << tname << "\": isEL = "
+                             << m_typeCache[ auxid ].isEL << ", isELVec = "
+                             << m_typeCache[ auxid ].isELVec );
+         }
+
+         // If it's not an EL type, then don't bother:
+         if( ! ( m_typeCache[ auxid ].isEL || m_typeCache[ auxid ].isELVec ) ) {
+            continue;
+         }
+
+         // Get a pointer to the vector variable. We need to cast away
+         // its constness in this ugly way, we can't afford to only ask for
+         // non-const pointers from the store. Since the ElementLink to be
+         // reset may very well be a const variable that was accessed already,
+         // and now needs its cache wiped.
+         void* ptr = const_cast< void* >( store.getData( auxid ) );
+
+         // Get the variable's element size:
+         const size_t eltSize = reg.getEltSize( auxid );
+
+         // Loop over its elements:
+         const size_t sz_i = store.size();
+         for( size_t i = 0; i < sz_i; ++i ) {
+
+            // Raw pointer to the object:
+            void* eltPtr = reinterpret_cast< char* >( ptr ) + i * eltSize;
+
+            // Do different things based on the variable type:
+            if( m_typeCache[ auxid ].isEL ) {
+               // For a single ElementLink, the logic is relatively simple:
+               reinterpret_cast< ElementLinkBase* >( eltPtr )->toTransient();
+            } else if( m_typeCache[ auxid ].isELVec ) {
+               // For a vector of links we heavily rely on knowing how GCC/Clang
+               // lays out the memory for vectors.
+               std::vector< ElementLinkBase >& v =
+                  *( reinterpret_cast< std::vector< ElementLinkBase >* >( eltPtr ) );
+               const size_t sz_j = v.size();
+               for( size_t j = 0; j < sz_j; ++j ) {
+                  v[ j ].toTransient();
+               }
+            } else {
+               ATH_MSG_FATAL( "There is a logic error in the code" );
+               return StatusCode::FAILURE;
+            }
+         }
+      }
+
+      // Return gracefully:
+      return StatusCode::SUCCESS;
+   }
+
+   ElementLinkResetAlg::AuxIDType::AuxIDType()
+      : isSet( false ), isEL( false ), isELVec( false ) {
+
+   }
+
+} // namespace xAODMaker
diff --git a/Event/xAOD/xAODCoreCnv/src/ElementLinkResetAlg.h b/Event/xAOD/xAODCoreCnv/src/ElementLinkResetAlg.h
new file mode 100644
index 00000000000..6f819948a46
--- /dev/null
+++ b/Event/xAOD/xAODCoreCnv/src/ElementLinkResetAlg.h
@@ -0,0 +1,75 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ElementLinkResetAlg.h 751107 2016-05-31 11:23:23Z krasznaa $
+#ifndef XAODCORECNV_ELEMENTLINKRESETALG_H
+#define XAODCORECNV_ELEMENTLINKRESETALG_H
+
+// System include(s):
+#include <vector>
+#include <string>
+
+// Gaudi/Athena include(s):
+#include "AthenaBaseComps/AthAlgorithm.h"
+
+// Forward declaration(s):
+namespace SG {
+   class IConstAuxStore;
+}
+
+namespace xAODMaker {
+
+   /**
+    *  @short Algorithm reseting ElementLink objects to their default state
+    *
+    *         This algorithm can be used to make sure that during/after an
+    *         AODFix-like configuration EDM objects are not left with cached
+    *         pointers to no longer existing objects.
+    *
+    *         The algorithm can make sure that every ElementLink in some
+    *         selected container(s), or all containers that are in StoreGate,
+    *         are cleared of all cached information.
+    *
+    * @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
+    *
+    * $Revision: 751107 $
+    * $Date: 2016-05-31 13:23:23 +0200 (Tue, 31 May 2016) $
+    */
+   class ElementLinkResetAlg : public AthAlgorithm {
+
+   public:
+      /// Regular Algorithm constructor
+      ElementLinkResetAlg( const std::string& name, ISvcLocator* svcLoc );
+
+      /// Function initialising the algorithm
+      virtual StatusCode initialize();
+      /// Function executing the algorithm
+      virtual StatusCode execute();
+
+   private:
+      /// Function reseting all the ElementLinks in one specific container
+      StatusCode reset( const SG::IConstAuxStore& store );
+
+      /// StoreGate keys of the auxiliary objects to be processed
+      std::vector< std::string > m_keys;
+
+      /// Helper class for caching auxiliary ID types
+      class AuxIDType {
+      public:
+         AuxIDType();
+         bool isSet; ///< Flag for whether this type was already set up
+         bool isEL; ///< True if the type is an ElementLink
+         bool isELVec; ///< True of the type is an ElementLink vector
+      };
+
+      /// Cached types of the auxiliary IDs
+      std::vector< AuxIDType > m_typeCache;
+
+   }; // class ElementLinkResetAlg
+
+} // namespace xAODMaker
+
+#endif // XAODCORECNV_ELEMENTLINKRESETALG_H
diff --git a/Event/xAOD/xAODCoreCnv/src/components/xAODCoreCnv_entries.cxx b/Event/xAOD/xAODCoreCnv/src/components/xAODCoreCnv_entries.cxx
index 15f70da1100..012b331a940 100644
--- a/Event/xAOD/xAODCoreCnv/src/components/xAODCoreCnv_entries.cxx
+++ b/Event/xAOD/xAODCoreCnv/src/components/xAODCoreCnv_entries.cxx
@@ -1,15 +1,18 @@
-// $Id: xAODCoreCnv_entries.cxx 583869 2014-02-18 11:31:09Z krasznaa $
+// $Id: xAODCoreCnv_entries.cxx 751107 2016-05-31 11:23:23Z krasznaa $
 
 // Gaudi/Athena include(s):
 #include "GaudiKernel/DeclareFactoryEntries.h"
 
 // Local include(s):
 #include "../AuxStoreWrapper.h"
+#include "../ElementLinkResetAlg.h"
 
 DECLARE_NAMESPACE_ALGORITHM_FACTORY( xAODMaker, AuxStoreWrapper )
+DECLARE_NAMESPACE_ALGORITHM_FACTORY( xAODMaker, ElementLinkResetAlg )
 
-DECLARE_FACTORY_ENTRIES( xAODCreatorAlgs ) {
+DECLARE_FACTORY_ENTRIES( xAODCoreCnv ) {
 
    DECLARE_NAMESPACE_ALGORITHM( xAODMaker, AuxStoreWrapper )
+   DECLARE_NAMESPACE_ALGORITHM( xAODMaker, ElementLinkResetAlg )
 
 }
-- 
GitLab