2 Copyright (C) 2002-2021 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 //__________________________________________________________________________
26 template <class TRANS, class PERS>
27 T_AthenaPoolCustCnv<TRANS, PERS>::T_AthenaPoolCustCnv(ISvcLocator* pSvcLocator,
28 const char* name /*= nullptr*/)
29 : T_AthenaPoolCnvBase<TRANS>(pSvcLocator, name) {
31 //______________________________________________________________________________
32 template <class TRANS, class PERS>
33 StatusCode 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 //__________________________________________________________________________
42 template <class TRANS, class PERS>
43 const CLID& T_AthenaPoolCustCnv<TRANS, PERS>::classID() {
44 return(ClassID_traits<TRANS>::ID());
46 //__________________________________________________________________________
47 template <class TRANS, class PERS>
49 Placement 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 //__________________________________________________________________________
54 template <class TRANS, class PERS>
56 StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::objectToPool(P* pObj, Token*& token, const std::string& key, const std::string& output) {
57 const static std::string className = ClassName<P>::name();
59 // Allow for multiple class names
60 if (this->m_className != className) {
61 this->m_className = className;
62 // Different class name - get description
63 auto itClass = this->m_classDescs.find(className);
64 if (itClass == this->m_classDescs.end()) {
65 // For new class names, check dictionary
66 this->m_classDesc = RootType( typeid(P) );
67 this->m_classDescs[className] = this->m_classDesc;
69 // Set to correct class description
70 this->m_classDesc = (*itClass).second;
73 Placement placement = setPlacementForP(*pObj, key, output);
74 token = this->m_athenaPoolCnvSvc->registerForWrite(&placement, pObj, this->m_classDesc);
75 return(StatusCode::SUCCESS);
77 //__________________________________________________________________________
78 template <class TRANS, class PERS>
80 StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::poolToObject(const Token*& token, P*& pObj) {
82 void* voidPtr = nullptr;
84 this->m_athenaPoolCnvSvc->setObjPtr(voidPtr, token);
86 catch (const std::exception& ex) {
87 AthenaPoolCnvSvc::throwExcCaughtException (__PRETTY_FUNCTION__,
93 if (voidPtr == nullptr) {
94 ATH_MSG_ERROR("poolToObject: Could not get object for Token = " << (token != nullptr ? token->toString() : ""));
95 return(StatusCode::FAILURE);
97 pObj = reinterpret_cast<P*>(voidPtr);
98 return(StatusCode::SUCCESS);
100 //__________________________________________________________________________
101 template <class TRANS, class PERS>
102 StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::DataObjectToPers(DataObject* pObj, IOpaqueAddress*& /*pAddr*/) {
103 const std::string className = ClassName<TRANS>::name();
104 ATH_MSG_DEBUG("Called DataObjectToPers for " << pObj << ": " << className << ", with key " << pObj->name());
105 return(StatusCode::SUCCESS);
107 //__________________________________________________________________________
108 template <class TRANS, class PERS>
109 StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::DataObjectToPool(IOpaqueAddress* pAddr, DataObject* pObj) {
110 const std::string className = ClassName<TRANS>::name();
111 ATH_MSG_DEBUG("Called DataObjectToPool for " << pObj << ": " << className << ", with key " << pObj->name());
112 PERS* persObj = nullptr;
113 TRANS* obj = nullptr;
114 bool success = SG::fromStorable(pObj, obj);
115 if (!success || obj == nullptr) {
116 ATH_MSG_ERROR("failed to cast to T for class (type/key) " << className << "/" << pObj->name());
117 return(StatusCode::FAILURE);
119 if (!transToPers(obj, persObj).isSuccess()) {
120 ATH_MSG_ERROR("Failed to convert to persistent DataType for class (type/key) " << className << "/" << pObj->name());
121 return(StatusCode::FAILURE);
123 Token* token = nullptr;
124 StatusCode status = objectToPool<PERS>(persObj, token, pObj->name(), *pAddr->par());
125 // Null/empty token means ERROR
126 if (token == nullptr || token->classID() == Guid::null()) {
127 ATH_MSG_ERROR("Failed to get Token for class (type/key) " << className << "/" << pObj->name());
128 return(StatusCode::FAILURE);
130 // Update IOpaqueAddress for this object.
131 TokenAddress* tokAddr = dynamic_cast<TokenAddress*>(pAddr);
132 if (tokAddr != nullptr) {
133 tokAddr->setToken(token); token = nullptr;
135 delete token; token = nullptr;
136 return(StatusCode::FAILURE);
140 //__________________________________________________________________________
141 template <class TRANS, class PERS>
143 T_AthenaPoolCustCnv<TRANS, PERS>::PoolToDataObject(DataObject*& pObj,
145 const std::string& /*key*/)
147 TRANS* transObj = nullptr;
149 if (!poolToObject<PERS>(token, obj).isSuccess()) {
150 ATH_MSG_ERROR("Failed to read persistent DataType");
151 return(StatusCode::FAILURE);
153 if (!persToTrans(transObj, obj).isSuccess()) {
154 delete transObj; transObj = nullptr;
155 delete obj; obj = nullptr;
156 ATH_MSG_ERROR("Failed to convert to transient DataType");
157 return(StatusCode::FAILURE);
159 delete obj; obj = nullptr;
160 pObj = SG::asStorable(transObj);
161 return(StatusCode::SUCCESS);
163 //__________________________________________________________________________
164 // Set the token (in std::string representation) and classID for
165 // the object that will be read next. Required by compareClassGuid()
166 template <class TRANS, class PERS>
167 inline void T_AthenaPoolCustCnv<TRANS, PERS>::setToken(const std::string& token_str) {
168 delete this->m_i_poolToken; this->m_i_poolToken = nullptr;
169 Token* token = new Token;
170 token->fromString(token_str);
171 this->m_i_poolToken = token; token = nullptr;
172 m_classID = this->m_i_poolToken->classID();
174 //__________________________________________________________________________
175 // Compare POOL class GUID with the one from object being read
176 // To be used in createTransient()
177 template <class TRANS, class PERS>
178 inline bool T_AthenaPoolCustCnv<TRANS, PERS>::compareClassGuid(const pool::Guid &guid) const {
179 return(guid == m_classID);