4 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
7 #ifndef TRIGT1CALOCONDSVC_L1CALOCONDSVC_ICC
8 #define TRIGT1CALOCONDSVC_L1CALOCONDSVC_ICC
10 #include "AthenaKernel/IOVRange.h"
11 #include "AthenaKernel/StorableConversions.h"
13 #include "AthenaPoolUtilities/AthenaAttributeList.h"
14 #include "AthenaPoolUtilities/CondAttrListCollection.h"
18 #include "CxxUtils/checker_macros.h"
19 ATLAS_NO_CHECK_FILE_THREAD_SAFETY; // obsolete, replaced by L1CaloCondAlg
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 ====================================================================== */
27 ATH_MSG_VERBOSE( "*** L1CaloCondSvc::store() ***" );
28 ATH_MSG_VERBOSE(key <<" "<< folder <<" "<< tag );
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();
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;
39 // Setting up a new IOV range
43 start = IOVTime(m_iovBeginTime);
44 end = IOVTime(m_iovEndTime);
46 start = IOVTime(m_iovBeginRun, m_iovBeginLB);
47 end = IOVTime(m_iovEndRun, m_iovEndLB);
50 // range is used later to setup the IOV range of the updated conditions
51 IOVRange range(start, end);
53 ATH_MSG_VERBOSE( "*** get old conditions ***" );
56 std::string conditionType = pobj->conditionType();
57 if(conditionType=="CondAttrListCollection") {
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;
66 if(m_bWriteNewChannels) {
67 ATH_MSG_VERBOSE( "*** m_bWriteNewChannels TRUE ***" );
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.
73 CondAttrListCollection* newAttrListCollection = new CondAttrListCollection(!m_bUseTimeStamp);
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;
80 newAttrListCollection->add(channelNumber, attrList);
81 newAttrListCollection->add(channelNumber, range);
84 ATH_CHECK( m_detStore->record(newAttrListCollection, key) );
88 ATH_MSG_VERBOSE( "*** m_bWriteNewChannels FALSE ***" );
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
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) );
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);
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
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;
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);
121 mergedAttrListCollection->add(channelNumber, coolAttrList);
122 mergedAttrListCollection->add(channelNumber, range);
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)");
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);
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)");
144 finalConditions = SG::asStorable(mergedAttrListCollection);
146 //-------------------------------------------
147 // replace the 'old' collection retrieved from COOL by the one updated with new attributes values
149 //retrieve the proxy of the CondAttrListCollection retrieved from COOL
150 SG::DataProxy* proxy = m_detStore->proxy(m_detStore->clid(key), key);
152 // we reset the proxy to delete the old conditions
155 // we add the new updated conditions to the proxy
156 proxy->setObject(finalConditions);
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;
170 } else if(conditionType=="AthenaAttributeList") {
172 AthenaAttributeList* attributeList = dynamic_cast<AthenaAttributeList*>(newConditions);
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) );
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);
182 finalConditions = SG::asStorable(mergedAthenaAttributeList);
186 ATH_MSG_ERROR( "Condition type " << conditionType<< "not recognized by L1CaloCondSvc" );
187 return StatusCode::FAILURE;
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) );
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) );
203 ATH_MSG_DEBUG( "Registered "<< pobj->conditionType() <<" to condition DB in folder "<< folder <<" with tag " << tag );
206 ATH_MSG_ERROR( "Could not create persistant collection");
207 return StatusCode::FAILURE;
210 return StatusCode::SUCCESS;
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 );
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;
227 ATH_MSG_DEBUG( "Container not found in DetStore. Trying to retrieve it from the condition DB.");
231 ATH_MSG_ERROR( "Could not create transient container" );
232 return StatusCode::FAILURE;
235 return this->retrieveImpl(pobj, key);
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 );
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;
252 ATH_MSG_DEBUG( "Container not found in DetStore. Trying to retrieve it from the condition DB.");
254 pobj = new T(folderKeyMap);
256 ATH_MSG_ERROR( "Could not create transient container" );
257 return StatusCode::FAILURE;
260 return this->retrieveImpl(pobj, key);
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 );
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;
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();
282 //sc = this->registerCondition(coolKey, pobj);
283 ATH_CHECK( this->registerCondition(pobj,key) );
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;
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 );
296 ATH_MSG_ERROR( "IL1CaloPersistenceCapable* pObj is NULL in L1CaloCondSvc::registerCondition()" );
297 return StatusCode::FAILURE;
300 std::string conditionType = pObj->conditionType();
302 if(conditionType=="CondAttrListCollection") {
304 // we retrieve the keys (ie cool folder paths) needed by the condition object
305 std::vector<std::string> vCoolInputKeys = pObj->coolInputKeys();
307 // Check if we specified some new key
308 // Used for L1Calo Overlay where we have both data and MC databases
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);
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);
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);
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);
342 //Check if we specified some new key
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);
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);
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);
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);
376 // this list is required to call updateConditions() later on
377 std::list<std::string> lKeys;
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);
384 m_mConditions[key].push_back(pObj);
385 m_map_conditions2key[pObj].push_back(key);
387 std::map<std::string, const DataHandle<CondAttrListCollection>* >::const_iterator it_dh = m_mDataHandleAttrListColl.find(key);
388 if(it_dh==m_mDataHandleAttrListColl.end()) {
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];
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) );
398 ATH_MSG_DEBUG("Added "<<key<<" to m_mDataHandleAttrListColl");
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" );
408 } else if(conditionType=="AthenaAttributeList"){
410 m_mConditions[key] = pObj;
411 m_mDataHandleAttrList[key] = new DataHandle<AthenaAttributeList>();
413 const DataHandle<AthenaAttributeList>& dh = *m_mDataHandleAttrList[key];
414 StatusCode sc = m_detStore->regFcn(&L1CaloCondSvc::updateConditions, this, dh, key, true);
416 log << MSG::ERROR << "failed to regFcn datahandle to L1CaloCondSvc::updateConditions()" << endmsg;
417 return StatusCode::FAILURE;
421 ATH_MSG_ERROR( "Condition type " << conditionType << "not recognized by L1CaloCondSvc" );
422 return StatusCode::FAILURE;
424 return StatusCode::SUCCESS;