ATLAS Offline Software
Loading...
Searching...
No Matches
L1TriggerByteStreamDecoderAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "eformat/DetectorMask.h"
7#include "eformat/SourceIdentifier.h"
8#include "eformat/Problem.h"
9#include <algorithm>
10#include <charconv>
11
12namespace {
13 std::string u32toHexString(uint32_t num) {
14 std::string hexRobId("0x ");
15 std::to_chars(hexRobId.data()+2, hexRobId.data()+hexRobId.size(), num, 16);
16 hexRobId.resize(std::min(10ul,hexRobId.find(' ')));
17 return hexRobId;
18 }
20 struct FractionPerLBNMonitor {
21 FractionPerLBNMonitor(std::string&& name, EventIDBase::number_type lbn, float denom, const ToolHandle<GenericMonitoringTool>& monTool)
22 : errorFraction(Monitored::Scalar<float>{std::move(name), 0}),
23 errorFractionLBN(Monitored::Scalar<EventIDBase::number_type>{"LumiBlock", lbn}),
24 denominator(denom),
25 tool(monTool) {}
26 ~FractionPerLBNMonitor() {
27 if (denominator==0) {
28 errorFraction = 0;
29 } else {
30 errorFraction /= denominator;
31 }
32 Monitored::Group{tool, errorFraction, errorFractionLBN};
33 }
34 void operator++() {++errorFraction;}
35 Monitored::Scalar<float> errorFraction;
36 Monitored::Scalar<EventIDBase::number_type> errorFractionLBN;
37 float denominator{1};
38 const ToolHandle<GenericMonitoringTool>& tool;
39 };
41 void printRobProblems(std::ostream& s, const IROBDataProviderSvc::ROBF* rob) {
42 std::vector<eformat::FragmentProblem> problems;
43 rob->problems(problems);
44 s << problems.size() << " problems: [";
45 bool firstProblem{true};
46 for (eformat::FragmentProblem problem : problems) {
47 if (firstProblem) {firstProblem=false;}
48 else {s << ", ";}
49 s << eformat::helper::FragmentProblemDictionary.string(problem);
50 }
51 s << "]";
52 }
53 std::string robIdsToString(const std::vector<uint32_t>& robIds) {
54 std::ostringstream ss;
55 bool first{true};
56 ss << "[";
57 for (const uint32_t robId : robIds) {
58 if (first) {first=false;}
59 else {ss << ", ";}
60 ss << "0x" << std::hex << robId << std::dec;
61 }
62 ss << "]";
63 return ss.str();
64 }
65}
66
67// =============================================================================
68// Standard constructor
69// =============================================================================
70L1TriggerByteStreamDecoderAlg::L1TriggerByteStreamDecoderAlg(const std::string& name, ISvcLocator* svcLoc)
71: AthReentrantAlgorithm(name, svcLoc) {}
72
73// =============================================================================
74// Implementation of AthReentrantAlgorithm::initialize
75// =============================================================================
77 ATH_MSG_DEBUG("Initialising " << name());
78 ATH_CHECK(m_decoderTools.retrieve());
80 if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
82
84
85 // Build a list of unique ROB IDs to request in each event
86 for (const auto& decoderTool : m_decoderTools) {
87 const std::vector<uint32_t>& ids = decoderTool->robIds();
88 m_robIds.insert(m_robIds.end(), ids.begin(), ids.end());
89 }
90 std::sort(m_robIds.begin(),m_robIds.end());
91 m_robIds.erase(std::unique(m_robIds.begin(),m_robIds.end()), m_robIds.end());
92 ATH_MSG_INFO("Will request " << m_robIds.size() << " ROBs per event: " << robIdsToString(m_robIds));
93
94 // Parse properties
95 m_maybeMissingRobs.insert(m_maybeMissingRobsProp.value().begin(), m_maybeMissingRobsProp.value().end());
96
97 auto setRobCheckBehaviour = [this](const Gaudi::Property<std::string>& prop, ROBCheckBehaviour& out) -> StatusCode {
98 if (prop.value() == "None") {out=ROBCheckBehaviour::None;}
99 else if (prop.value() == "Warning") {out=ROBCheckBehaviour::Warning;}
100 else if (prop.value() == "Error") {out=ROBCheckBehaviour::Error;}
101 else if (prop.value() == "Fatal") {out=ROBCheckBehaviour::Fatal;}
102 else {
103 ATH_MSG_ERROR(prop.name() << " is set to \"" << prop.value()
104 << "\" but needs to be one of [\"None\", \"Warning\", \"Error\", \"Fatal\"]");
105 return StatusCode::FAILURE;
106 }
107 return StatusCode::SUCCESS;
108 };
109
110 ATH_CHECK(setRobCheckBehaviour(m_robStatusCheckLevel,m_robStatusCheck));
111 ATH_CHECK(setRobCheckBehaviour(m_robFormatCheckLevel,m_robFormatCheck));
112
113 return StatusCode::SUCCESS;
114}
115
116// =============================================================================
117// Implementation of AthReentrantAlgorithm::start
118// =============================================================================
120 // Skip detector mask checks if ByteStreamMetaData not available
121 if (m_bsMetaDataContRHKey.key().empty()) {
122 return StatusCode::SUCCESS;
123 }
124
125 // Get the detector mask
127 ATH_CHECK(bsmdc.isValid());
128 ATH_CHECK(!bsmdc->empty());
129 const ByteStreamMetadata* metadata = bsmdc->front();
130 const eformat::helper::DetectorMask detectorMask{metadata->getDetectorMask(), metadata->getDetectorMask2()};
131
132 // Check if the requested ROBs should be expected to be present or may be missing
133 for (const uint32_t robId : m_robIds) {
134 const eformat::helper::SourceIdentifier sid{robId};
135 if (!detectorMask.is_set(sid.subdetector_id())) {
136 if (m_maybeMissingRobs.insert(robId).second) {
137 ATH_MSG_WARNING("ROB ID 0x" << MSG::hex << robId << MSG::dec << " was requested for decoding, "
138 << "but the SubDetector " << sid.human_detector() << " is disabled in "
139 << "the detector mask. Will not require this ROB ID to be present in every event.");
140 }
141 }
142 }
143
144 return StatusCode::SUCCESS;
145}
146
147// =============================================================================
148// Implementation of AthReentrantAlgorithm::finalize
149// =============================================================================
151 ATH_MSG_DEBUG("Finalising " << name());
153 ATH_CHECK(m_decoderTools.release());
154 return StatusCode::SUCCESS;
155}
156
157// =============================================================================
158// Implementation of AthReentrantAlgorithm::execute
159// =============================================================================
160StatusCode L1TriggerByteStreamDecoderAlg::execute(const EventContext& eventContext) const {
161 ATH_MSG_DEBUG("Executing " << name());
162 auto monTimeExec = Monitored::Timer<std::chrono::duration<float, std::milli>>("TIME_execute");
163
164 // Retrieve the BS data for all tools in one request to parallelise DCM->ROS network requests
166 m_robDataProviderSvc->getROBData(eventContext, m_robIds, vrobf, name());
167
168 // Filter ROB list for each tool and call the conversion
169 for (const auto& decoderTool : m_decoderTools) {
170 std::string toolName{decoderTool->name().substr(decoderTool->name().rfind('.')+1)};
171 auto monTimePrep = Monitored::Timer<std::chrono::duration<float, std::milli>>("TIME_prepareROBs_"+toolName);
173 ATH_CHECK(filterRobs(vrobf, vrobfForTool, decoderTool->robIds(), toolName, eventContext));
174 ATH_CHECK(checkRobs(vrobfForTool, toolName, eventContext));
175 monTimePrep.stop();
176 auto monTimeConv = Monitored::Timer<std::chrono::duration<float, std::milli>>("TIME_convert_"+toolName);
177 try {
178 ATH_CHECK(decoderTool->convertFromBS(vrobfForTool, eventContext));
179 } catch (const std::exception& ex) {
180 ATH_MSG_ERROR("Exception in " << toolName << "::convertFromBS: " << ex.what());
181 return StatusCode::FAILURE;
182 }
183 // Note: time histograms not filled if any ATH_CHECK above fails
184 Monitored::Group(m_monTool, monTimePrep, monTimeConv);
185 }
186
187 Monitored::Group(m_monTool, monTimeExec);
188 return StatusCode::SUCCESS;
189}
190
191// =============================================================================
194 const std::vector<uint32_t>& ids,
195 std::string_view toolName,
196 const EventContext& eventContext) const {
197 std::copy_if(in.cbegin(), in.cend(), std::back_inserter(out),
198 [&ids](const IROBDataProviderSvc::ROBF* rob){
199 return (std::find(ids.cbegin(),ids.cend(),rob->source_id()) != ids.cend());
200 });
201
202 std::string missingFractionName{"MissingROBFraction_"};
203 missingFractionName.append(toolName);
204 FractionPerLBNMonitor monMissingFraction{std::move(missingFractionName), eventContext.eventID().lumi_block(), static_cast<float>(ids.size()), m_monTool};
205
206 // Check if all ROBs were found and report errors if not
207 if (ids.size() != out.size()) {
208 bool fail{false};
209 for (const uint32_t id : ids) {
210 auto eqRobId = [&id](const IROBDataProviderSvc::ROBF* rob){return (rob->source_id() == id);};
211 if (std::find_if(out.cbegin(),out.cend(),eqRobId) == out.cend()) {
212 ++monMissingFraction;
213 std::string hexRobId = u32toHexString(id);
214 if (std::find(m_maybeMissingRobs.cbegin(),m_maybeMissingRobs.cend(),id) != m_maybeMissingRobs.cend()) {
215 ATH_MSG_DEBUG("Missing ROBFragment with ID " << hexRobId << " ("
216 << eformat::helper::SourceIdentifier(id).human() << ") requested by " << toolName
217 << " but it is allowed to be missing due to the detector mask or the "
218 << m_maybeMissingRobsProp.name() << " property");
219 Monitored::Scalar<std::string> monMissing{"MissingROBAllowed", hexRobId};
220 Monitored::Group{m_monTool, monMissing};
221 } else {
222 ATH_MSG_ERROR("Missing ROBFragment with ID " << hexRobId << " ("
223 << eformat::helper::SourceIdentifier(id).human() << ") requested by " << toolName);
224 fail = true;
225 Monitored::Scalar<std::string> monMissing{"MissingROB", hexRobId};
226 Monitored::Group{m_monTool, monMissing};
227 }
228 }
229 }
230 if (fail) {
231 return StatusCode::FAILURE;
232 }
233 }
234 ATH_MSG_DEBUG("Found " << out.size() << " out of " << ids.size() << " ROBFragments requested by " << toolName);
235 return StatusCode::SUCCESS;
236}
237
238// =============================================================================
240 std::string_view toolName,
241 const EventContext& eventContext) const {
242 StatusCode sc{StatusCode::SUCCESS};
244 return sc;
245 }
246 std::string corruptedFractionName{"CorruptedROBFraction_"};
247 std::string errorFractionName{"ErroneousROBFraction_"};
248 corruptedFractionName.append(toolName);
249 errorFractionName.append(toolName);
250 FractionPerLBNMonitor monCorruptedFraction{std::move(corruptedFractionName), eventContext.eventID().lumi_block(), static_cast<float>(robs.size()), m_monTool};
251 FractionPerLBNMonitor monErrorFraction{std::move(errorFractionName), eventContext.eventID().lumi_block(), static_cast<float>(robs.size()), m_monTool};
252 auto printCheckMsg = [this](std::ostringstream& ss, ROBCheckBehaviour checkBehaviour, bool maybeMissing, StatusCode& sc) {
253 if (maybeMissing) {
254 ss << " but it is allowed due to the detector mask or the " << m_maybeMissingRobsProp.name() << " property";
255 ATH_MSG_DEBUG(ss.str());
256 }
257 else if (checkBehaviour==ROBCheckBehaviour::Warning) {ATH_MSG_WARNING(ss.str());}
258 else if (checkBehaviour==ROBCheckBehaviour::Error) {ATH_MSG_ERROR(ss.str());}
259 else if (checkBehaviour==ROBCheckBehaviour::Fatal) {
260 ATH_MSG_ERROR(ss.str());
261 sc = StatusCode::FAILURE;
262 }
263 };
264
265 for (const IROBDataProviderSvc::ROBF* rob : robs) {
266 // Format check
267 if (m_robFormatCheck!=ROBCheckBehaviour::None && !rob->check_noex()) {
268 ++monCorruptedFraction;
269 const uint32_t id{rob->rob_source_id()}; // there's a small chance ID is also corrupted, but usually corruption affects latter words
270 std::string hexRobId = u32toHexString(id);
271 const bool maybeMissing{std::find(m_maybeMissingRobs.cbegin(),m_maybeMissingRobs.cend(),id) != m_maybeMissingRobs.cend()};
272
273 Monitored::Scalar<std::string> monCorrupted{(maybeMissing ? "CorruptedROBAllowed" : "CorruptedROB"), hexRobId};
274 Monitored::Group{m_monTool, monCorrupted};
275
276 std::ostringstream ss;
277 ss << "ROBFragment with ID " << hexRobId << " (" << eformat::helper::SourceIdentifier(id).human()
278 << ") requested by " << toolName << " has corrupted data with ";
279 printRobProblems(ss, rob);
280 printCheckMsg(ss, m_robFormatCheck, maybeMissing, sc);
281 }
282 // Status check
283 if (m_robStatusCheck!=ROBCheckBehaviour::None && rob->nstatus()>0 && rob->status()[0]!=0) {
284 ++monErrorFraction;
285 const uint32_t id{rob->rob_source_id()};
286 std::string hexRobId = u32toHexString(id);
287 const bool maybeMissing{std::find(m_maybeMissingRobs.cbegin(),m_maybeMissingRobs.cend(),id) != m_maybeMissingRobs.cend()};
288
289 Monitored::Scalar<std::string> monErroneous{(maybeMissing ? "ErroneousROBAllowed" : "ErroneousROB"), hexRobId};
290 Monitored::Group{m_monTool, monErroneous};
291
292 std::ostringstream ss;
293 ss << "ROBFragment with ID " << hexRobId << " (" << eformat::helper::SourceIdentifier(id).human()
294 << ") requested by " << toolName << " has non-zero status 0x" << std::hex << rob->status()[0] << std::dec;
295 printCheckMsg(ss, m_robStatusCheck, maybeMissing, sc);
296 }
297 }
298 return sc;
299}
#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)
static Double_t ss
static Double_t sc
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)
An algorithm that can be simultaneously executed in multiple threads.
This class is the StoreGate data object for bytestream metadata.
OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment ROBF
std::vector< const ROBF * > VROBFRAG
std::set< uint32_t > m_maybeMissingRobs
Set of ROB IDs allowed to be missing because they are disabled.
virtual StatusCode execute(const EventContext &eventContext) const override
StatusCode checkRobs(const IROBDataProviderSvc::VROBFRAG &robs, std::string_view toolName, const EventContext &eventContext) const
Check ROB status word and report if different from zero.
ROBCheckBehaviour
The behaviour for non-zero ROB status words.
StatusCode filterRobs(const IROBDataProviderSvc::VROBFRAG &in, IROBDataProviderSvc::VROBFRAG &out, const std::vector< uint32_t > &ids, std::string_view toolName, const EventContext &eventContext) const
Copy over ROBFragment pointers from in to out for ROBs with IDs from the ids list.
Gaudi::Property< std::string > m_robFormatCheckLevel
Set behaviour for corrupted ROB data.
std::vector< uint32_t > m_robIds
Vector of ROB IDs to request, filled from all decoder tools in initialize.
Gaudi::Property< std::string > m_robStatusCheckLevel
Set behaviour for non-zero ROB status words.
L1TriggerByteStreamDecoderAlg(const std::string &name, ISvcLocator *svcLoc)
Standard constructor.
ServiceHandle< IROBDataProviderSvc > m_robDataProviderSvc
ROBDataProvider service handle.
Gaudi::Property< std::vector< uint32_t > > m_maybeMissingRobsProp
Allow some ROBs to be missing.
ToolHandleArray< IL1TriggerByteStreamTool > m_decoderTools
Tool performing the decoding work.
ToolHandle< GenericMonitoringTool > m_monTool
Monitoring tool to create online histograms.
SG::ReadHandleKey< ByteStreamMetadataContainer > m_bsMetaDataContRHKey
StoreGate key for the ByteStreamMetadata container to retrieve detector mask.
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
A monitored timer.
bool first
Definition DeMoScan.py:534
TGCHBChip operator++(TGCHBChip &rs, int)
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
DataModel_detail::iterator< DVL > unique(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of unique for DataVector/List.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.