2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
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>
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"
19 #include "GaudiKernel/ClassID.h"
20 #include "GaudiKernel/StatusCode.h"
21 #include "GaudiKernel/MsgStream.h"
23 #include "AthenaKernel/CLASS_DEF.h"
24 #include "AthenaKernel/StorableConversions.h"
26 #include "CxxUtils/checker_macros.h"
31 //__________________________________________________________________________
32 template <class COLL_T, class ELEM_T, class ELEM_P>
33 T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::T_AthenaPoolCoolMultChanCnv(ISvcLocator* svcloc)
35 T_AthenaPoolCustCnv<COLL_T, ELEM_T>(svcloc)
37 ATH_MSG_DEBUG("AthenaPool Converter Constructor for " << this->classID());
40 //__________________________________________________________________________
41 template <class COLL_T, class ELEM_T, class ELEM_P>
42 StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::createObj(IOpaqueAddress* pAddr, DataObject*& pObj)
44 // This is the "read" method for a collection T (i.e. DataObject
45 // pObj) which contains objects of type T::value_type.
47 // There are two situations we must allow for:
49 // 1) When reading from COOL - the "standard production" scenario
50 // 2) When reading directly the collection from a pool file/db.
51 // This is used by "developers" who are testing their
54 // For 1) the IOpaqueAddress contains a ptr to a
55 // CondAttrListCollection, and this contains tokens to each of the
56 // objects in the collection to be read.
58 // For 2) the IOpaqueAddress DOES NOT contain a ptr to a
59 // CondAttrListCollection, rather we simply use the collection
60 // token and read in the CondMultChanCollImpl and build a
61 // CondAttrListCollection
64 ATH_MSG_DEBUG("Read in objects for collection");
66 m_persCtx = pAddr->ipar()[0];
68 CondAttrListCollAddress* addr = dynamic_cast<CondAttrListCollAddress*>(pAddr);
70 std::unique_ptr<COLL_T> obj;
72 // Successful cast - situation 1)
74 // Loop over tokens inside the CondAttrListCollection, read
75 // them in and add them to the data object.
76 CondAttrListCollection* coll = addr->attrListColl();
77 COLL_T* pobj = nullptr;
78 StatusCode sc = attrListCollToObject(coll, pobj);
79 obj = std::unique_ptr<COLL_T>(pobj);
80 if (sc != StatusCode::SUCCESS) {
81 ATH_MSG_ERROR("Unable to read in tokens from CondAttrListCollection");
82 return(StatusCode::FAILURE);
84 ATH_MSG_DEBUG("Created CondAttrListCollection from an CondAttrListCollAddress");
86 // Situation 2) - read in the CondMultChanCollImpl and build a
87 // CondAttrListCollection from the CondMultChanCollImpl
88 COLL_T* pobj = nullptr;
89 StatusCode sc = condMultChanCollImplToObject( *(pAddr->par()), pobj);
90 obj = std::unique_ptr<COLL_T>(pobj);
91 if (sc != StatusCode::SUCCESS) {
92 ATH_MSG_ERROR("Unable to read in CondMultChanCollImpl");
93 return(StatusCode::FAILURE);
95 ATH_MSG_DEBUG("Created CondAttrListCollection from an CondMultChanCollImpl");
98 // Initialize object after having been read in
99 StatusCode sc = obj->initialize();
100 if (sc != StatusCode::SUCCESS) {
101 ATH_MSG_ERROR("Unable to initialize object read in");
102 return(StatusCode::FAILURE);
105 // Convert to DataObject
106 pObj = SG::asStorable (std::move (obj));
108 ATH_MSG_ERROR("Cannot get DataObject from COLL_T");
109 return(StatusCode::FAILURE);
111 ATH_MSG_DEBUG("End createObj");
112 return(StatusCode::SUCCESS);
115 //__________________________________________________________________________
116 template <class COLL_T, class ELEM_T, class ELEM_P>
118 T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::objectToAttrListColl ATLAS_NOT_THREAD_SAFE
119 (COLL_T* obj, IOpaqueAddress*& pAddr,
120 CondAttrListCollection*& attrListColl,
121 std::unique_ptr<Token>& implToken)
123 ATH_MSG_DEBUG("Creating a CondAttrListCollection from a collection");
126 attrListColl = new CondAttrListCollection(true); // set hasRunEventTime
128 // Make sure the channel vector is filled
129 if (obj->size() != obj->chan_size()) {
130 ATH_MSG_ERROR("Must fill in channel numbers! Number of objects: " << obj->size()
131 << " Number of channels: " << obj->chan_size());
132 return(StatusCode::FAILURE);
135 // Fill IOVs if they are there
136 bool hasIOVs = (obj->iov_size() == obj->size());
138 // Get the contained object in the COLL_T
139 CondMultChanCollImpl* impl = obj->implementation();
141 // Reset tokens in case this object was previously written out
144 // Loop over objects in COLL_T*
145 typename COLL_T::chan_const_iterator itChan = obj->chan_begin();
146 typename COLL_T::iov_const_iterator itIOV = obj->iov_begin();
147 std::string token_str;
148 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
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);
159 token_str = token->toString();
161 // Create a new AthenaAttributeList
162 AthenaAttributeList attrList;
163 attrList.extend("PoolRef","string");
164 attrList["PoolRef"].setValue( token_str );
165 attrListColl->add((*itChan), attrList);
167 attrListColl->add((*itChan), (*itIOV));
170 ATH_MSG_DEBUG("Adding new attrList for token: " << token_str);
172 // Save as well in implementation
173 impl->add(token_str);
177 ATH_MSG_DEBUG("Print out tokens in implementaion:");
178 CondMultChanCollImpl::token_const_iterator itToken = impl->token_begin();
179 CondMultChanCollImpl::token_const_iterator itTokenEnd = impl->token_end();
180 CondMultChanCollImpl::chan_const_iterator itChan1 = impl->chan_begin();
181 for (; itToken != itTokenEnd; ++itToken, ++itChan1) {
182 ATH_MSG_DEBUG(*itToken);
183 ATH_MSG_DEBUG("Chan " << *itChan1);
186 StatusCode sc = this->objectToPool(impl, implToken, "", *pAddr->par());
187 if (sc != StatusCode::SUCCESS || !implToken) {
188 ATH_MSG_ERROR("Unable to write out CondMultChanCollImpl");
189 return(StatusCode::FAILURE);
191 ATH_MSG_DEBUG("Wrote out CondMultChanCollImpl - token: " << implToken->toString());
193 ATH_MSG_DEBUG("End objectToAttrListColl");
194 return(StatusCode::SUCCESS);
197 //__________________________________________________________________________
198 template <class COLL_T, class ELEM_T, class ELEM_P>
199 StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::createRep(DataObject* pObj, IOpaqueAddress*& pAddr)
201 // This is the "write" method for a collection of COLL_T*
202 // (i.e. DataObject pObj). Each element of the collection is
203 // written out and the tokens are stored in a
204 // CondAttrListCollection.
206 ATH_MSG_DEBUG("Write out objects in collection");
209 SG::fromStorable(pObj, obj);
211 ATH_MSG_ERROR("Unable to convert DataObject");
212 return(StatusCode::FAILURE);
214 CondAttrListCollection* coll = 0;
215 std::unique_ptr<Token> token;
216 // Ok, because it's just creating a new list.
217 StatusCode sc ATLAS_THREAD_SAFE = objectToAttrListColl(obj, pAddr, coll, token);
218 if (sc != StatusCode::SUCCESS || !token) {
219 ATH_MSG_ERROR("Unable to get objects and fill CondAttrListCollection with tokens");
220 return(StatusCode::FAILURE);
222 CondAttrListCollAddress* addr = new CondAttrListCollAddress(POOL_StorageType,
225 addr->setAttrListColl(coll);
226 delete pAddr; pAddr = addr;
229 ATH_MSG_DEBUG("End createRep");
230 return(StatusCode::SUCCESS);
233 //__________________________________________________________________________
234 template <class COLL_T, class ELEM_T, class ELEM_P>
235 StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::fillRepRefs(IOpaqueAddress* /*pAddr*/, DataObject* /*pObj*/)
237 ATH_MSG_DEBUG("End fillRepRefs");
238 return(StatusCode::SUCCESS);
241 //__________________________________________________________________________
242 template <class COLL_T, class ELEM_T, class ELEM_P>
244 T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::attrListCollToObject(CondAttrListCollection* attrListColl,
248 ATH_MSG_DEBUG("Creating a collection from a CondAttrListCollection");
253 // Check the sizes of objs and IOVs
254 if (attrListColl->size() != attrListColl->iov_size()) {
255 ATH_MSG_ERROR("CondAttrListCollection incorrect size for IOVs! "
256 << " Number of objects: " << attrListColl->size()
257 << " Number of IOVs: " << attrListColl->iov_size());
258 return(StatusCode::FAILURE);
261 /// Add the pointer to the CondAttrListCollection to COLL_T
262 /// object. This will allow subsequent addition of IOVRange
263 /// objects added to COLL_T to be propagated to the
264 /// CondAttrListCollection. This is needed for IOV registration
265 /// which may happen AFTER a read back of the COLL_T.
266 obj->implementation()->setAttrListColl(attrListColl);
268 // Loop over objects in COLL_T*
270 CondAttrListCollection::const_iterator it = attrListColl->begin();
271 CondAttrListCollection::const_iterator last = attrListColl->end();
272 CondAttrListCollection::iov_const_iterator itIOV = attrListColl->iov_begin();
273 for (; it != last; ++it, ++itIOV) {
276 const coral::AttributeList& attrList = (*it).second;
277 token=attrList["PoolRef"].data<std::string>();
280 catch(const std::exception& x) {
281 ATH_MSG_ERROR("PoolRef not found in attribute list");
282 return(StatusCode::FAILURE);
284 // Allow T/P separation - set token and use createTransient
285 ELEM_T* elem {nullptr};
287 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
288 this->setToken( token );
289 elem = this->createTransient();
291 // Add elem, channel number and IOV
292 obj->push_back(elem);
293 obj->add((*it).first);
294 obj->add((*itIOV).second);
296 ATH_MSG_DEBUG("Read in new object for token: " << token);
300 ATH_MSG_DEBUG("End attrListCollToObject");
301 return(StatusCode::SUCCESS);
304 /// Read in CondMultChanCollImpl and the objects for its tokens,
305 /// saving them in the output collection
306 /// @param collImpl [IN] CondMultChanCollImpl token
307 /// @param obj [OUT] pointer to the collection of objects.
308 template <class COLL_T, class ELEM_T, class ELEM_P>
310 T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::condMultChanCollImplToObject(const std::string& collImplToken,
314 ATH_MSG_DEBUG("Creating a collection from a CondMultChanCollImpl for token");
320 // Read in the CondMultChanCollImpl
321 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
322 CondMultChanCollImpl* impl = 0;
323 this->setToken(collImplToken);
324 StatusCode sc = this->poolToObject(this->m_i_poolToken, impl);
325 if (sc != StatusCode::SUCCESS) {
326 ATH_MSG_ERROR("Unable to read in CondMultChanCollImpl");
327 return(StatusCode::FAILURE);
330 // Make sure the channel vector is filled
331 if (impl->token_size() != impl->chan_size()) {
332 ATH_MSG_ERROR("Token and channel vectors are not the same size! Number of tokens: " << impl->token_size()
333 << " Number of channels: " << impl->chan_size());
334 return(StatusCode::FAILURE);
337 // Fill IOVs if they are there
338 bool hasIOVs = (impl->iov_size() == impl->token_size());
340 // Loop over tokens in Impl and retrieve objects
341 CondMultChanCollImpl::chan_const_iterator itChan = impl->chan_begin();
342 CondMultChanCollImpl::iov_const_iterator itIOV = impl->iov_begin();
343 CondMultChanCollImpl::token_const_iterator itToken = impl->token_begin();
344 for (unsigned int i = 0; i < impl->chan_size(); ++i, ++itChan, ++itIOV, ++itToken) {
346 // Allow T/P separation - set token and use createTransient
347 this->setToken( *itToken );
348 elem = this->createTransient();
350 // Add elem, channel number and IOV
351 obj->push_back(elem);
353 if (hasIOVs)obj->add(*itIOV);
355 ATH_MSG_DEBUG("Read in new object for token: " << *itToken);
361 ATH_MSG_DEBUG("End condMultChanCollImplToObject");
362 return(StatusCode::SUCCESS);
365 /// Dummy methods not needed here
366 //__________________________________________________________________________
367 template <class COLL_T, class ELEM_T, class ELEM_P>
369 StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::transToPers(COLL_T* /*obj*/, ELEM_T*& /*persObj*/)
371 return(StatusCode::SUCCESS);
374 //__________________________________________________________________________
375 template <class COLL_T, class ELEM_T, class ELEM_P>
377 StatusCode T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::persToTrans(COLL_T*& /*transObj*/, ELEM_T* /*obj*/)
379 return(StatusCode::SUCCESS);
382 //__________________________________________________________________________
383 // Read object of type P. This is an exception-throwing version of poolToObject()
384 // plus reading of all extending objects
385 template <class COLL_T, class ELEM_T, class ELEM_P>
388 P* T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::poolReadObject() {
390 if( this->poolToObject( this->m_i_poolToken , persObj ).isFailure() ) {
391 throw std::runtime_error("POOL read failed");
396 //__________________________________________________________________________
397 // Read object of type P. This is an exception-throwing version of poolToObject()
398 // plus reading of all extending objects
399 template <class COLL_T, class ELEM_T, class ELEM_P>
401 ELEM_T* T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::poolReadObject() {
403 if( this->poolToObject( this->m_i_poolToken , persObj ).isFailure() ) {
404 throw std::runtime_error("POOL read failed");
409 //__________________________________________________________________________
410 template <class COLL_T, class ELEM_T, class ELEM_P>
411 ELEM_P* T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::createPersistent(ELEM_T* tobj)
413 // Default implementation - ELEM_T == ELEM_P so just return input
414 ELEM_P* obj = dynamic_cast<ELEM_P*>(tobj);
418 //__________________________________________________________________________
419 template <class COLL_T, class ELEM_T, class ELEM_P>
420 ELEM_T* T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::createTransient()
422 // Default version - no T/P separation. We read in transient
425 ELEM_T* elem = this->poolReadObject();
429 //__________________________________________________________________________
430 /// specialized version that adds persistency contextID to tokens (for reading)
431 template <class COLL_T, class ELEM_T, class ELEM_P>
433 T_AthenaPoolCoolMultChanCnv<COLL_T, ELEM_T, ELEM_P>::
434 setToken (const std::string& token)
437 ::sprintf(context, "[CTXT=%08X]", m_persCtx);
438 T_AthenaPoolCustCnv<COLL_T, ELEM_T>::setToken( token + context );