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