ATLAS Offline Software
T_AthenaPoolCustCnv.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
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>
8  **/
9 
10 #include "AthenaPoolCnvSvc/IAthenaPoolCnvSvc.h"
11 #include "AthenaPoolCnvSvc/exceptions.h"
12 
13 #include "GaudiKernel/StatusCode.h"
14 #include "GaudiKernel/DataObject.h"
15 #include "GaudiKernel/IOpaqueAddress.h"
16 #include "GaudiKernel/IRegistry.h"
17 
18 #include "StorageSvc/DbReflex.h"
19 
20 #include "AthenaKernel/CLASS_DEF.h"
21 #include "AthenaKernel/ClassName.h"
22 #include "AthenaKernel/StorableConversions.h"
23 #include "PersistentDataModel/Token.h"
24 
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), m_persMap() {
30 }
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);
38  }
39  return(this->m_athenaPoolCnvSvc->registerCleanUp(this));
40 }
41 //__________________________________________________________________________
42 template <class TRANS, class PERS>
43 const CLID& T_AthenaPoolCustCnv<TRANS, PERS>::classID() {
44  return(ClassID_traits<TRANS>::ID());
45 }
46 //__________________________________________________________________________
47 template <class TRANS, class PERS>
48 template <class P>
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));
52 }
53 //__________________________________________________________________________
54 template <class TRANS, class PERS>
55 template <class P>
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();
58  // Check dictionary
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;
68  } else {
69  // Set to correct class description
70  this->m_classDesc = (*itClass).second;
71  }
72  }
73  Placement placement = setPlacementForP(*pObj, key, output);
74  token = this->m_athenaPoolCnvSvc->registerForWrite(&placement, pObj, this->m_classDesc);
75  return(StatusCode::SUCCESS);
76 }
77 //__________________________________________________________________________
78 template <class TRANS, class PERS>
79 template <class P>
80 StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::poolToObject(const Token*& token, P*& pObj) {
81  pObj = nullptr;
82  void* voidPtr = nullptr;
83  try {
84  this->m_athenaPoolCnvSvc->setObjPtr(voidPtr, token);
85  }
86  catch (const std::exception& ex) {
87  AthenaPoolCnvSvc::throwExcCaughtException (__PRETTY_FUNCTION__,
88  "pooltoObject",
89  ex,
90  typeid(P),
91  token->toString());
92  }
93  if (voidPtr == nullptr) {
94  ATH_MSG_ERROR("poolToObject: Could not get object for Token = " << (token != nullptr ? token->toString() : ""));
95  return(StatusCode::FAILURE);
96  }
97  pObj = reinterpret_cast<P*>(voidPtr);
98  return(StatusCode::SUCCESS);
99 }
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() << ", map size = " << m_persMap.size());
105  PERS* persObj = nullptr;
106  m_persMap.insert(std::pair<DataObject*, PERS*>(pObj, persObj));
107  return(StatusCode::SUCCESS);
108 }
109 //__________________________________________________________________________
110 template <class TRANS, class PERS>
111 StatusCode T_AthenaPoolCustCnv<TRANS, PERS>::DataObjectToPool(IOpaqueAddress* pAddr, DataObject* pObj) {
112  const std::string className = ClassName<TRANS>::name();
113  ATH_MSG_DEBUG("Called DataObjectToPool for " << pObj << ": " << className << ", with key " << pObj->name() << ", map size = " << m_persMap.size());
114  PERS* persObj = nullptr;
115  typename std::map<DataObject*, PERS*>::iterator it = m_persMap.find(pObj);
116  if (it != m_persMap.end()) {
117  persObj = it->second;
118  m_persMap.erase(it);
119  }
120  if (persObj == nullptr) {
121  TRANS* obj = nullptr;
122  bool success = SG::fromStorable(pObj, obj);
123  if (!success || obj == nullptr) {
124  ATH_MSG_ERROR("failed to cast to T for class (type/key) " << className << "/" << pObj->name());
125  return(StatusCode::FAILURE);
126  }
127  if (!transToPers(obj, persObj).isSuccess()) {
128  ATH_MSG_ERROR("Failed to convert to persistent DataType for class (type/key) " << className << "/" << pObj->name());
129  return(StatusCode::FAILURE);
130  }
131  }
132  Token* token = nullptr;
133  StatusCode status = objectToPool<PERS>(persObj, token, pObj->name(), *pAddr->par());
134  // Null/empty token means ERROR
135  if (token == nullptr || token->classID() == Guid::null()) {
136  ATH_MSG_ERROR("Failed to get Token for class (type/key) " << className << "/" << pObj->name());
137  return(StatusCode::FAILURE);
138  }
139  // Update IOpaqueAddress for this object.
140  TokenAddress* tokAddr = dynamic_cast<TokenAddress*>(pAddr);
141  if (tokAddr != nullptr) {
142  tokAddr->setToken(token); token = nullptr;
143  } else {
144  delete token; token = nullptr;
145  return(StatusCode::FAILURE);
146  }
147  return(status);
148 }
149 //__________________________________________________________________________
150 template <class TRANS, class PERS>
151 StatusCode
152 T_AthenaPoolCustCnv<TRANS, PERS>::PoolToDataObject(DataObject*& pObj,
153  const Token* token,
154  const std::string& /*key*/)
155 {
156  TRANS* transObj = nullptr;
157  PERS* obj = nullptr;
158  if (!poolToObject<PERS>(token, obj).isSuccess()) {
159  ATH_MSG_ERROR("Failed to read persistent DataType");
160  return(StatusCode::FAILURE);
161  }
162  if (!persToTrans(transObj, obj).isSuccess()) {
163  delete transObj; transObj = nullptr;
164  delete obj; obj = nullptr;
165  ATH_MSG_ERROR("Failed to convert to transient DataType");
166  return(StatusCode::FAILURE);
167  }
168  delete obj; obj = nullptr;
169  pObj = SG::asStorable(transObj);
170  return(StatusCode::SUCCESS);
171 }
172 //__________________________________________________________________________
173 // Set the token (in std::string representation) and classID for
174 // the object that will be read next. Required by compareClassGuid()
175 template <class TRANS, class PERS>
176 inline void T_AthenaPoolCustCnv<TRANS, PERS>::setToken(const std::string& token_str) {
177  delete this->m_i_poolToken; this->m_i_poolToken = nullptr;
178  Token* token = new Token;
179  token->fromString(token_str);
180  this->m_i_poolToken = token; token = nullptr;
181  m_classID = this->m_i_poolToken->classID();
182 }
183 //__________________________________________________________________________
184 // Compare POOL class GUID with the one from object being read
185 // To be used in createTransient()
186 template <class TRANS, class PERS>
187 inline bool T_AthenaPoolCustCnv<TRANS, PERS>::compareClassGuid(const pool::Guid &guid) const {
188  return(guid == m_classID);
189 }