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