ATLAS Offline Software
Loading...
Searching...
No Matches
T_AthenaPoolCoolMultChanCnv.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_AthenaPoolCoolMultChanCnv.icc
6 * @brief This templated class provides the POOL converter to
7 * translate a DataVector<ELEM_T> to and from a CondAttrListCollection. In
8 * this case, the elements of T are written/read and their POOL
9 * tokens are stored in CondAttrListCollection.
10 * @author RD Schaffer <R.D.Schaffer@cern.ch>
11 **/
12
13#include "AthenaPoolCnvSvc/IAthenaPoolCnvSvc.h"
14#include "AthenaPoolUtilities/AthenaAttributeList.h"
15#include "AthenaPoolUtilities/CondAttrListCollection.h"
16#include "AthenaPoolUtilities/CondAttrListCollAddress.h"
17#include "AthenaPoolUtilities/CondMultChanCollection.h"
18
19#include "GaudiKernel/ClassID.h"
20#include "GaudiKernel/StatusCode.h"
21#include "GaudiKernel/MsgStream.h"
22
23#include "AthenaKernel/CLASS_DEF.h"
24#include "AthenaKernel/StorableConversions.h"
25
26#include "CxxUtils/checker_macros.h"
27
28#include <exception>
29#include <string>
30#include <format>
31
32//__________________________________________________________________________
33template <class COLL_T, class ELEM_T, class ELEM_P>
34T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::T_AthenaPoolCoolMultChanCnv(ISvcLocator* svcloc)
35 :
36 T_AthenaPoolCustCnv<COLL_T, ELEM_T>(svcloc)
37{
38 ATH_MSG_DEBUG("AthenaPool Converter Constructor for " << this->classID());
39}
40
41//__________________________________________________________________________
42template <class COLL_T, class ELEM_T, class ELEM_P>
43StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::createObj(IOpaqueAddress* pAddr, DataObject*& pObj)
44{
45 // This is the "read" method for a collection T (i.e. DataObject
46 // pObj) which contains objects of type T::value_type.
47 //
48 // There are two situations we must allow for:
49 //
50 // 1) When reading from COOL - the "standard production" scenario
51 // 2) When reading directly the collection from a pool file/db.
52 // This is used by "developers" who are testing their
53 // conditions objects
54 //
55 // For 1) the IOpaqueAddress contains a ptr to a
56 // CondAttrListCollection, and this contains tokens to each of the
57 // objects in the collection to be read.
58 //
59 // For 2) the IOpaqueAddress DOES NOT contain a ptr to a
60 // CondAttrListCollection, rather we simply use the collection
61 // token and read in the CondMultChanCollImpl and build a
62 // CondAttrListCollection
63 //
64
65 ATH_MSG_DEBUG("Read in objects for collection");
66
67 m_persCtx = pAddr->ipar()[0];
68
69 CondAttrListCollAddress* addr = dynamic_cast<CondAttrListCollAddress*>(pAddr);
70
71 std::unique_ptr<COLL_T> obj;
72 if (addr) {
73 // Successful cast - situation 1)
74
75 // Loop over tokens inside the CondAttrListCollection, read
76 // them in and add them to the data object.
77 CondAttrListCollection* coll = addr->attrListColl();
78 COLL_T* pobj = nullptr;
79 StatusCode sc = attrListCollToObject(coll, pobj);
80 obj = std::unique_ptr<COLL_T>(pobj);
81 if (sc != StatusCode::SUCCESS) {
82 ATH_MSG_ERROR("Unable to read in tokens from CondAttrListCollection");
83 return(StatusCode::FAILURE);
84 }
85 ATH_MSG_DEBUG("Created CondAttrListCollection from an CondAttrListCollAddress");
86 } else {
87 // Situation 2) - read in the CondMultChanCollImpl and build a
88 // CondAttrListCollection from the CondMultChanCollImpl
89 COLL_T* pobj = nullptr;
90 StatusCode sc = condMultChanCollImplToObject( *(pAddr->par()), pobj);
91 obj = std::unique_ptr<COLL_T>(pobj);
92 if (sc != StatusCode::SUCCESS) {
93 ATH_MSG_ERROR("Unable to read in CondMultChanCollImpl");
94 return(StatusCode::FAILURE);
95 }
96 ATH_MSG_DEBUG("Created CondAttrListCollection from an CondMultChanCollImpl");
97 }
98
99 // Initialize object after having been read in
100 StatusCode sc = obj->initialize();
101 if (sc != StatusCode::SUCCESS) {
102 ATH_MSG_ERROR("Unable to initialize object read in");
103 return(StatusCode::FAILURE);
104 }
105
106 // Convert to DataObject
107 pObj = SG::asStorable (std::move (obj));
108 if (!pObj) {
109 ATH_MSG_ERROR("Cannot get DataObject from COLL_T");
110 return(StatusCode::FAILURE);
111 }
112 ATH_MSG_DEBUG("End createObj");
113 return(StatusCode::SUCCESS);
114}
115
116//__________________________________________________________________________
117template <class COLL_T, class ELEM_T, class ELEM_P>
118StatusCode
119T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::objectToAttrListColl ATLAS_NOT_THREAD_SAFE
120 (COLL_T* obj, IOpaqueAddress*& pAddr,
121 CondAttrListCollection*& attrListColl,
122 std::unique_ptr<Token>& implToken)
123{
124 ATH_MSG_DEBUG("Creating a CondAttrListCollection from a collection");
125
126
127 attrListColl = new CondAttrListCollection(true); // set hasRunEventTime
128
129 // Make sure the channel vector is filled
130 if (obj->size() != obj->chan_size()) {
131 ATH_MSG_ERROR("Must fill in channel numbers! Number of objects: " << obj->size()
132 << " Number of channels: " << obj->chan_size());
133 return(StatusCode::FAILURE);
134 }
135
136 // Fill IOVs if they are there
137 bool hasIOVs = (obj->iov_size() == obj->size());
138
139 // Get the contained object in the COLL_T
140 CondMultChanCollImpl* impl = obj->implementation();
141
142 // Reset tokens in case this object was previously written out
143 impl->resetTokens();
144
145 // Loop over objects in COLL_T*
146 typename COLL_T::chan_const_iterator itChan = obj->chan_begin();
147 typename COLL_T::iov_const_iterator itIOV = obj->iov_begin();
148 std::string token_str;
149 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
150 for (unsigned int chan = 0; chan < obj->size(); ++chan, ++itChan) {
151 ELEM_T* elem = (*obj)[chan];
152 // Allow for T/P separation, convert to persistent object
153 ELEM_P* elem_p = this->createPersistent(elem);
154 std::unique_ptr<Token> token;
155 StatusCode sc = this->objectToPool(elem_p, token, "", *pAddr->par());
156 if (sc != StatusCode::SUCCESS || !token) {
157 ATH_MSG_ERROR("Unable to write out object");
158 return(StatusCode::FAILURE);
159 }
160 token_str = token->toString();
161
162 // Create a new AthenaAttributeList
163 AthenaAttributeList attrList;
164 attrList.extend("PoolRef","string");
165 attrList["PoolRef"].setValue( token_str );
166 attrListColl->add((*itChan), attrList);
167 if (hasIOVs) {
168 attrListColl->add((*itChan), (*itIOV));
169 ++itIOV;
170 }
171 ATH_MSG_DEBUG("Adding new attrList for token: " << token_str);
172
173 // Save as well in implementation
174 impl->add(token_str);
175 }
176
177 // Print out tokens
178 ATH_MSG_DEBUG("Print out tokens in implementaion:");
179 CondMultChanCollImpl::token_const_iterator itToken = impl->token_begin();
180 CondMultChanCollImpl::token_const_iterator itTokenEnd = impl->token_end();
181 CondMultChanCollImpl::chan_const_iterator itChan1 = impl->chan_begin();
182 for (; itToken != itTokenEnd; ++itToken, ++itChan1) {
183 ATH_MSG_DEBUG(*itToken);
184 ATH_MSG_DEBUG("Chan " << *itChan1);
185 }
186
187 StatusCode sc = this->objectToPool(impl, implToken, "", *pAddr->par());
188 if (sc != StatusCode::SUCCESS || !implToken) {
189 ATH_MSG_ERROR("Unable to write out CondMultChanCollImpl");
190 return(StatusCode::FAILURE);
191 }
192 ATH_MSG_DEBUG("Wrote out CondMultChanCollImpl - token: " << implToken->toString());
193
194 ATH_MSG_DEBUG("End objectToAttrListColl");
195 return(StatusCode::SUCCESS);
196}
197
198//__________________________________________________________________________
199template <class COLL_T, class ELEM_T, class ELEM_P>
200StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::createRep(DataObject* pObj, IOpaqueAddress*& pAddr)
201{
202 // This is the "write" method for a collection of COLL_T*
203 // (i.e. DataObject pObj). Each element of the collection is
204 // written out and the tokens are stored in a
205 // CondAttrListCollection.
206
207 ATH_MSG_DEBUG("Write out objects in collection");
208
209 COLL_T* obj = 0;
210 SG::fromStorable(pObj, obj);
211 if (!obj) {
212 ATH_MSG_ERROR("Unable to convert DataObject");
213 return(StatusCode::FAILURE);
214 }
215 CondAttrListCollection* coll = 0;
216 std::unique_ptr<Token> token;
217 // Ok, because it's just creating a new list.
218 StatusCode sc ATLAS_THREAD_SAFE = objectToAttrListColl(obj, pAddr, coll, token);
219 if (sc != StatusCode::SUCCESS || !token) {
220 ATH_MSG_ERROR("Unable to get objects and fill CondAttrListCollection with tokens");
221 return(StatusCode::FAILURE);
222 }
223 CondAttrListCollAddress* addr = new CondAttrListCollAddress(POOL_StorageType,
224 this->classID(),
225 token->toString());
226 addr->setAttrListColl(coll);
227 delete pAddr; pAddr = addr;
228 pAddr->addRef();
229
230 ATH_MSG_DEBUG("End createRep");
231 return(StatusCode::SUCCESS);
232}
233
234//__________________________________________________________________________
235template <class COLL_T, class ELEM_T, class ELEM_P>
236StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::fillRepRefs(IOpaqueAddress* /*pAddr*/, DataObject* /*pObj*/)
237{
238 ATH_MSG_DEBUG("End fillRepRefs");
239 return(StatusCode::SUCCESS);
240}
241
242//__________________________________________________________________________
243template <class COLL_T, class ELEM_T, class ELEM_P>
244StatusCode
245T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::attrListCollToObject(CondAttrListCollection* attrListColl,
246 COLL_T*& obj)
247{
248
249 ATH_MSG_DEBUG("Creating a collection from a CondAttrListCollection");
250
251 // Create collection
252 obj = new COLL_T();
253
254 // Check the sizes of objs and IOVs
255 if (attrListColl->size() != attrListColl->iov_size()) {
256 ATH_MSG_ERROR("CondAttrListCollection incorrect size for IOVs! "
257 << " Number of objects: " << attrListColl->size()
258 << " Number of IOVs: " << attrListColl->iov_size());
259 return(StatusCode::FAILURE);
260 }
261
262 /// Add the pointer to the CondAttrListCollection to COLL_T
263 /// object. This will allow subsequent addition of IOVRange
264 /// objects added to COLL_T to be propagated to the
265 /// CondAttrListCollection. This is needed for IOV registration
266 /// which may happen AFTER a read back of the COLL_T.
267 obj->implementation()->setAttrListColl(attrListColl);
268
269 // Loop over objects in COLL_T*
270 std::string token;
271 CondAttrListCollection::const_iterator it = attrListColl->begin();
272 CondAttrListCollection::const_iterator last = attrListColl->end();
273 CondAttrListCollection::iov_const_iterator itIOV = attrListColl->iov_begin();
274 for (; it != last; ++it, ++itIOV) {
275 try {
276 // pool token/ref
277 const coral::AttributeList& attrList = (*it).second;
278 token=attrList["PoolRef"].data<std::string>();
279 }
280 // FIXME exception
281 catch(const std::exception& x) {
282 ATH_MSG_ERROR("PoolRef not found in attribute list");
283 return(StatusCode::FAILURE);
284 }
285 // Allow T/P separation - set token and use createTransient
286 ELEM_T* elem {nullptr};
287 {
288 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
289 this->setToken( token );
290 elem = this->createTransient();
291 }
292 // Add elem, channel number and IOV
293 obj->push_back(elem);
294 obj->add((*it).first);
295 obj->add((*itIOV).second);
296
297 ATH_MSG_DEBUG("Read in new object for token: " << token);
298
299 }
300
301 ATH_MSG_DEBUG("End attrListCollToObject");
302 return(StatusCode::SUCCESS);
303}
304
305/// Read in CondMultChanCollImpl and the objects for its tokens,
306/// saving them in the output collection
307/// @param collImpl [IN] CondMultChanCollImpl token
308/// @param obj [OUT] pointer to the collection of objects.
309template <class COLL_T, class ELEM_T, class ELEM_P>
310StatusCode
311T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::condMultChanCollImplToObject(const std::string& collImplToken,
312 COLL_T*& obj)
313{
314
315 ATH_MSG_DEBUG("Creating a collection from a CondMultChanCollImpl for token");
316
317 // Create collection
318 obj = new COLL_T();
319 ELEM_T* elem = 0;
320
321 // Read in the CondMultChanCollImpl
322 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
323 CondMultChanCollImpl* impl = 0;
324 this->setToken(collImplToken);
325 StatusCode sc = this->poolToObject(this->m_i_poolToken, impl);
326 if (sc != StatusCode::SUCCESS) {
327 ATH_MSG_ERROR("Unable to read in CondMultChanCollImpl");
328 return(StatusCode::FAILURE);
329 }
330
331 // Make sure the channel vector is filled
332 if (impl->token_size() != impl->chan_size()) {
333 ATH_MSG_ERROR("Token and channel vectors are not the same size! Number of tokens: " << impl->token_size()
334 << " Number of channels: " << impl->chan_size());
335 return(StatusCode::FAILURE);
336 }
337
338 // Fill IOVs if they are there
339 bool hasIOVs = (impl->iov_size() == impl->token_size());
340
341 // Loop over tokens in Impl and retrieve objects
342 CondMultChanCollImpl::chan_const_iterator itChan = impl->chan_begin();
343 CondMultChanCollImpl::iov_const_iterator itIOV = impl->iov_begin();
344 CondMultChanCollImpl::token_const_iterator itToken = impl->token_begin();
345 for (unsigned int i = 0; i < impl->chan_size(); ++i, ++itChan, ++itIOV, ++itToken) {
346
347 // Allow T/P separation - set token and use createTransient
348 this->setToken( *itToken );
349 elem = this->createTransient();
350
351 // Add elem, channel number and IOV
352 obj->push_back(elem);
353 obj->add(*itChan);
354 if (hasIOVs)obj->add(*itIOV);
355
356 ATH_MSG_DEBUG("Read in new object for token: " << *itToken);
357 }
358
359 // Now remove impl
360 delete impl;
361
362 ATH_MSG_DEBUG("End condMultChanCollImplToObject");
363 return(StatusCode::SUCCESS);
364}
365
366/// Dummy methods not needed here
367//__________________________________________________________________________
368template <class COLL_T, class ELEM_T, class ELEM_P>
369inline
370StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::transToPers(COLL_T* /*obj*/, ELEM_T*& /*persObj*/)
371{
372 return(StatusCode::SUCCESS);
373}
374
375//__________________________________________________________________________
376template <class COLL_T, class ELEM_T, class ELEM_P>
377inline
378StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::persToTrans(COLL_T*& /*transObj*/, ELEM_T* /*obj*/)
379{
380 return(StatusCode::SUCCESS);
381}
382
383//__________________________________________________________________________
384// Read object of type P. This is an exception-throwing version of poolToObject()
385// plus reading of all extending objects
386template <class COLL_T, class ELEM_T, class ELEM_P>
387template <class P>
388inline
389P* T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::poolReadObject() {
390 P* persObj = 0;
391 if( this->poolToObject( this->m_i_poolToken , persObj ).isFailure() ) {
392 throw std::runtime_error("POOL read failed");
393 }
394 return(persObj);
395}
396
397//__________________________________________________________________________
398// Read object of type P. This is an exception-throwing version of poolToObject()
399// plus reading of all extending objects
400template <class COLL_T, class ELEM_T, class ELEM_P>
401inline
402ELEM_T* T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::poolReadObject() {
403 ELEM_T* persObj = 0;
404 if( this->poolToObject( this->m_i_poolToken , persObj ).isFailure() ) {
405 throw std::runtime_error("POOL read failed");
406 }
407 return(persObj);
408}
409
410//__________________________________________________________________________
411template <class COLL_T, class ELEM_T, class ELEM_P>
412ELEM_P* T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::createPersistent(ELEM_T* tobj)
413{
414 // Default implementation - ELEM_T == ELEM_P so just return input
415 ELEM_P* obj = dynamic_cast<ELEM_P*>(tobj);
416 return(obj);
417}
418
419//__________________________________________________________________________
420template <class COLL_T, class ELEM_T, class ELEM_P>
421ELEM_T* T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::createTransient()
422{
423 // Default version - no T/P separation. We read in transient
424 // object
425 //ELEM_T* elem = 0;
426 ELEM_T* elem = this->poolReadObject();
427 return(elem);
428}
429
430//__________________________________________________________________________
431/// specialized version that adds persistency contextID to tokens (for reading)
432template <class COLL_T, class ELEM_T, class ELEM_P>
433void
434T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::
435setToken (const std::string& token)
436{
437 char context[32];
438 const std::string contextStr = std::format("[CTXT={:08X}]", m_persCtx);
439 std::strncpy(context, contextStr.c_str(), sizeof(context) - 1);
440 context[sizeof(context) - 1] = '\0';
441 T_AthenaPoolCustCnv<COLL_T, ELEM_T>::setToken( token + context );
442}