ATLAS Offline Software
Loading...
Searching...
No Matches
TrigCOOLUpdateHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
10
12
17#include "CoralBase/AttributeListException.h"
19
20// TDAQ includes
21#include "CTPfragment/CTPfragment.h"
22#include "CTPfragment/CTPExtraWordsFormat.h"
23#include "CTPfragment/Issue.h"
24
25#include <algorithm>
26#include <sstream>
27
28//=========================================================================
29// Standard methods
30//=========================================================================
32 const std::string &name,
33 const IInterface *parent)
34 : AthAlgTool(type, name, parent),
35 m_robDataProviderSvc("ROBDataProviderSvc", name)
36{}
37
38
40{
41 // Do not create these services if they are not available already
42 m_iovSvc = service("IOVSvc", /*createIf=*/false);
43 m_iovDbSvc = service("IOVDbSvc", /*createIf=*/false);
44
45 if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
46
47 return StatusCode::SUCCESS;
48}
49
50
52{
53 m_folderUpdates.clear();
54 return StatusCode::SUCCESS;
55}
56
58{
59 std::ostringstream pending;
60 // Loop over folder updates
61 for (auto f : m_folderUpdates) {
62 if (f.second.needsUpdate) pending << "[" << f.second.lumiBlock << "," << f.second.folderIndex << "]";
63 }
64
65 if (pending.str().empty()) pending << "NONE";
66 ATH_MSG_INFO("[LB,Folder] with pending COOL updates: " << pending.str());
67
68 return StatusCode::SUCCESS;
69}
70
71//=========================================================================
72// Read COOL folder info
73// Loop over all registered keys and get folder name and CLID
74//=========================================================================
75StatusCode TrigCOOLUpdateHelper::readFolderInfo()
76{
77 if (!m_iovDbSvc) return StatusCode::SUCCESS;
78
79 m_folderInfo.clear();
80 // Loop over all keys registered with IOVDbSvc
81 for (const std::string& key : m_iovDbSvc->getKeyList()) {
82
83 // Get folder name and CLID for each key
85 if ( !m_iovDbSvc->getKeyInfo(key, info) ||
86 m_folderInfo.find(info.folderName)!=m_folderInfo.end() )
87 continue;
88
89 CLID clid = detStore()->clid(key);
90 if (clid!=CLID_NULL)
91 m_folderInfo.insert({info.folderName, FolderInfo{clid, key}});
92 else
93 ATH_MSG_ERROR("Cannot find CLID for " << key);
94
95 // If the folder is in the allowed list, make sure it is marked "extensible"
96 if (std::find(m_folders.begin(), m_folders.end(), info.folderName)!=m_folders.end() &&
97 not info.extensible) {
98 ATH_MSG_ERROR("IOVDBSvc folder " << info.folderName << " is not marked as </extensible>. "
99 "Remove it from the allowed 'Folders' property or mark it as extensible.");
100 return StatusCode::FAILURE;
101 }
102 }
103
104 if (!m_coolFolderName.empty()) {
105 // Read COOL folder map
106 const DataHandle<CondAttrListCollection> folderMapHandle;
107 ATH_CHECK( detStore()->regHandle(folderMapHandle, m_coolFolderName) );
108
109 ATH_MSG_INFO("COOL folder map in " << m_coolFolderName << ":");
110 for (auto const& [idx, attr] : *folderMapHandle) {
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.
defines an "iterator" over instances of a given type in StoreGateSvc
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
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 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