ATLAS Offline Software
Loading...
Searching...
No Matches
TrigCOOLUpdateHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
10
12
17#include "CoralBase/AttributeListException.h"
18
19// TDAQ includes
20#include "CTPfragment/CTPfragment.h"
21#include "CTPfragment/CTPExtraWordsFormat.h"
22#include "CTPfragment/Issue.h"
23
24#include <algorithm>
25#include <sstream>
26
27//=========================================================================
28// Standard methods
29//=========================================================================
31 const std::string &name,
32 const IInterface *parent)
33 : AthAlgTool(type, name, parent),
34 m_robDataProviderSvc("ROBDataProviderSvc", name)
35{}
36
37
39{
40 // Do not create these services if they are not available already
41 m_iovSvc = service("IOVSvc", /*createIf=*/false);
42 m_iovDbSvc = service("IOVDbSvc", /*createIf=*/false);
43
44 if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
45
46 return StatusCode::SUCCESS;
47}
48
49
51{
52 m_folderUpdates.clear();
53 return StatusCode::SUCCESS;
54}
55
57{
58 std::ostringstream pending;
59 // Loop over folder updates
60 for (auto f : m_folderUpdates) {
61 if (f.second.needsUpdate) pending << "[" << f.second.lumiBlock << "," << f.second.folderIndex << "]";
62 }
63
64 if (pending.str().empty()) pending << "NONE";
65 ATH_MSG_INFO("[LB,Folder] with pending COOL updates: " << pending.str());
66
67 return StatusCode::SUCCESS;
68}
69
70//=========================================================================
71// Read COOL folder info
72// Loop over all registered keys and get folder name and CLID
73//=========================================================================
75{
76 if (!m_iovDbSvc) return StatusCode::SUCCESS;
77
78 m_folderInfo.clear();
79 // Loop over all keys registered with IOVDbSvc
80 for (const std::string& key : m_iovDbSvc->getKeyList()) {
81
82 // Get folder name and CLID for each key
84 if ( !m_iovDbSvc->getKeyInfo(key, info) ||
85 m_folderInfo.find(info.folderName)!=m_folderInfo.end() )
86 continue;
87
88 CLID clid = detStore()->clid(key);
89 if (clid!=CLID_NULL)
90 m_folderInfo.insert({info.folderName, FolderInfo{clid, key}});
91 else
92 ATH_MSG_ERROR("Cannot find CLID for " << key);
93
94 // If the folder is in the allowed list, make sure it is marked "extensible"
95 if (std::find(m_folders.begin(), m_folders.end(), info.folderName)!=m_folders.end() &&
96 not info.extensible) {
97 ATH_MSG_ERROR("IOVDBSvc folder " << info.folderName << " is not marked as </extensible>. "
98 "Remove it from the allowed 'Folders' property or mark it as extensible.");
99 return StatusCode::FAILURE;
100 }
101 }
102
103 if (!m_coolFolderName.empty()) {
104 // Read COOL folder map. We cannot use a ReadCondHandle because
105 // this is executed before the first event.
106 const CondAttrListCollection* folderMap{};
107 ATH_CHECK( detStore()->retrieve(folderMap, m_coolFolderName) );
108
109 ATH_MSG_INFO("COOL folder map in " << m_coolFolderName << ":");
110 for (auto const& [idx, attr] : *folderMap) {
111 m_folderNames[idx] = attr["FolderName"].data<std::string>();
112 ATH_MSG_INFO(" (" << idx << ") " << m_folderNames[idx]);
113 }
114 }
115 return StatusCode::SUCCESS;
116}
117
118StatusCode TrigCOOLUpdateHelper::resetFolders(const std::vector<std::string>& folders)
119{
120 if (folders.empty()) return StatusCode::SUCCESS;
121
122 StatusCode sc(StatusCode::SUCCESS);
123 for (const std::string& f : folders) {
124 if ( resetFolder(f).isFailure() ) {
125 sc = StatusCode::FAILURE;
126 }
127 }
128 return sc;
129}
130
131StatusCode TrigCOOLUpdateHelper::resetFolder(const std::string& folder)
132{
133 // Force a reset of folders by setting an IOVRange in the past
134
135 if (!m_iovSvc || !m_iovDbSvc) return StatusCode::SUCCESS;
136
137 const auto& f = m_folderInfo.find(folder);
138 if ( f==m_folderInfo.end() ) {
139 ATH_MSG_DEBUG("Folder " << folder << " not registered with IOVDbSvc");
140 return StatusCode::SUCCESS;
141 }
142
143 const CLID& clid = f->second.clid;
144 const std::string& key = f->second.key;
145
146 // Make sure we are not trying to reset a time-based folder
147 IOVRange iov;
148 if ( m_iovSvc->getRange(clid, key, iov).isSuccess() ) {
149 if ( iov.start().isTimestamp() || iov.start().isBoth() ) {
150 ATH_MSG_ERROR(folder << " is not a Run/LB based folder. Cannot perform COOL update.");
151 return StatusCode::FAILURE;
152 }
153 }
154
155 if ( m_iovSvc->dropObjectFromDB(clid, key, "StoreGateSvc").isFailure() ) {
156 ATH_MSG_WARNING("Could not invalidate folder " << folder);
157 return StatusCode::FAILURE;
158 }
159
160 // All OK
161 ATH_MSG_INFO("Invalidated IOV and dropped payload of folder " <<
162 folder << (key!=folder ? " (key="+key+")" : "") );
163
164 return StatusCode::SUCCESS;
165}
166
167
168//=========================================================================
169// Folder update during the run
170//=========================================================================
171StatusCode TrigCOOLUpdateHelper::hltCoolUpdate(const EventContext& ctx)
172{
173 // Extract COOL folder updates from CTP fragment
174 if ( extractFolderUpdates(ctx).isFailure() ) {
175 ATH_MSG_ERROR("Failure reading CTP extra payload");
176 return StatusCode::FAILURE;
177 }
178
179 // Loop over folders to be updated
180 for (auto& [idx, f] : m_folderUpdates) {
181
182 if (f.needsUpdate) {
183
184 if ( !m_iovSvc || m_coolFolderName.empty() ) {
185 ATH_MSG_DEBUG("Request to reload COOL folder ID " << idx << " for IOV change in lumiblock "
186 << f.lumiBlock << " but running without IOVSvc. Current event: " << ctx.eventID());
187 f.needsUpdate = false;
188 continue;
189 }
190
191 std::string folderName;
192 if (getFolderName(f.folderIndex, folderName).isFailure()) {
193 continue; // On purpose not a failure
194 }
195
196 ATH_MSG_INFO("Reload of COOL folder " << folderName << " for IOV change in lumiblock "
197 << f.lumiBlock << ". Current event: " << ctx.eventID());
198
199 if ( hltCoolUpdate(folderName).isFailure() ) {
200 ATH_MSG_ERROR("COOL update failed for " << folderName << ". Aborting.");
201 return StatusCode::FAILURE;
202 }
203 // All OK
204 f.needsUpdate = false;
205 }
206 }
207
208 return StatusCode::SUCCESS;
209}
210
211StatusCode TrigCOOLUpdateHelper::hltCoolUpdate(const std::string& folderName)
212{
213 if (std::find(m_folders.begin(), m_folders.end(), folderName)==m_folders.end()) {
214 ATH_MSG_ERROR("Received request to update COOL folder '" << folderName
215 << "' but this folder is not in the allowed list:" << m_folders);
216 return StatusCode::FAILURE;
217 }
218
219 auto mon_t = Monitored::Timer("TIME_CoolFolderUpdate");
220 Monitored::Group mon(m_monTool, mon_t);
221
222 // Reset folder and make IOVDbSvc drop objects
223 if (resetFolder(folderName).isFailure()) {
224 ATH_MSG_ERROR("Reset of " << folderName << " failed");
225 return StatusCode::FAILURE;
226 }
227
228 return StatusCode::SUCCESS;
229}
230
231StatusCode TrigCOOLUpdateHelper::getFolderName(CTPfragment::FolderIndex idx, std::string& folderName) const
232{
233 const auto& itr = m_folderNames.find(idx);
234 if (itr==m_folderNames.end()) {
235 ATH_MSG_ERROR(m_coolFolderName << " does not contain a folder for index/channel " << idx
236 << ". Existing folders are:");
237 for (auto const& [idx, name] : m_folderNames) {
238 ATH_MSG_INFO(" (" << idx << ") " << name);
239 }
240 return StatusCode::FAILURE;
241 }
242
243 folderName = itr->second;
244 return StatusCode::SUCCESS;
245}
246
247
248//=========================================================================
249// Extract COOL folder updates from CTP fragment
250//=========================================================================
251StatusCode TrigCOOLUpdateHelper::extractFolderUpdates(const EventContext& ctx)
252{
253 using CTPfragment::FolderIndex;
254 using CTPfragment::FolderEntry;
255
256 // Fetch CTP fragment ROB
257 const std::vector<uint32_t> robs{m_ctpRobId};
259 try {
260 m_robDataProviderSvc->addROBData(ctx, robs, name());
261 m_robDataProviderSvc->getROBData(ctx, robs, ctpRobs, name());
262 }
263 catch (const std::exception& ex) {
264 ATH_MSG_ERROR("Cannot retrieve CTP ROB 0x" << MSG::hex << m_ctpRobId.value() << MSG::dec << " due to exception: " << ex.what());
265 return StatusCode::FAILURE;
266 }
267
268 if ( ctpRobs.empty() ) {
269 ATH_MSG_ERROR("Cannot retrieve CTP ROB 0x" << MSG::hex << m_ctpRobId.value() << MSG::dec);
270 return StatusCode::FAILURE;
271 }
272
273 // Decode CTP extra payload words
274 std::vector<uint32_t> l1_extraPayload = CTPfragment::extraPayloadWords( ctpRobs[0] );
275 CTPfragment::ExtraPayload ctp_payload;
276 try {
277 ctp_payload = CTPfragment::ExtraPayload(l1_extraPayload);
278 }
279 catch (CTPfragment::ExtraPayloadTooLong& ex) {
280 ATH_MSG_ERROR("Invalid CTP fragment. Exception = " << ex.what());
281 return StatusCode::FAILURE;
282 }
283
284 if ( msgLevel(MSG::DEBUG) ) {
285 msg() << MSG::DEBUG << "CTP extra payload (" << l1_extraPayload.size() << " words): ";
286 for (std::size_t i=0; i<l1_extraPayload.size(); ++i) {
287 msg() << " " << l1_extraPayload[i];
288 }
289 std::ostringstream out;
290 out << ctp_payload;
291 msg() << out.str() << endmsg;
292 }
293
294 // Loop over potential new folder updates
295 for (const std::pair<const FolderIndex, FolderEntry>& kv : ctp_payload.getFolderUpdates()) {
296
297 // Check if we already have an update for this folder
298 std::map<FolderIndex, FolderUpdate>::const_iterator f = m_folderUpdates.find(kv.first);
299
300 // No updates yet or this update supersedes the previous one
301 if (f==m_folderUpdates.end() || (f->second.lumiBlock != kv.second.lumiBlock)) {
302 m_folderUpdates[kv.first] = FolderUpdate(kv.second); // new folder update
303
304 ATH_MSG_DEBUG("Conditions update for folder " << kv.second.folderIndex
305 << " on lumiblock " << kv.second.lumiBlock);
306 }
307 }
308 return StatusCode::SUCCESS;
309}
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This file defines the class for a collection of AttributeLists where each one is associated with a ch...
Helpers for checking error return status codes and reporting errors.
uint32_t CLID
The Class ID type.
Validity Range object.
Basic time unit for IOVSvc.
static Double_t sc
Helper tool for COOL updates.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
MsgStream & msg() const
This class is a collection of AttributeLists where each one is associated with a channel number.
Validity Range object.
Definition IOVRange.h:30
std::vector< const ROBF * > VROBFRAG
Group of local monitoring quantities and retain correlation when filling histograms
A monitored timer.
TrigCOOLUpdateHelper(const std::string &type, const std::string &name, const IInterface *parent)
virtual StatusCode start() override
Gaudi::Property< std::vector< std::string > > m_folders
std::map< std::string, FolderInfo > m_folderInfo
CLID/name mapping of COOL folders.
virtual StatusCode stop() override
std::map< CTPfragment::FolderIndex, std::string > m_folderNames
Map to store the folder update index -> name mapping.
std::map< CTPfragment::FolderIndex, FolderUpdate > m_folderUpdates
Map to store scheduled/done COOL folder updates.
StatusCode resetFolder(const std::string &folder)
Reset COOL folder.
StatusCode hltCoolUpdate(const EventContext &ctx)
Perform COOL udpates if needed.
SmartIF< IIOVDbSvc > m_iovDbSvc
ToolHandle< GenericMonitoringTool > m_monTool
StatusCode readFolderInfo()
Read information about existing COOL folders.
StatusCode resetFolders(const std::vector< std::string > &folders)
Reset list of COOL folders.
Gaudi::Property< std::string > m_coolFolderName
virtual StatusCode initialize() override
Gaudi::Property< uint32_t > m_ctpRobId
StatusCode extractFolderUpdates(const EventContext &ctx)
Decode COOL folder updates according to extra payload in CTP fragment.
StatusCode getFolderName(CTPfragment::FolderIndex idx, std::string &folderName) const
Return folder name to index.
SmartIF< IIOVSvc > m_iovSvc
ServiceHandle< IROBDataProviderSvc > m_robDataProviderSvc
Struct to hold CLID <-> folder name mapping.
Folder update entry.
Filled by IIOVDbSvc::getKeyInfo.
Definition IIOVDbSvc.h:44