2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
5/** @file T_AthenaPoolCustCnv.icc
6 * @brief This file contains the implementation for the templated T_AthenaPoolCustCnv class.
7 * @author Peter van Gemmeren <gemmeren@anl.gov>
10#include "AthenaPoolCnvSvc/IAthenaPoolCnvSvc.h"
11#include "AthenaPoolCnvSvc/exceptions.h"
13#include "GaudiKernel/StatusCode.h"
14#include "GaudiKernel/DataObject.h"
15#include "GaudiKernel/IOpaqueAddress.h"
16#include "GaudiKernel/IRegistry.h"
18#include "StorageSvc/DbReflex.h"
20#include "AthenaKernel/CLASS_DEF.h"
21#include "AthenaKernel/ClassName.h"
22#include "AthenaKernel/StorableConversions.h"
23#include "PersistentDataModel/Token.h"
25//__________________________________________________________________________
26template <class TRANS, class PERS>
27T_AthenaPoolCustCnv<TRANS, PERS>::T_AthenaPoolCustCnv(ISvcLocator* pSvcLocator,
28 const char* name /*= nullptr*/)
29 : T_AthenaPoolCnvBase<TRANS>(pSvcLocator, name), m_className(), m_classDescs() {
31//______________________________________________________________________________
32template <class TRANS, class PERS>
33StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::initialize() {
34 ATH_MSG_DEBUG("initialize() in T_AthenaPoolCustCnv " << classID());
35 if (!T_AthenaPoolCnvBase<TRANS>::initialize().isSuccess()) {
36 ATH_MSG_FATAL("Failed to initialize AthenaPoolConverter base class.");
37 return(StatusCode::FAILURE);
39 return(this->m_athenaPoolCnvSvc->registerCleanUp(this));
41//__________________________________________________________________________
42template <class TRANS, class PERS>
43CLID T_AthenaPoolCustCnv<TRANS, PERS>::classID() {
44 return(ClassID_traits<TRANS>::ID());
46//__________________________________________________________________________
47template <class TRANS, class PERS>
49Placement T_AthenaPoolCustCnv<TRANS, PERS>::setPlacementForP(P& /*p*/, const std::string& key, const std::string& output) {
50 const std::string typenm = ClassName<P>::name();
51 return(this->setPlacementWithType(typenm, key, output));
53//__________________________________________________________________________
54template <class TRANS, class PERS>
56StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::objectToPool(P* pObj, std::unique_ptr<Token>& token, const std::string& key, const std::string& output) {
57 const static std::string className = ClassName<P>::name();
59 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
60 // Allow for multiple class names
61 if (m_className != className) {
62 m_className = className;
63 // Different class name - get description
64 auto itClass = m_classDescs.find(className);
65 if (itClass == m_classDescs.end()) {
66 // For new class names, check dictionary
67 m_classDescs[className] = RootType( typeid(P) );
70 Placement placement = setPlacementForP(*pObj, key, output);
71 token.reset(this->m_athenaPoolCnvSvc->registerForWrite(&placement, pObj, m_classDescs[m_className]));
72 return(StatusCode::SUCCESS);
74//__________________________________________________________________________
75template <class TRANS, class PERS>
77StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::poolToObject(const Token* token, P*& pObj) {
79 void* voidPtr = nullptr;
81 this->m_athenaPoolCnvSvc->setObjPtr(voidPtr, token);
83 catch (const std::exception& ex) {
84 AthenaPoolCnvSvc::throwExcCaughtException (__PRETTY_FUNCTION__,
88 token != nullptr ? token->toString() : "");
90 if (voidPtr == nullptr) {
91 ATH_MSG_ERROR("poolToObject: Could not get object for Token = " << (token != nullptr ? token->toString() : ""));
92 return(StatusCode::FAILURE);
94 pObj = reinterpret_cast<P*>(voidPtr);
95 return(StatusCode::SUCCESS);
97//__________________________________________________________________________
98template <class TRANS, class PERS>
99StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::DataObjectToPool(IOpaqueAddress* pAddr, DataObject* pObj) {
100 const std::string className = ClassName<TRANS>::name();
101 ATH_MSG_DEBUG("Called DataObjectToPool for " << pObj << ": " << className << ", with key " << pObj->name());
102 PERS* persObj = nullptr;
103 TRANS* obj = nullptr;
104 bool success = SG::fromStorable(pObj, obj);
105 if (!success || obj == nullptr) {
106 ATH_MSG_ERROR("failed to cast to T for class (type/key) " << className << "/" << pObj->name());
107 return(StatusCode::FAILURE);
110 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
111 if (!transToPers(obj, persObj).isSuccess()) {
112 ATH_MSG_ERROR("Failed to convert to persistent DataType for class (type/key) " << className << "/" << pObj->name());
113 return(StatusCode::FAILURE);
116 std::unique_ptr<Token> token;
117 StatusCode status = objectToPool<PERS>(persObj, token, pObj->name(), *pAddr->par());
118 // Null/empty token means ERROR
119 if (token == nullptr || token->classID() == Guid::null()) {
120 ATH_MSG_ERROR("Failed to get Token for class (type/key) " << className << "/" << pObj->name());
121 return(StatusCode::FAILURE);
123 // Update IOpaqueAddress for this object.
124 TokenAddress* tokAddr = dynamic_cast<TokenAddress*>(pAddr);
125 if (tokAddr != nullptr) {
126 tokAddr->setToken(std::move(token));
128 return(StatusCode::FAILURE);
132//__________________________________________________________________________
133template <class TRANS, class PERS>
135T_AthenaPoolCustCnv<TRANS, PERS>::PoolToDataObject(DataObject*& pObj,
137 const std::string& /*key*/)
139 TRANS* transObj = nullptr;
141 if (!poolToObject<PERS>(token, obj).isSuccess()) {
142 ATH_MSG_ERROR("Failed to read persistent DataType");
143 return(StatusCode::FAILURE);
146 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
147 if (!persToTrans(transObj, obj).isSuccess()) {
148 delete transObj; transObj = nullptr;
149 delete obj; obj = nullptr;
150 ATH_MSG_ERROR("Failed to convert to transient DataType");
151 return(StatusCode::FAILURE);
154 delete obj; obj = nullptr;
155 pObj = SG::asStorable(transObj);
156 return(StatusCode::SUCCESS);
158//__________________________________________________________________________
159// Compare POOL class GUID with the one from object being read
160// To be used in createTransient(const Token* token)
161template <class TRANS, class PERS>
162inline bool T_AthenaPoolCustCnv<TRANS, PERS>::compareClassGuid(const Token* token, const pool::Guid &guid) const {
163 return(token ? (guid == token->classID()) : false);