ATLAS Offline Software
Loading...
Searching...
No Matches
HLTResultMTMaker.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
8#include "eformat/DetectorMask.h"
9#include "eformat/SourceIdentifier.h"
10#include <unistd.h> // gethostname
11#include <limits.h> // HOST_NAME_MAX
12#include <sstream>
13#include <algorithm>
14
15// Local helpers
16namespace {
18 template<typename T> bool contains(const std::set<T>& set, const T& value) {
19 return set.find(value) != set.cend();
20 }
21 bool isHLT(const uint32_t robid) {
22 return eformat::helper::SourceIdentifier(robid).subdetector_id() == eformat::TDAQ_HLT;
23 }
24 bool isHLT(const eformat::SubDetector subdet) {
25 return subdet == eformat::TDAQ_HLT;
26 }
28 template<typename T> std::set<T> removeDisabled(std::set<T>& requestedIds, const std::set<T>& enabledIds) {
29 std::set<T> removedIds;
30 for (auto it=requestedIds.begin(); it!=requestedIds.end(); ) {
31 // Check if ROB/SubDet is disabled (skip HLT result ID)
32 if (!isHLT(*it) && !contains(enabledIds, *it)) {
33 removedIds.insert(*it);
34 it = requestedIds.erase(it);
35 }
36 else ++it;
37 }
38 return removedIds;
39 }
41 std::string format(const std::set<uint32_t>& set) {
42 std::ostringstream ss;
43 for (const uint32_t id : set)
44 ss << "0x" << std::hex << std::setfill('0') << std::setw(8) << id << std::dec << " ";
45 return ss.str();
46 }
48 std::string format(const std::set<eformat::SubDetector>& set) {
49 std::ostringstream ss;
50 for (const eformat::SubDetector id : set) ss << eformat::helper::SubDetectorDictionary.string(id) << " ";
51 return ss.str();
52 }
53}
54
55// =============================================================================
56// Standard constructor
57// =============================================================================
58HLTResultMTMaker::HLTResultMTMaker(const std::string& type, const std::string& name, const IInterface* parent)
59 : AthAlgTool(type, name, parent) {}
60
61// =============================================================================
62// Implementation of IStateful::initialize
63// =============================================================================
65 ATH_CHECK(m_hltResultWHKey.initialize());
67 ATH_CHECK(m_streamTagMaker.retrieve(DisableTool{m_streamTagMaker.name().empty()}));
68 ATH_CHECK(m_makerTools.retrieve());
69 ATH_CHECK(m_monTool.retrieve(DisableTool{m_monTool.empty()}));
70 ATH_CHECK(m_jobOptionsSvc.retrieve());
71 ATH_CHECK(m_bsMetaDataContRHKey.initialize(!m_extraROBs.empty() || !m_extraSubDets.empty()));
72
73 return StatusCode::SUCCESS;
74}
75
76// =============================================================================
77// Implementation of IStateful::start
78// Initialise the enabled ROBs/SubDets list from DataFlowConfig and extra properties.
79// =============================================================================
81 // DataFlowConfig is a special object used online to hold DF properties passed from TDAQ to HLT as run parameters.
82 Gaudi::Property<std::vector<uint32_t>> enabledROBsProp("EnabledROBs",{});
83 if (enabledROBsProp.fromString(m_jobOptionsSvc->get("DataFlowConfig.DF_Enabled_ROB_IDs","[]")).isSuccess()) {
84 m_enabledROBs.insert(enabledROBsProp.value().begin(), enabledROBsProp.value().end());
85 ATH_MSG_DEBUG("Retrieved a list of " << m_enabledROBs.size()
86 << " ROBs from DataFlowConfig.DF_Enabled_ROB_IDs");
87 }
88 else {
89 ATH_MSG_ERROR("Could not parse DataFlowConfig.DF_Enabled_ROB_IDs from JobOptionsSvc");
90 }
91
92 m_enabledSubDets.clear();
93 Gaudi::Property<std::vector<uint32_t>> enabledSubDetsProp("EnabledSubDets",{});
94 if (enabledSubDetsProp.fromString(m_jobOptionsSvc->get("DataFlowConfig.DF_Enabled_SubDet_IDs","[]")).isSuccess()) {
95 // Need to convert from uint32_t to eformat::SubDetector representable by uint8_t
96 for (const uint32_t id : enabledSubDetsProp.value()) {
97 m_enabledSubDets.insert( static_cast<eformat::SubDetector>(id & 0xFF) );
98 }
99 ATH_MSG_DEBUG("Retrieved a list of " << m_enabledSubDets.size()
100 << " SubDets from DataFlowConfig.DF_Enabled_SubDet_IDs");
101 }
102 else {
103 ATH_MSG_ERROR("Could not parse DataFlowConfig.DF_Enabled_SubDet_IDs from JobOptionsSvc");
104 }
105
106 if (m_enabledROBs.empty() && m_enabledSubDets.empty()) {
108 ATH_MSG_INFO("The list of enabled ROBs and SubDets was not provided by DataFlowConfig or is empty. "
109 << "StreamTag PEBInfo validation will be skipped.");
110 }
111 else {
113 m_enabledROBs.insert(m_extraEnabledROBs.value().begin(), m_extraEnabledROBs.value().end());
114 m_enabledROBs.insert(m_extraROBs.value().begin(), m_extraROBs.value().end());
115 // Need to convert from uint32_t to eformat::SubDetector representable by uint8_t
116 for (const uint32_t id : m_extraEnabledSubDets.value()) {
117 m_enabledSubDets.insert( static_cast<eformat::SubDetector>(id & 0xFF) );
118 }
119 for (const uint32_t id : m_extraSubDets.value()) {
120 m_enabledSubDets.insert( static_cast<eformat::SubDetector>(id & 0xFF) );
121 }
122 ATH_MSG_INFO("StreamTag PEBInfo will be validated against " << m_enabledROBs.size() << " enabled ROBs and "
123 << m_enabledSubDets.size() << " enabled SubDets");
124 }
125 return StatusCode::SUCCESS;
126}
127
128// =============================================================================
129// Implementation of IStateful::finalize
130// =============================================================================
132 ATH_CHECK(m_monTool.release());
133 return StatusCode::SUCCESS;
134}
135
136// =============================================================================
137// Create, record and fill a new result
138// =============================================================================
139StatusCode HLTResultMTMaker::makeResult(const EventContext& eventContext) const {
140 auto hltResult = SG::makeHandle(m_hltResultWHKey,eventContext);
141 ATH_CHECK( hltResult.record(std::make_unique<HLT::HLTResultMT>()) );
142 ATH_MSG_DEBUG("Recorded HLTResultMT with key " << m_hltResultWHKey.key());
143 ATH_CHECK(fillResult(*hltResult, eventContext));
144 return StatusCode::SUCCESS;
145}
146
147// =============================================================================
148// The main method of the tool
149// =============================================================================
150StatusCode HLTResultMTMaker::fillResult(HLT::HLTResultMT& hltResult, const EventContext& eventContext) const {
151 auto monTime = Monitored::Timer<std::chrono::duration<float, std::milli>>("TIME_fillResult");
152
153 // Save HLT runtime metadata
155 runtimeMetadataOutput->push_back(std::make_unique<xAOD::TrigComposite>());
156 char hostname [HOST_NAME_MAX];
157 bool errcode = !gethostname(hostname, HOST_NAME_MAX); // returns 0 on success and -1 on failure, casted to false on success, true on failure
158 std::string hostnameString = std::string(hostname); // setDetail needs a reference
159 errcode &= runtimeMetadataOutput->back()->setDetail("hostname", hostnameString);
160 if (!errcode) ATH_MSG_WARNING("Failed to append hostname to HLT Runtime Metadata TC");
161
162 // Fill the stream tags
163 StatusCode finalStatus = StatusCode::SUCCESS;
164 if (m_streamTagMaker.isEnabled() && m_streamTagMaker->fill(hltResult, eventContext).isFailure()) {
165 ATH_MSG_ERROR(m_streamTagMaker->name() << " failed");
166 finalStatus = StatusCode::FAILURE;
167 }
168
169 // Fill the result using all other tools if the event was accepted
170 if (hltResult.isAccepted()) {
171 for (auto& maker: m_makerTools) {
172 ATH_MSG_DEBUG("Calling " << maker->name() << " for accepted event");
173 if (StatusCode sc = maker->fill(hltResult, eventContext); sc.isFailure()) {
174 ATH_MSG_ERROR(maker->name() << " failed");
175 finalStatus = sc;
176 }
177 }
178
179 if (!m_skipValidatePEBInfo) validatePEBInfo(hltResult);
180 }
181 else {
182 ATH_MSG_DEBUG("Rejected event, further result filling skipped after stream tag maker");
183 }
184
185 ATH_MSG_DEBUG(hltResult);
186
187 Monitored::Group(m_monTool, monTime);
188 return finalStatus;
189}
190
191// =============================================================================
192// Private method removing disabled ROBs/SubDets from StreamTags
193// =============================================================================
195 std::vector<eformat::helper::StreamTag> streamTagsToRemove;
196 for (eformat::helper::StreamTag& st : hltResult.getStreamTagsNonConst()) {
197 // Skip full event building stream tags immediately
198 if (st.robs.empty() && st.dets.empty()) {continue;}
199
200 std::set<uint32_t> removedROBs = removeDisabled(st.robs,m_enabledROBs);
201 if (!removedROBs.empty()) {
202 ATH_MSG_DEBUG("StreamTag " << st.type << "_" << st.name << " requested disabled ROBs: " << format(removedROBs)
203 << " - these ROBs were removed from the StreamTag by " << name());
204 std::vector<eformat::SubDetector> removedSubDets;
205 for (const uint32_t rob : removedROBs) {
206 eformat::SubDetector sd{eformat::helper::SourceIdentifier(rob).subdetector_id()};
207 if (std::find(removedSubDets.begin(),removedSubDets.end(),sd)==removedSubDets.end()) {
208 removedSubDets.push_back(sd);
209 }
210 }
211 auto monRemovedROBsSubDet = Monitored::Collection(
212 "PEB_RemovedROBs_SubDet", removedSubDets,
213 [](const eformat::SubDetector sd) -> const std::string & {return eformat::helper::SubDetectorDictionary.string(sd);});
214 Monitored::Group(m_monTool, monRemovedROBsSubDet);
215 } else {
216 ATH_MSG_VERBOSE("No disabled ROBs were requested by StreamTag " << st.type << "_" << st.name);
217 }
218
219 std::set<eformat::SubDetector> removedSubDets = removeDisabled(st.dets,m_enabledSubDets);
220 if (!removedSubDets.empty()) {
221 ATH_MSG_DEBUG("StreamTag " << st.type << "_" << st.name << " requested disabled SubDets: " << format(removedSubDets)
222 << " - these SubDets were removed from the StreamTag by " << name());
223 std::vector<eformat::SubDetector> removedSubDetsVec(removedSubDets.begin(),removedSubDets.end());
224 auto monRemovedSubDets = Monitored::Collection(
225 "PEB_RemovedSubDets", removedSubDetsVec,
226 [](const eformat::SubDetector sd)-> const std::string & {return eformat::helper::SubDetectorDictionary.string(sd);});
227 Monitored::Group(m_monTool, monRemovedSubDets);
228 } else {
229 ATH_MSG_VERBOSE("No disabled SubDets were requested by StreamTag " << st.type << "_" << st.name);
230 }
231
232 // If the PEB list now became empty, it would turn PEB into FEB - prevent this and drop the stream tag (ATR-24378)
233 if (st.robs.empty() && st.dets.empty()) {
234 bool printed{false};
235 if (m_emptyPEBInfoErrorPrinted.compare_exchange_strong(printed, true, std::memory_order_relaxed)) {
236 ATH_MSG_ERROR("Event accepted to stream " << st.type << "_" << st.name << " but the streaming to this stream "
237 << "is forcibly prevented, because all requested ROBs/SubDets in the PEB list are disabled. "
238 << "ROBs: " << format(removedROBs) << ", SubDets: " << format(removedSubDets));
239 }
240 streamTagsToRemove.push_back(st);
241 }
242 }
243 for (const eformat::helper::StreamTag& st : streamTagsToRemove) {
244 auto it =
245 std::remove(hltResult.getStreamTagsNonConst().begin(),
246 hltResult.getStreamTagsNonConst().end(),
247 st);
248 hltResult.getStreamTagsNonConst().resize (it - hltResult.getStreamTagsNonConst().begin());
249 }
250}
251
252// =============================================================================
253// Private method removing ExtraROBs/ExtraSubDets disabled by the detector mask
254// =============================================================================
256 if (m_extraROBs.empty() && m_extraSubDets.empty()) {
257 // Nothing to check
258 return StatusCode::SUCCESS;
259 }
260
261 // Get the detector mask
263 ATH_CHECK(bsmdc.isValid());
264 ATH_CHECK(!bsmdc->empty());
265 const ByteStreamMetadata* metadata = bsmdc->front();
266 const eformat::helper::DetectorMask detectorMask{metadata->getDetectorMask(), metadata->getDetectorMask2()};
267
268 // Check ROBs
269 std::vector<uint32_t> validatedExtraROBs;
270 for (const uint32_t rob_id : m_extraROBs.value()) {
271 const eformat::helper::SourceIdentifier sid{rob_id};
272 const eformat::SubDetector subdet_id = sid.subdetector_id();
273 if (detectorMask.is_set(subdet_id)) {
274 validatedExtraROBs.push_back(rob_id);
275 }
276 else {
277 ATH_MSG_WARNING("Removing 0x" << MSG::hex << rob_id << MSG::dec << " from " << m_extraROBs.name()
278 << " because SubDetector " << sid.human_detector() << " is disabled in the detector mask");
279 }
280 }
281 m_extraROBs = validatedExtraROBs;
282
283 // Check SubDets
284 std::vector<uint32_t> validatedExtraSubDets;
285 for (const uint32_t subdet_id32 : m_extraSubDets.value()) {
286 const eformat::SubDetector subdet_id = static_cast<eformat::SubDetector>(subdet_id32 & 0xFF);
287 if (detectorMask.is_set(subdet_id)) {
288 validatedExtraSubDets.push_back(subdet_id32);
289 }
290 else {
291 ATH_MSG_WARNING("Removing 0x" << MSG::hex << subdet_id << MSG::dec << " from " << m_extraSubDets.name()
292 << " because SubDetector " << eformat::helper::SourceIdentifier(subdet_id,0,0).human_detector()
293 << " is disabled in the detector mask");
294 }
295 }
296 m_extraSubDets = validatedExtraSubDets;
297
298 return StatusCode::SUCCESS;
299}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t ss
static Double_t sc
Header file to be included by clients of the Monitored infrastructure.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
This class is the StoreGate data object for bytestream metadata.
virtual StatusCode start() override
Gaudi::Property< std::vector< uint32_t > > m_extraEnabledROBs
Extra enabled ROBs.
HLTResultMTMaker(const std::string &type, const std::string &name, const IInterface *parent)
Standard constructor.
Gaudi::Property< std::vector< uint32_t > > m_extraROBs
Extra enabled ROBs checked against detector mask.
ToolHandle< GenericMonitoringTool > m_monTool
Monitoring tool.
Gaudi::Property< std::vector< uint32_t > > m_extraSubDets
Extra enabled SubDets checked against detector mask.
SG::WriteHandleKey< xAOD::TrigCompositeContainer > m_runtimeMetadataWHKey
StoreGate key for HLT Runtime Metadata container.
ServiceHandle< Gaudi::Interfaces::IOptionsSvc > m_jobOptionsSvc
Handle to JobOptionsSvc used to retrieve the DataFlowConfig property.
bool m_skipValidatePEBInfo
If true, don't call validatePEBInfo.
void validatePEBInfo(HLT::HLTResultMT &hltResult) const
Check ROB and SubDet lists in StreamTags and remove those which are disabled.
ToolHandleArray< HLTResultMTMakerTool > m_makerTools
Tools filling the HLTResultMT object.
SG::ReadHandleKey< ByteStreamMetadataContainer > m_bsMetaDataContRHKey
StoreGate key for the ByteStreamMetadata container to retrieve detector mask.
StatusCode fillResult(HLT::HLTResultMT &hltResult, const EventContext &eventContext) const
Fill an existing HLTResultMT with event information.
SG::WriteHandleKey< HLT::HLTResultMT > m_hltResultWHKey
StoreGate key for the HLTResultMT.
StatusCode makeResult(const EventContext &eventContext) const
Create and fill a new HLTResultMT, and record it in the event store.
virtual StatusCode finalize() override
virtual StatusCode initialize() override
std::set< uint32_t > m_enabledROBs
List of enabled ROBs retrieved during initialisation.
Gaudi::Property< std::vector< uint32_t > > m_extraEnabledSubDets
Extra enabled SubDets.
StatusCode validateExtraROBsAndSubDets()
Check ExtraROBs and ExtraSubDets against the detector mask and drop the masked out IDs.
ToolHandle< HLTResultMTMakerTool > m_streamTagMaker
Tool creating stream tags (defines if event is accepted)
std::set< eformat::SubDetector > m_enabledSubDets
List of enabled SubDets retrieved during initialisation.
std::atomic_bool m_emptyPEBInfoErrorPrinted
Flag if empty PEB list error was already printed.
A container class for data required to build online output from HLT.
Definition HLTResultMT.h:38
bool isAccepted() const
If there is at least one stream tag set, it means the event is accepted.
std::vector< eformat::helper::StreamTag > & getStreamTagsNonConst()
Non-const-getter for stream tags needed by the result maker to remove disabled ROBs/SubDets.
Group of local monitoring quantities and retain correlation when filling histograms
A monitored timer.
STL class.
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:114
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
SG::WriteHandle< DecisionContainer > createAndStore(const SG::WriteHandleKey< DecisionContainer > &key, const EventContext &ctx)
Creates and right away records the DecisionContainer with the key.
DataModel_detail::iterator< DVL > remove(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, const T &value)
Specialization of remove for DataVector/List.