ATLAS Offline Software
L1CaloCondSvc.icc
Go to the documentation of this file.
1 // -*- C++ -*-
2 
3 /*
4  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 #ifndef TRIGT1CALOCONDSVC_L1CALOCONDSVC_ICC
8 #define TRIGT1CALOCONDSVC_L1CALOCONDSVC_ICC
9 
10 #include "AthenaKernel/IOVRange.h"
11 #include "AthenaKernel/StorableConversions.h"
12 
13 #include "AthenaPoolUtilities/AthenaAttributeList.h"
14 #include "AthenaPoolUtilities/CondAttrListCollection.h"
15 
16 #include <iostream>
17 
18 #include "CxxUtils/checker_macros.h"
19 ATLAS_NO_CHECK_FILE_THREAD_SAFETY; // obsolete, replaced by L1CaloCondAlg
20 
21 template <typename T>
22 StatusCode L1CaloCondSvc::store(const T*& pobj, const std::string& key, const std::string& folder, const std::string& tag) const {
23  /* ======================================================================
24  The object pobj must implement the IL1CaloPersistenceCapable interface
25  ====================================================================== */
26 
27  ATH_MSG_VERBOSE( "*** L1CaloCondSvc::store() ***" );
28  ATH_MSG_VERBOSE(key <<" "<< folder <<" "<< tag );
29 
30  // create persistent object (either AthenaAttributeList or CondAttrListCollection) from the transient one
31  // the new object is not registered in the TDS
32  ATH_MSG_VERBOSE( "*** pobj->makePersistent() ***" );
33  DataObject* newConditions = pobj->makePersistent();
34 
35  // Declare a pointer to point to the final CondAttrListCollection (or AthenaAttributeList)
36  // containing the updated conditions merged with the old ones from COOL
37  DataObject* finalConditions = 0;
38 
39  // Setting up a new IOV range
40  IOVTime start, end;
41 
42  if(m_bUseTimeStamp) {
43  start = IOVTime(m_iovBeginTime);
44  end = IOVTime(m_iovEndTime);
45  } else {
46  start = IOVTime(m_iovBeginRun, m_iovBeginLB);
47  end = IOVTime(m_iovEndRun, m_iovEndLB);
48  }
49 
50  // range is used later to setup the IOV range of the updated conditions
51  IOVRange range(start, end);
52 
53  ATH_MSG_VERBOSE( "*** get old conditions ***" );
54  if(newConditions) {
55 
56  std::string conditionType = pobj->conditionType();
57  if(conditionType=="CondAttrListCollection") {
58 
59  // cast pobj to a CondAttrListCollection
60  CondAttrListCollection* attrListCollection = dynamic_cast<CondAttrListCollection*>(newConditions);
61  if (!attrListCollection) {
62  ATH_MSG_ERROR( "Could not cast to CondAttrListCollection" );
63  return StatusCode::FAILURE;
64  }
65 
66  if(m_bWriteNewChannels) {
67  ATH_MSG_VERBOSE( "*** m_bWriteNewChannels TRUE ***" );
68 
69  // New channels can only be written to cool is their AttributeList match exactly the destination folder one
70  // OR if the channels are written to a empty new folder.
71  // In such a case there is no need to do any merging as all attributes in the destination folder are defined.
72 
73  CondAttrListCollection* newAttrListCollection = new CondAttrListCollection(!m_bUseTimeStamp);
74 
75  CondAttrListCollection::const_iterator it_attrList = attrListCollection->begin();
76  for(;it_attrList!=attrListCollection->end();++it_attrList) {
77  CondAttrListCollection::ChanNum channelNumber = it_attrList->first;
78  const CondAttrListCollection::AttributeList& attrList = it_attrList->second;
79 
80  newAttrListCollection->add(channelNumber, attrList);
81  newAttrListCollection->add(channelNumber, range);
82  }
83 
84  ATH_CHECK( m_detStore->record(newAttrListCollection, key) );
85 
86  } else {
87 
88  ATH_MSG_VERBOSE( "*** m_bWriteNewChannels FALSE ***" );
89 
90  // In this case we are updating a subset of channel attributes from an already filled cool folder
91  // The non-defined attributes information is retrieved from COOL, so All channels that will be updated must already exist
92  // in the source COOL folder
93 
94  // Now we retrieve the latest valid CondAttrListCollection (the full folder) from the TES or from COOL (if not already in the TES)
95  const CondAttrListCollection* pConstCOOLCondAttrListCollection = 0;
96  ATH_CHECK( m_detStore->retrieve(pConstCOOLCondAttrListCollection, key) );
97 
98  // create a new CondAttrListCollection to merge the new data from attrListCollection with the old ones from pConstCOOLCondAttrListCollection
99  // CondAttrListCollection(false) will use TimeStamp
100  // CondAttrListCollection(true) will use Run/Lumi blocks
101  CondAttrListCollection* mergedAttrListCollection = new CondAttrListCollection(!m_bUseTimeStamp);
102 
103  // do the merging
104  // only the channels present in attrListCollection are copied & merged to the new CondAttrListCollection
105  // so non-updated channels will not be recorded to COOL
106 
107  CondAttrListCollection::const_iterator it_attrList = attrListCollection->begin();
108  for(;it_attrList!=attrListCollection->end();++it_attrList) {
109  CondAttrListCollection::ChanNum channelNumber = it_attrList->first;
110  const CondAttrListCollection::AttributeList& attrList = it_attrList->second;
111 
112  CondAttrListCollection::const_iterator it_coolAttrList = pConstCOOLCondAttrListCollection->chanAttrListPair(channelNumber);
113  if(it_coolAttrList!=pConstCOOLCondAttrListCollection->end()) {
114  // a corresponding channel is already defined in the COOL folder
115  // the new attributes are merged with the old ones
116  //CondAttrListCollection::AttributeList* coolAttrList = new CondAttrListCollection::AttributeList(it_coolAttrList->second);
117  CondAttrListCollection::AttributeList coolAttrList;
118  coolAttrList.merge(it_coolAttrList->second);
119  coolAttrList.merge(attrList);
120 
121  mergedAttrListCollection->add(channelNumber, coolAttrList);
122  mergedAttrListCollection->add(channelNumber, range);
123 
124  } else {
125  // the current channel does not exist in the COOL folder -> 2 cases
126  ATH_MSG_WARNING( "Trying to update channel "<< channelNumber << ", which does not already exist in the COOL folder for the specified IOV (WriteNewChannel is switched off)");
127 
128  /*
129  if(m_bWriteNewChannels) {
130  // if ALL the COOL attributes are defined/updated by the transient object we can add this new channel to the new collection to be stored in COOL
131  // (this is the case when populating a new folder from scratch)
132  mergedAttrListCollection->add(channelNumber, attrList);
133  mergedAttrListCollection->add(channelNumber, range);
134  } else {
135  // the transient object only defines/updates a subset of the COOL folder attributes.
136  // (ie we are adding a new channel to an already filled folder)
137  // We don't know how to initialize the other attribute, so this channel is not added to the new collection to be stored in COOL
138  ATH_MSG_WARNING(g to update channel "<< channelNumber << ", which does not already exist in the COOL folder (WriteNewChannel is switched off)");
139  }
140  */
141  }
142  }
143 
144  finalConditions = SG::asStorable(mergedAttrListCollection);
145 
146  //-------------------------------------------
147  // replace the 'old' collection retrieved from COOL by the one updated with new attributes values
148 
149  //retrieve the proxy of the CondAttrListCollection retrieved from COOL
150  SG::DataProxy* proxy = m_detStore->proxy(m_detStore->clid(key), key);
151 
152  // we reset the proxy to delete the old conditions
153  proxy->reset();
154 
155  // we add the new updated conditions to the proxy
156  proxy->setObject(finalConditions);
157 
158  }
159  /*
160  ATH_MSG_INFO("====================================================================================================" );
161  it_attrList = mergedAttrListCollection->begin();
162  for(;it_attrList!=mergedAttrListCollection->end();++it_attrList) {
163  CondAttrListCollection::ChanNum channelNumber = it_attrList->first;
164  CondAttrListCollection::AttributeList attrList = it_attrList->second;
165  //log<<MSG::INFO<<"atributeList : "<<attrList.toOutputStream(log)<<endmsg;
166  std::cout <<channelNumber<<" "<< attrList.toOutputStream(std::cout) <<std::endl;
167  }
168  */
169 
170  } else if(conditionType=="AthenaAttributeList") {
171  /*
172  AthenaAttributeList* attributeList = dynamic_cast<AthenaAttributeList*>(newConditions);
173 
174  // Now we retrieve the latest valid CondAttrListCollection (the full folder) from the TES or from COOL (if not already in the TES)
175  const AthenaAttributeList* pConstCOOLAthenaAttributeList = 0;
176  ATH_CHECK( m_detStore->retrieve(pConstCOOLAthenaAttributeList, key) );
177 
178  // create a new CondAttrListCollection to merge the new data from attrListCollection with the old ones from pConstCOOLCondAttrListCollection
179  AthenaAttributeList* mergedAthenaAttributeList = new AthenaAttributeList(*pConstCOOLAthenaAttributeList);
180  mergedAthenaAttributeList->merge(*attributeList);
181 
182  finalConditions = SG::asStorable(mergedAthenaAttributeList);
183  */
184 
185  } else {
186  ATH_MSG_ERROR( "Condition type " << conditionType<< "not recognized by L1CaloCondSvc" );
187  return StatusCode::FAILURE;
188  }
189 
190 
191 
192  //-------------------------------------------
193  // register attrListCollection to IOVDB
194  if(m_bUseTimeStamp) {
195  ATH_MSG_DEBUG( "use timestamp" );
196  ATH_CHECK( m_regSvc->registerIOV(pobj->conditionType(), key, folder, tag, m_iovBeginTime, m_iovEndTime) );
197  } else {
198  ATH_MSG_DEBUG( "use run/lumi" );
199  ATH_CHECK( m_regSvc->registerIOV(pobj->conditionType(), key, folder, tag, m_iovBeginRun, m_iovEndRun, m_iovBeginLB, m_iovEndLB) );
200  }
201 
202 
203  ATH_MSG_DEBUG( "Registered "<< pobj->conditionType() <<" to condition DB in folder "<< folder <<" with tag " << tag );
204 
205  } else {
206  ATH_MSG_ERROR( "Could not create persistant collection");
207  return StatusCode::FAILURE;
208  }
209 
210  return StatusCode::SUCCESS;
211 }
212 
213 template <typename T>
214 StatusCode L1CaloCondSvc::retrieve( T*& pobj, const std::string& key /*= ""*/) {
215  /* ======================================================================
216  The object pobj must implement the IL1CaloPersistenceCapable interface
217  ====================================================================== */
218  ATH_MSG_VERBOSE( "*** L1CaloCondSvc::retrieve() ***" );
219  ATH_MSG_VERBOSE( " -> Key: "<< key );
220 
221  if (m_detStore->contains<T>(key)) {
222  ATH_MSG_DEBUG( "Container already existing in DetStore with key:"<< key );
223  ATH_CHECK( m_detStore->retrieve(pobj, key) );
224  return StatusCode::SUCCESS;
225  }
226 
227  ATH_MSG_DEBUG( "Container not found in DetStore. Trying to retrieve it from the condition DB.");
228 
229  pobj = new T;
230  if(!pobj) {
231  ATH_MSG_ERROR( "Could not create transient container" );
232  return StatusCode::FAILURE;
233  }
234 
235  return this->retrieveImpl(pobj, key);
236 }
237 
238 template <typename T, typename FolderMapping>
239 StatusCode L1CaloCondSvc::retrieve(T*& pobj, const FolderMapping& folderKeyMap, const std::string& key /*= ""*/) {
240  /* ======================================================================
241  The object pobj must implement the IL1CaloPersistenceCapable interface
242  ====================================================================== */
243  ATH_MSG_VERBOSE( "*** L1CaloCondSvc::retrieve() ***" );
244  ATH_MSG_VERBOSE( " -> Key: "<< key );
245 
246  if (m_detStore->contains<T>(key)) {
247  ATH_MSG_DEBUG( "Container already existing in DetStore with key:"<< key );
248  ATH_CHECK( m_detStore->retrieve(pobj, key) );
249  return StatusCode::SUCCESS;
250  }
251 
252  ATH_MSG_DEBUG( "Container not found in DetStore. Trying to retrieve it from the condition DB.");
253 
254  pobj = new T(folderKeyMap);
255  if(!pobj) {
256  ATH_MSG_ERROR( "Could not create transient container" );
257  return StatusCode::FAILURE;
258  }
259 
260  return this->retrieveImpl(pobj, key);
261 }
262 
263 
264 template <typename T>
265 StatusCode L1CaloCondSvc::retrieveImpl( T*& pobj, const std::string& key) {
266  // common parts of the two public retrieve methods. pobj must be a valid object.
267  ATH_MSG_VERBOSE( "*** L1CaloCondSvc::retrieveImpl() ***" );
268  ATH_MSG_VERBOSE( " -> Key: "<< key );
269 
270  // store objects without key.
271  // contains<T>("") somehow returns false as soon as more than one object is stored
272  // and none of them has key ""
273  // std::string sgKey;
274  // if(key=="") {
275  // //if no key is provided, the default object's key, which should be the COOL folder path, is taken.
276  // //coolKey = pobj->storeGateKey();
277  // sgKey = pobj->coolOutputKey();
278  // } else {
279  // sgKey = key;
280  // }
281 
282  //sc = this->registerCondition(coolKey, pobj);
283  ATH_CHECK( this->registerCondition(pobj,key) );
284 
285  //register object to storegate
286  ATH_CHECK( m_detStore->record(pobj, key) );
287  ATH_MSG_DEBUG( "Stored Container in DetStore, key: "<< key );
288  return StatusCode::SUCCESS;
289 }
290 
291 template <typename T>
292 StatusCode L1CaloCondSvc::registerCondition(T*& pObj, const std::string& mykey) {
293  ATH_MSG_DEBUG( "L1CaloCondSvc::registerCondition(T*& pObj))" );
294  ATH_MSG_DEBUG( " -> Specified key: "<< mykey );
295  if(!pObj) {
296  ATH_MSG_ERROR( "IL1CaloPersistenceCapable* pObj is NULL in L1CaloCondSvc::registerCondition()" );
297  return StatusCode::FAILURE;
298  }
299 
300  std::string conditionType = pObj->conditionType();
301 
302  if(conditionType=="CondAttrListCollection") {
303 
304  // we retrieve the keys (ie cool folder paths) needed by the condition object
305  std::vector<std::string> vCoolInputKeys = pObj->coolInputKeys();
306 
307  // Check if we specified some new key
308  // Used for L1Calo Overlay where we have both data and MC databases
309 
310  // Update for PprChanCalib
311  if (!mykey.empty() && mykey.find("PprChanCalib")!=std::string::npos){
312  ATH_MSG_INFO("Overriding default keys for PprChanCalib that were:");
313  for (auto it=vCoolInputKeys.begin();it!=vCoolInputKeys.end();++it) {ATH_MSG_INFO(*it);}
314  //Now set to specified key only
315  vCoolInputKeys.clear(); vCoolInputKeys.push_back(mykey);
316  }
317 
318  // Update for PprChanDefaults
319  if (!mykey.empty() && mykey.find("PprChanDefaults")!=std::string::npos){
320  ATH_MSG_INFO("Overriding default keys for PprChanDefaults that were:");
321  for (auto it=vCoolInputKeys.begin();it!=vCoolInputKeys.end();++it) {ATH_MSG_INFO(*it);}
322  //Now set to specified key only
323  vCoolInputKeys.clear(); vCoolInputKeys.push_back(mykey);
324  }
325 
326  // Update for DisabledTowers
327  if (!mykey.empty() && mykey.find("DisabledTowers")!=std::string::npos){
328  ATH_MSG_INFO("Overriding default keys for DisabledTowers that were:");
329  for (auto it=vCoolInputKeys.begin();it!=vCoolInputKeys.end();++it) {ATH_MSG_INFO(*it);}
330  //Now set to specified key only
331  vCoolInputKeys.clear(); vCoolInputKeys.push_back(mykey);
332  }
333 
334  // Update for PpmDeadChannels
335  if (!mykey.empty() && mykey.find("PpmDeadChannels")!=std::string::npos){
336  ATH_MSG_INFO("Overriding default keys for PpmDeadChannels that were:");
337  for (auto it=vCoolInputKeys.begin();it!=vCoolInputKeys.end();++it) {ATH_MSG_INFO(*it);}
338  //Now set to specified key only
339  vCoolInputKeys.clear(); vCoolInputKeys.push_back(mykey);
340  }
341 
342  //Check if we specified some new key
343 
344  // Update for PprChanCalib
345  if (!mykey.empty() && mykey.find("PprChanCalib")!=std::string::npos){
346  ATH_MSG_INFO("Overriding default keys for PprChanCalib that were:");
347  for (auto it=vCoolInputKeys.begin();it!=vCoolInputKeys.end();++it) {ATH_MSG_INFO(*it);}
348  //Now set to specified key only
349  vCoolInputKeys.clear(); vCoolInputKeys.push_back(mykey);
350  }
351 
352  // Update for PprChanDefaults
353  if (!mykey.empty() && mykey.find("PprChanDefaults")!=std::string::npos){
354  ATH_MSG_INFO("Overriding default keys for PprChanDefaults that were:");
355  for (auto it=vCoolInputKeys.begin();it!=vCoolInputKeys.end();++it) {ATH_MSG_INFO(*it);}
356  //Now set to specified key only
357  vCoolInputKeys.clear(); vCoolInputKeys.push_back(mykey);
358  }
359 
360  // Update for DisabledTowers
361  if (!mykey.empty() && mykey.find("DisabledTowers")!=std::string::npos){
362  ATH_MSG_INFO("Overriding default keys for DisabledTowers that were:");
363  for (auto it=vCoolInputKeys.begin();it!=vCoolInputKeys.end();++it) {ATH_MSG_INFO(*it);}
364  //Now set to specified key only
365  vCoolInputKeys.clear(); vCoolInputKeys.push_back(mykey);
366  }
367 
368  // Update for PpmDeadChannels
369  if (!mykey.empty() && mykey.find("PpmDeadChannels")!=std::string::npos){
370  ATH_MSG_INFO("Overriding default keys for PpmDeadChannels that were:");
371  for (auto it=vCoolInputKeys.begin();it!=vCoolInputKeys.end();++it) {ATH_MSG_INFO(*it);}
372  //Now set to specified key only
373  vCoolInputKeys.clear(); vCoolInputKeys.push_back(mykey);
374  }
375 
376  // this list is required to call updateConditions() later on
377  std::list<std::string> lKeys;
378 
379  // loop over the keys to register a callback to L1CaloCondSvc::updateConditions
380  for (const std::string& key : vCoolInputKeys) {
381  lKeys.push_back(key);
382  ATH_MSG_DEBUG("Adding keys to maps: "<<key);
383 
384  m_mConditions[key].push_back(pObj);
385  m_map_conditions2key[pObj].push_back(key);
386 
387  std::map<std::string, const DataHandle<CondAttrListCollection>* >::const_iterator it_dh = m_mDataHandleAttrListColl.find(key);
388  if(it_dh==m_mDataHandleAttrListColl.end()) {
389 
390  // creat a new datahandle for the CondAttrListCollection and keep track of it
391  m_mDataHandleAttrListColl[key] = new DataHandle<CondAttrListCollection>();
392  const DataHandle<CondAttrListCollection>& dh = *m_mDataHandleAttrListColl[key];
393 
394  // set the callback but do not trigger it immediately. updateConditions() is called only once all
395  // the CondAttrListCollection the condition is depending on have been registered
396  ATH_CHECK( m_detStore->regFcn(&L1CaloCondSvc::updateConditions, this, dh, key, false) );
397 
398  ATH_MSG_DEBUG("Added "<<key<<" to m_mDataHandleAttrListColl");
399  }
400  }
401 
402  // Now we call updateConditions() to populate pObj
403  int n = lKeys.size();
404  StatusCode scUpdate = this->updateConditions(n, lKeys);
405  if (scUpdate.isFailure())
406  ATH_MSG_WARNING( "updateConditions failed to populate pObj" );
407 
408  } else if(conditionType=="AthenaAttributeList"){
409  /*
410  m_mConditions[key] = pObj;
411  m_mDataHandleAttrList[key] = new DataHandle<AthenaAttributeList>();
412 
413  const DataHandle<AthenaAttributeList>& dh = *m_mDataHandleAttrList[key];
414  StatusCode sc = m_detStore->regFcn(&L1CaloCondSvc::updateConditions, this, dh, key, true);
415  if(sc.isFailure()) {
416  log << MSG::ERROR << "failed to regFcn datahandle to L1CaloCondSvc::updateConditions()" << endmsg;
417  return StatusCode::FAILURE;
418  }
419  */
420  } else {
421  ATH_MSG_ERROR( "Condition type " << conditionType << "not recognized by L1CaloCondSvc" );
422  return StatusCode::FAILURE;
423  }
424  return StatusCode::SUCCESS;
425 
426 }
427 
428 #endif
429 
430