ATLAS Offline Software
T_AthenaPoolCustomCnv.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 /** @file T_AthenaPoolCustomCnv.icc
6  * @brief This file contains the implementation for the templated T_AthenaPoolCustomCnv class.
7  * @author Marcin.Nowak@cern.ch
8  **/
9 
10 #include "GaudiKernel/StatusCode.h"
11 #include "GaudiKernel/DataObject.h"
12 #include "GaudiKernel/IOpaqueAddress.h"
13 #include "GaudiKernel/IRegistry.h"
14 
15 #include "StorageSvc/DbReflex.h"
16 
17 #include "AthenaKernel/StorableConversions.h"
18 
19 #include "AthenaPoolCnvSvc/exceptions.h"
20 #include "AthenaPoolCnvTPExtension.h"
21 
22 #include <sstream>
23 #include <stdexcept>
24 
25 template <class TRANS, class PERS>
26 T_AthenaPoolCustomCnvWithKey<TRANS, PERS>::T_AthenaPoolCustomCnvWithKey(ISvcLocator* pSvcLocator,
27  const char* name /*= nullptr*/) : BaseType(pSvcLocator, name) {
28 }
29 
30 template <class TRANS, class PERS>
31 StatusCode T_AthenaPoolCustomCnvWithKey<TRANS, PERS>::DataObjectToPers(DataObject* pObj, IOpaqueAddress*& /*pAddr*/) {
32  ATH_MSG_VERBOSE("In DataObjectToPers() for key = " << pObj->name());
33  return(StatusCode::SUCCESS);
34 }
35 
36 template <class TRANS, class PERS>
37 StatusCode T_AthenaPoolCustomCnvWithKey<TRANS, PERS>::DataObjectToPool(IOpaqueAddress* pAddr, DataObject* pObj) {
38  ATH_MSG_VERBOSE("In DataObjectToPool() for key = " << pObj->name());
39  TRANS* obj = nullptr;
40  PERS* persObj = nullptr;
41  bool success = SG::fromStorable(pObj, obj);
42  if (!success || obj == nullptr) {
43  ATH_MSG_ERROR("Failed to cast DataObject to transient type");
44  return(StatusCode::FAILURE);
45  }
46  try {
47  persObj = createPersistentWithKey(obj, pObj->name());
48  }
49  catch (const std::exception& ex) {
50  AthenaPoolCnvSvc::throwExcCaughtException (__PRETTY_FUNCTION__,
51  "creating persistent object",
52  ex,
53  typeid(TRANS),
54  pObj->name());
55  }
56  std::unique_ptr<Token> token;
57  StatusCode status = this->objectToPool(persObj, token, pObj->name(), *pAddr->par());
58  // Null/empty token means ERROR
59  if (token == nullptr || token->classID() == Guid::null()) {
60  ATH_MSG_ERROR("failed to get Token for " << pObj->name());
61  return(StatusCode::FAILURE);
62  }
63  std::size_t cpos = pAddr->par()->find(':');
64  std::size_t bpos = pAddr->par()->find('[');
65  if (cpos == std::string::npos) {
66  cpos = 0;
67  } else {
68  cpos++;
69  }
70  if (bpos != std::string::npos) bpos = bpos - cpos;
71  keepPoolObj(persObj, pAddr->par()->substr(cpos, bpos));
72  // Update IOpaqueAddress for this object.
73  TokenAddress* tokAddr = dynamic_cast<TokenAddress*>(pAddr);
74  if (tokAddr != nullptr) {
75  tokAddr->setToken(std::move(token));
76  } else {
77  return(StatusCode::FAILURE);
78  }
79  return(status);
80 }
81 
82 template <class TRANS, class PERS>
83 StatusCode
84 T_AthenaPoolCustomCnvWithKey<TRANS, PERS>::PoolToDataObject(DataObject*& pObj,
85  const Token* token,
86  const std::string& key)
87 {
88  if (token != nullptr) {
89  this->m_classID = token->classID();
90  }
91  TRANS* transObj = nullptr;
92  AthenaConverterTLPExtension *extCnv = dynamic_cast<AthenaConverterTLPExtension*>(this);
93  // reset the TP converter used for reading, so old value is not used
94  if (extCnv != nullptr) {
95  extCnv->resetTPCnvForReading();
96  }
97  try {
98  transObj = createTransientWithKey(key);
99  }
100  catch(const std::exception& ex) {
101  AthenaPoolCnvSvc::throwExcCaughtException (__PRETTY_FUNCTION__,
102  "creating transient object",
103  ex,
104  typeid(TRANS),
105  key);
106  }
107  if (extCnv != nullptr) {
108  extCnv->deletePersistentObjects();
109  }
110  pObj = SG::asStorable(transObj);
111  return(StatusCode::SUCCESS);
112 }
113 
114 // Read object of type P. This is an exception-throwing version of poolToObject()
115 // plus reading of all extending objects
116 template <class TRANS, class PERS>
117 template <class P>
118 inline P* T_AthenaPoolCustomCnvWithKey<TRANS, PERS>::poolReadObject() {
119  P* persObj = nullptr;
120  if (this->poolToObject(this->m_i_poolToken, persObj).isFailure()) {
121  std::string error("POOL read failed. Token = ");
122  throw std::runtime_error(error + (this->m_i_poolToken != nullptr ? this->m_i_poolToken->toString() : ""));
123  }
124  AthenaConverterTLPExtension *extCnv = dynamic_cast<AthenaConverterTLPExtension*>(this);
125  if (extCnv != nullptr) {
126  extCnv->readExtendingObjects(persObj);
127  }
128  return(persObj);
129 }
130 
131 // Read object of type P (plus all extending objects)
132 // using the indicated top-level TP converter
133 template <class TRANS, class PERS>
134 template <class P>
135 inline void T_AthenaPoolCustomCnvWithKey<TRANS, PERS>::poolReadObject(TopLevelTPCnvBase& tlp_converter) {
136  AthenaPoolCnvTPExtension *extCnv = dynamic_cast<AthenaPoolCnvTPExtension*>(this);
137  // set which Top level TP concerter will by used for reading
138  // only matters for extended converters
139  if (extCnv != nullptr) {
140  extCnv->usingTPCnvForReading(tlp_converter);
141  }
142  // read the object
143  P* persObj = poolReadObject<P>();
144  // remember the object we just read
145  tlp_converter.setTLPersObject(persObj);
146  // not returning the object - the TLP converter owns it now
147  // and it will delete it automatically in createTransient()!
148 }
149 
150 // Remember the POOL object until commit (then delete it)
151 template <class TRANS, class PERS>
152 inline void T_AthenaPoolCustomCnvWithKey<TRANS, PERS>::keepPoolObj(PERS* obj, const std::string& output) {
153  std::ostringstream oss;
154  oss << Gaudi::Hive::currentContext().slot();
155  std::lock_guard lock(m_pListMutex);
156  m_persObjLists[output + ":" + oss.str()].emplace_back(obj);
157 }
158 
159 // callback from the CleanupSvc to delete persistent objects after commit
160 template <class TRANS, class PERS>
161 StatusCode T_AthenaPoolCustomCnvWithKey<TRANS, PERS>::cleanUp(const std::string& output) {
162  std::ostringstream oss;
163  oss << Gaudi::Hive::currentContext().slot();
164  std::lock_guard lock(m_pListMutex);
165  m_persObjLists[output + ":" + oss.str()].clear();
166  return(StatusCode::SUCCESS);
167 }
168 
169 
170 template <class TRANS, class PERS>
171 PERS* T_AthenaPoolCustomCnv<TRANS, PERS>::createPersistentWithKey
172  (TRANS* obj, const std::string& /*key*/)
173 {
174  return createPersistent(obj);
175 }
176 
177 
178 template <class TRANS, class PERS>
179 TRANS* T_AthenaPoolCustomCnv<TRANS, PERS>::createTransientWithKey
180  (const std::string& /*key*/)
181 {
182  return createTransient();
183 }