ATLAS Offline Software
Loading...
Searching...
No Matches
HltROBDataProviderSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
7
8// Gaudi
9#include "Gaudi/Interfaces/IOptionsSvc.h"
10
11// hltinterface / data collector
12#include "hltinterface/DataCollector.h"
13
14// eformat
15#include "eformat/Status.h"
16
17// Athena
18
19// STL includes
20#include <algorithm> // std::find
21
22// Maximum number of ROB fragments in ROB buffer
23static const size_t MAX_ROBFRAGMENTS = 4096;
24
25HltROBDataProviderSvc::HltROBDataProviderSvc(const std::string& name, ISvcLocator* pSvcLocator) :
26 base_class(name, pSvcLocator)
27{
28}
29
31{
32 ATH_MSG_INFO("HltROBDataProviderSvc::" << __FUNCTION__ << ": name = " << name());
33//===================================================================
34// The filtering of ROBs can be configured with job options as:
35//
36// for individual ROBs as :
37// ------------------------
38// ROBDataProviderSvc.filterRobWithStatus = [ (ROB SourceId, StatusCode to remove),
39// (ROB SourceId 2, StatusCode to remove 2), ... ]
40// and:
41// ROBDataProviderSvc.filterRobWithStatus += [ (ROB SourceId n, StatusCode to remove n) ]
42//
43// Example:
44// ROBDataProviderSvc.filterRobWithStatus = [ (0x42002a,0x0000000f), (0x42002e,0x00000008) ]
45// ROBDataProviderSvc.filterRobWithStatus += [ (0x42002b,0x00000000) ]
46//
47// for all ROBs of a given sub detector as :
48// -----------------------------------------
49// ROBDataProviderSvc.filterSubDetWithStatus = [ (Sub Det Id, StatusCode to remove),
50// (Sub Det Id 2, StatusCode to remove 2), ... ]
51// and:
52// ROBDataProviderSvc.filterSubDetWithStatus += [ (Sub Det Id n, StatusCode to remove n) ]
53//
54// Example:
55// ROBDataProviderSvc.filterSubDetWithStatus = [ (0x41,0x00000000), (0x42,0x00000000) ]
56// ROBDataProviderSvc.filterSubDetWithStatus += [ (0x41,0xcb0002) ]
57//
58// For valid ROB Source Ids, Sub Det Ids and ROB Status elements see the event format
59// document ATL-D-ES-0019 (EDMS)
60//===================================================================
61 // get list of ROBs to filter out by status code
62 for (unsigned int i = 0; i < m_filterRobWithStatus.value().size(); i++) {
63 eformat::helper::SourceIdentifier tmpsrc(m_filterRobWithStatus.value()[i].first);
64 if (tmpsrc.human_detector() != "UNKNOWN") {
65 m_filterRobMap[tmpsrc.code()].push_back(m_filterRobWithStatus.value()[i].second);
66 }
67 }
68
69 // get list of subdetectors to filter out by status code
70 for (unsigned int i = 0; i < m_filterSubDetWithStatus.value().size(); i++) {
71 eformat::helper::SourceIdentifier tmpsrc((eformat::SubDetector)m_filterSubDetWithStatus.value()[i].first, 0);
72 if (tmpsrc.human_detector() != "UNKNOWN") {
73 m_filterSubDetMap[tmpsrc.subdetector_id()].push_back(m_filterSubDetWithStatus.value()[i].second);
74 }
75 }
76 ATH_MSG_INFO(" ---> Filter out empty ROB fragments = " << m_filterEmptyROB);
77
78 // print list of ROBs to filter out by status code
79 ATH_MSG_INFO(" ---> Filter out specific ROBs by Status Code: # ROBs = " << m_filterRobMap.size());
80 for (const auto& it : m_filterRobMap) {
81 eformat::helper::SourceIdentifier tmpsrc(it.first);
82 ATH_MSG_INFO(" RobId=0x" << MSG::hex << it.first << " -> in Sub Det = " << tmpsrc.human_detector());
83
84 for (auto it_status: it.second) {
85 eformat::helper::Status tmpstatus(it_status);
86 ATH_MSG_INFO(" Status Code=0x"
87 << MSG::hex << std::setfill( '0' ) << std::setw(8) << tmpstatus.code()
88 << " Generic Part=0x" << std::setw(4) << tmpstatus.generic()
89 << " Specific Part=0x" << std::setw(4) << tmpstatus.specific() << MSG::dec);
90 }
91 }
92
93 // print list of subdetectors to filter out by status code
94 ATH_MSG_INFO(" ---> Filter out Sub Detector ROBs by Status Code: # Sub Detectors = " << m_filterSubDetMap.size());
95 for (const auto& it : m_filterSubDetMap) {
96 eformat::helper::SourceIdentifier tmpsrc(it.first, 0);
97 ATH_MSG_INFO(" SubDetId=0x" << MSG::hex << it.first << " -> " << tmpsrc.human_detector());
98 for (auto it_status : it.second) {
99 eformat::helper::Status tmpstatus(it_status);
100 ATH_MSG_INFO(" Status Code=0x"
101 << MSG::hex << std::setfill( '0' ) << std::setw(8) << tmpstatus.code()
102 << " Generic Part=0x" << std::setw(4) << tmpstatus.generic()
103 << " Specific Part=0x" << std::setw(4) << tmpstatus.specific() << MSG::dec);
104 }
105 }
106
107 // get the list of enabled ROBs from OKS
108 bool robOKSconfigFound = false;
109
110 if ( m_readROBfromOKS.value() ) {
111 ServiceHandle<Gaudi::Interfaces::IOptionsSvc> jobOptionsSvc("JobOptionsSvc", name());
112 if ((jobOptionsSvc.retrieve()).isFailure()) {
113 ATH_MSG_ERROR("Could not find JobOptionsSvc");
114 } else {
115 if (jobOptionsSvc->has("DataFlowConfig.DF_Enabled_ROB_IDs") &&
116 m_enabledROBs.fromString(jobOptionsSvc->get("DataFlowConfig.DF_Enabled_ROB_IDs")).isSuccess()) {
117 robOKSconfigFound = true;
118 ATH_MSG_INFO(" ---> Read from OKS = "
119 << MSG::dec << m_enabledROBs.value().size() << " enabled ROB IDs.");
120 } else {
121 ATH_MSG_WARNING("Could not set Property 'enabledROBs' from OKS.");
122 }
123 }
124 }
125
126 // print list of enabled ROBs, read from OKS
127 ATH_MSG_INFO(" ---> Read list of enabled ROBs from OKS = " << m_readROBfromOKS);
128 if (m_enabledROBs.value().empty()) {
129 ATH_MSG_INFO(" ---> The list of enabled ROBs has size = 0. No check will be performed ");
130 } else {
131 if (m_readROBfromOKS.value() && robOKSconfigFound) {
132 ATH_MSG_INFO(" ---> The list of enabled ROBs has size = " << MSG::dec << m_enabledROBs.value().size()
133 << ". It was read from the partition database." );
134 } else {
135 ATH_MSG_INFO(" ---> The list of enabled ROBs has size = " << MSG::dec << m_enabledROBs.value().size()
136 << ". It was read from job options." );
137 }
138 }
139
140 // prefetch all ROBs in a ROS on a first retrieval of ROBs from this ROS
141 ATH_MSG_INFO(" ---> Prefetch all ROBs in a ROS on first retrieval = " << m_prefetchAllROBsfromROS);
142
143 if ( m_prefetchAllROBsfromROS.value() && !m_enabledROBs.value().empty() ) {
144 m_prefetchWholeROSList.reserve( m_enabledROBs.value().size() );
145 if ( m_prefetchSubDetROS.value().empty() ||
146 (std::find(m_prefetchSubDetROS.value().begin(),m_prefetchSubDetROS.value().end(),0) != m_prefetchSubDetROS.value().end())
147 )
148 {
150 ATH_MSG_INFO(" All enabled ROBs are used for prefetching. ROB list size = " << m_prefetchWholeROSList.size() );
151 } else {
152 ATH_MSG_INFO(" The following sub-detectors or sub-detector groups are configured for prefetching : Number = "
153 << m_prefetchSubDetROS.value().size() );
154 for (uint8_t it : m_prefetchSubDetROS.value() ) {
155 if (it > 0xf) {
156 eformat::SubDetector sd(static_cast<eformat::SubDetector>(it));
157 eformat::helper::SourceIdentifier tmpsrc(sd, 0);
158 ATH_MSG_INFO(" SubDetId = 0x" << MSG::hex << std::setw(2) << (int)it << MSG::dec << " -> Group : "
159 << tmpsrc.human_group()
160 << " -> SubDetector : " << tmpsrc.human_detector() );
161 } else {
162 eformat::SubDetectorGroup sg(static_cast<eformat::SubDetectorGroup>(it));
163 ATH_MSG_INFO(" SubDetGroup = 0x" << MSG::hex << std::setw(1) << (int)it << MSG::dec << " -> Group : "
164 << eformat::helper::SubDetectorGroupDictionary.string(sg));
165 }
166 }
167 // establish prefetch list
169 for (auto rob : m_enabledROBs.value() ) {
170 eformat::helper::SourceIdentifier tmpsrc(rob);
171 if( (std::find(m_prefetchSubDetROS.value().begin(),m_prefetchSubDetROS.value().end(),tmpsrc.subdetector_id())
172 != m_prefetchSubDetROS.value().end()) ||
173 (std::find(m_prefetchSubDetROS.value().begin(),m_prefetchSubDetROS.value().end(),tmpsrc.subdetector_group())
174 != m_prefetchSubDetROS.value().end())
175 ) m_prefetchWholeROSList.push_back(rob);
176 }
177 ATH_MSG_INFO(" Number of ROBs which are used for prefetching = " << m_prefetchWholeROSList.size() );
178 }
179 }
180
181 // Setup the slot specific cache
183
184 // Retrieve the monitoring tool
185 if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
186
188
189 return(StatusCode::SUCCESS);
190}
191
193{
194 ATH_CHECK(m_monTool.release());
195 return StatusCode::SUCCESS;
196}
197
199
201void HltROBDataProviderSvc::addROBData(const EventContext& context, const std::vector<uint32_t>& robIds,
202 const std::string_view callerName)
203{
204 ATH_MSG_VERBOSE("start of " << __FUNCTION__ << ": Number of ROB Ids to add = " << robIds.size()
205 << " caller name = " << callerName);
206 EventCache* cache = m_eventsCache.get( context );
207
208 // allocate vector of missing ROB Ids
209 std::vector<uint32_t> robIds_missing ;
210
211 // allocate vector with existing ROB fragments in cache
212 std::vector<const ROBF*> robFragments_inCache ;
213
214 // check input ROB list against cache
215 eventCache_checkRobListToCache(cache,robIds, robFragments_inCache, robIds_missing ) ;
216
217 // call data collector
218 if (!robIds_missing.empty()) {
219 ATH_MSG_DEBUG( __FUNCTION__ << ": Number of ROB Ids to reserve with DCM = " << robIds_missing.size());
220 // reserve the ROBs in the DCM
221 try {
222 auto mon_robres_t = Monitored::Timer("TIME_ROBReserveData");
223 hltinterface::DataCollector::instance()->reserveROBData(cache->globalEventNumber, robIds_missing);
224 mon_robres_t.stop();
225 // Fill monitoring histograms
226 auto mon_robres_nROBs = Monitored::Scalar("NUMBER_ROBReserveData",robIds_missing.size());
227 auto mon = Monitored::Group(m_monTool, mon_robres_t, mon_robres_nROBs);
228 } catch (const std::exception& ex) {
229 ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
230 << "Failed to reserve ROB data, caught an unexpected exception: " << ex.what());
231 } catch (...) {
232 ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
233 << "Failed to reserve ROB data, caught an unexpected exception.");
234 }
235 }
236}
237
239void HltROBDataProviderSvc::setNextEvent(const EventContext& context, const std::vector<ROBF>& result)
240{
241 ATH_MSG_FATAL("Obsolete method HltROBDataProviderSvc::setNextEvent(const EventContext& context, const std::vector<ROBF>& result) called "
242 << "\n context = " << context << " number of ROB fragments = " << result.size() );
243}
244
246void HltROBDataProviderSvc::setNextEvent(const EventContext& context, const RawEvent* re)
247{
248 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
249 EventCache* cache = m_eventsCache.get( context );
250
251 // clear the event cache of the previous event
252 eventCache_clear( cache );
253
254 //----------------------------------------------+
255 // Fill the event cache with the new event data |
256 //----------------------------------------------+
257
258 // store the pointer to the event
259 cache->event = re;
260 // set the LVL1 id
261 cache->currentLvl1ID = re->lvl1_id();
262 // set the global event number
263 cache->globalEventNumber = re->global_id();
264 // set flag for masking L2/EF module ID, this is only necessary for the separate L2 and EF systems from Run 1
265 m_maskL2EFModuleID = (re->nlvl2_trigger_info() != 0);
266
267 //--------------------+
268 // Fill the ROB cache |
269 //--------------------+
270
271 // get all the ROBFragments
273 size_t number_robs = re->children(robF,MAX_ROBFRAGMENTS);
274 if (number_robs == MAX_ROBFRAGMENTS) {
275 ATH_MSG_ERROR("ROB buffer overflow: ROBs found = " << number_robs
276 << " Max. number of ROBs allowed = " << MAX_ROBFRAGMENTS);
277 }
278 std::vector<ROBF> rob_fragments;
279 rob_fragments.reserve(number_robs);
280 // loop over all ROBs
281 for (size_t irob = 0; irob < number_robs; irob++) {
282 rob_fragments.push_back(ROBF(robF[irob]));
283 }
284 // add the ROBs to the cache/rob map, but extract the size before moving it
285 const size_t nRobs = rob_fragments.size();
286 eventCache_addRobData(cache, std::move(rob_fragments)) ;
287
288 ATH_MSG_DEBUG(" ---> setNextEvent for " << name() );
289 ATH_MSG_DEBUG(" current [global id, LVL1 id] = [" << cache->globalEventNumber << "," << cache->currentLvl1ID << "]" );
290 ATH_MSG_DEBUG(" number of received ROBs = " << nRobs );
291 ATH_MSG_DEBUG(" size of ROB cache = " << cache->robmap.size() );
292
293 //------------------------------+
294 // Initiate whole ROS retrieval |
295 //------------------------------+
296 if ( m_prefetchAllROBsfromROS.value() && !m_prefetchWholeROSList.empty() ) {
297 addROBData( context, m_prefetchWholeROSList, "prefetch_HLTROBDataProviderSvc" );
298 ATH_MSG_DEBUG(" ROS prefetch init. size = " << m_prefetchWholeROSList.size() );
299 }
300
301 return;
302}
303
305void HltROBDataProviderSvc::getROBData(const EventContext& context,
306 const std::vector<uint32_t>& robIds, std::vector<const ROBF*>& robFragments,
307 const std::string_view callerName)
308{
309 EventCache* cache = m_eventsCache.get( context );
310
311 // lock for event cache update with DCM
312 std::lock_guard<std::mutex> lock( cache->eventCache_mtx );
313
314 TrigTimeStamp rosStartTime;
315
316 ATH_MSG_VERBOSE("start of " << __FUNCTION__ << ": Number of ROB Ids to get = " << robIds.size()
317 << " caller name = " << callerName);
318
319 // allocate vector of missing ROB Ids
320 std::vector<uint32_t> robIds_missing ;
321
322 // check input ROB list against cache
323 eventCache_checkRobListToCache(cache, robIds, robFragments, robIds_missing) ;
324
325 // no missing ROB fragments, return the found ROB fragments
326 if (robIds_missing.empty()) {
327 ATH_MSG_DEBUG( __FUNCTION__ << ": All requested ROB Ids were found in the cache. ");
328 return;
329 }
330
331 // There were missing ROB fragments retrieve them from the DCM and add them to the cache
332 ATH_MSG_DEBUG( __FUNCTION__ << ": Number of ROB Ids to retrieve with DCM = " << robIds_missing.size());
333
334 typedef std::vector<hltinterface::DCM_ROBInfo> ROBInfoVec;
335 ROBInfoVec vRobInfos;
336
337 // Get ROB Fragments with DataCollector
338 vRobInfos.reserve( robIds_missing.size() ) ;
339 try {
340 auto mon_rob_t = Monitored::Timer("TIME_ROBRequest");
341 hltinterface::DataCollector::instance()->collect(vRobInfos, cache->globalEventNumber, robIds_missing);
342 mon_rob_t.stop();
343 // Fill monitoring histograms
344 auto mon_rob_nROBs = Monitored::Scalar("NUMBER_ROBRequest",vRobInfos.size());
345 auto mon = Monitored::Group(m_monTool, mon_rob_t, mon_rob_nROBs);
346 } catch (const std::exception& ex) {
347 ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
348 << "Failed to collect ROBs, caught an unexpected exception: " << ex.what()
349 << ". Throwing hltonl::Exception::EventSourceCorrupted" );
351 } catch (...) {
352 ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
353 << "Failed to collect ROBs, caught an unexpected exception. "
354 << "Throwing hltonl::Exception::EventSourceCorrupted" );
356 }
357
358 // Store retrieved ROB data in the cache
359 std::vector<ROBF> robFragments_missing;
360 robFragments_missing.reserve( vRobInfos.size() );
361 for(ROBInfoVec::const_iterator it=vRobInfos.begin(); it!=vRobInfos.end(); ++it) {
362 ATH_MSG_DEBUG(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << it->robFragment.source_id() << MSG::dec
363 << " retrieved from DCM for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
364 robFragments_missing.push_back( it->robFragment );
365 }
366
367 // Check if event should be monitored and monitor ROB data
368 auto monitorData = robmonitor::ROBDataMonitorStruct(cache->currentLvl1ID, std::string(callerName));
369 if (m_doCostMonitoring && m_trigCostSvcHandle->isMonitoredEvent(context, /*includeMultiSlot =*/ false)) {
370 // Monitor HLT cached ROBs
371 for (const ROBF* robFrag : robFragments) {
372 monitorData.requested_ROBs[robFrag->source_id()] = robmap_getRobData(*robFrag, robmonitor::HLT_CACHED);
373 }
374
375 // Add the ROBs to the cache/rob map and collect ignored robs
376 std::set<uint32_t> robIds_ignored;
377 eventCache_addRobData(cache, std::move(robFragments_missing), robIds_ignored);
378
379 // Monitor DCM ROBs
380 for (const hltinterface::DCM_ROBInfo& robInfo : vRobInfos) {
382
383 // Check ROB history
384 if (robIds_ignored.find(robInfo.robFragment.source_id()) != robIds_ignored.end()) {
385 status = robmonitor::IGNORED;
386 }
387 else {
388 status = robInfo.robIsCached ? robmonitor::DCM_CACHED : robmonitor::RETRIEVED;
389 }
390
391 monitorData.requested_ROBs[robInfo.robFragment.source_id()] = robmap_getRobData(robInfo.robFragment, status);
392 }
393
394 // Return all the requested ROB fragments from the cache and collect disabled ROBs
395 std::set<uint32_t> robIds_disabled;
396 eventCache_checkRobListToCache(cache, robIds, robFragments, robIds_missing, robIds_disabled);
397
398 // Fill undefined (not enabled) ROBs
399 for (uint32_t robId : robIds_disabled) {
400 monitorData.requested_ROBs[robId] = robmonitor::ROBDataStruct(robId);
401 monitorData.requested_ROBs[robId].rob_history = robmonitor::UNDEFINED;
402 }
403 }
404 else {
405 // add the ROBs to the cache/rob map
406 eventCache_addRobData(cache, std::move(robFragments_missing)) ;
407
408 // return all the requested ROB fragments from the cache
409 eventCache_checkRobListToCache(cache, robIds, robFragments, robIds_missing) ;
410 }
411
412 // Save ROS processing time and pass ROS data to CostMonitor
413 if (m_doCostMonitoring && m_trigCostSvcHandle->isMonitoredEvent(context, /*includeMultiSlot =*/ false)) {
414 TrigTimeStamp rosEndTime;
415
416 monitorData.start_time = rosStartTime.microsecondsSinceEpoch();
417 monitorData.end_time = rosEndTime.microsecondsSinceEpoch();
418
419 // Check if ROBMonitorDataStruct is move-constructible
420 static_assert(std::is_nothrow_move_constructible<robmonitor::ROBDataMonitorStruct>::value);
421 if (m_trigCostSvcHandle->monitorROS(context, std::move(monitorData)).isFailure()) {
422 ATH_MSG_WARNING("TrigCost ROS monitoring failed!");
423 }
424 }
425}
426
428{
429 auto robData = robmonitor::ROBDataStruct(robFrag.source_id());
430 robData.rob_size = robFrag.fragment_size_word();
431 robData.rob_status_word = robFrag.nstatus() ? robFrag.status()[0] : 0;
432 robData.rob_history = robStatus;
433
434 return robData;
435}
436
438const RawEvent* HltROBDataProviderSvc::getEvent(const EventContext& context)
439{
440 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
441 return m_eventsCache.get( context )->event;
442}
443
445void HltROBDataProviderSvc::setEventStatus(const EventContext& context, uint32_t status)
446{
447 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
448 m_eventsCache.get(context)->eventStatus = status;
449}
450
452uint32_t HltROBDataProviderSvc::getEventStatus(const EventContext& context)
453{
454 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
455 return m_eventsCache.get( context )->eventStatus;
456}
457
459void HltROBDataProviderSvc::processCachedROBs(const EventContext& context, const std::function< void(const ROBF* )>& fn) const
460{
461 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
462 for ( const auto& el : m_eventsCache.get( context )->robmap )
463 {
464 fn( &el.second );
465 }
466}
467
469bool HltROBDataProviderSvc::isEventComplete(const EventContext& context) const
470{
471 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
472 return m_eventsCache.get( context )->isEventComplete;
473}
474
476int HltROBDataProviderSvc::collectCompleteEventData(const EventContext& context, const std::string_view callerName)
477{
478 ATH_MSG_VERBOSE("start of " << __FUNCTION__ << " caller name = " << callerName);
479
480 EventCache* cache = m_eventsCache.get( context );
481
482 // lock for event cache update with DCM
483 std::lock_guard<std::mutex> lock( cache->eventCache_mtx );
484
485 // return if event is already complete
486 if (cache->isEventComplete) return 0;
487
488 typedef std::vector<hltinterface::DCM_ROBInfo> ROBInfoVec;
489 ROBInfoVec vRobInfos ;
490 if (!m_enabledROBs.value().empty()) {
491 vRobInfos.reserve( m_enabledROBs.value().size() ) ;
492 } else {
493 vRobInfos.reserve( MAX_ROBFRAGMENTS ) ;
494 }
495
496 // Get ROB Fragments for complete event with DataCollector
497 try {
498 auto mon_col_t = Monitored::Timer("TIME_CollectAllROBs");
499 hltinterface::DataCollector::instance()->collect(vRobInfos, cache->globalEventNumber);
500 mon_col_t.stop();
501 ATH_MSG_DEBUG( __FUNCTION__ << ": Number of received ROB Ids = " << vRobInfos.size() );
502 // Fill monitoring histograms
503 auto mon_col_nROBs = Monitored::Scalar("NUMBER_CollectAllROBs",vRobInfos.size());
504 auto mon = Monitored::Group(m_monTool, mon_col_t, mon_col_nROBs);
505 } catch (const std::exception& ex) {
506 ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
507 << "Failed to collect complete event, caught an unexpected exception: " << ex.what()
508 << ". Throwing hltonl::Exception::EventSourceCorrupted" );
510 } catch (...) {
511 ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
512 << "Failed to collect complete event, caught an unexpected exception. "
513 << "Throwing hltonl::Exception::EventSourceCorrupted" );
515 }
516
517 // Store retrieved ROB data in the cache
518 std::vector<ROBF> robFragments_missing;
519 robFragments_missing.reserve( vRobInfos.size() );
520 for(ROBInfoVec::const_iterator it=vRobInfos.begin(); it!=vRobInfos.end(); ++it) {
521 ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << it->robFragment.source_id() << MSG::dec
522 << " retrieved from DCM for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
523 robFragments_missing.push_back( it->robFragment );
524 }
525 // add the ROBs to the cache/rob map
526 eventCache_addRobData(cache, std::move(robFragments_missing)) ;
527
528 // update event complete flag
529 cache->isEventComplete = true;
530
531 return vRobInfos.size();
532}
533
536{
537 // No filter criteria defined
538 if (m_filterRobMap.empty() && m_filterSubDetMap.empty()) {
539 return(false);
540 }
541
542 // There should be at least one status element if there was an error
543 // in case there are 0 status elements then there was no known error
544 // (see event format document ATL-D-ES-0019 (EDMS))
545 const uint32_t* rob_it_status;
546 const uint32_t null_status(0);
547 // The ROB has no status elements
548 if (rob->nstatus() == 0) {
549 rob_it_status = &null_status;
550 } else {
551 // The ROB has at least one status element, access it via an iterator
552 rob->status(rob_it_status);
553 }
554
555 // Build the full ROB Sourceidentifier
556 eformat::helper::SourceIdentifier tmpsrc(rob->rob_source_id());
557
558 // Check if there is a ROB specific filter rule defined for this ROB Id and match the status code
559 FilterRobMap::iterator map_it_rob = m_filterRobMap.find(tmpsrc.code());
560 if (map_it_rob != m_filterRobMap.end()) {
561 for (auto it_status: (*map_it_rob).second) {
562 if (*rob_it_status == it_status) {
563 ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << tmpsrc.code()
564 << " with status = 0x" << *rob_it_status << MSG::dec
565 << " removed due to ROB filter rule.");
566 return(true);
567 }
568 }
569 }
570
571 // Check if there is a sub detector specific filter rule defined for this ROB Id and match the status code
572 FilterSubDetMap::iterator map_it_subdet = m_filterSubDetMap.find(tmpsrc.subdetector_id());
573 if (map_it_subdet != m_filterSubDetMap.end()) {
574 for (auto it_status: (*map_it_subdet).second) {
575 if (*rob_it_status == it_status) {
576 ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << tmpsrc.code()
577 << " with status = 0x" << *rob_it_status << MSG::dec
578 << " removed due to SubDet filter rule.");
579 return(true);
580 }
581 }
582 }
583 return(false);
584}
585
587{
588 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
589 cache->event = nullptr;
590 cache->currentLvl1ID = 0;
591 cache->globalEventNumber = 0;
592 cache->eventStatus = 0;
593 cache->isEventComplete = false;
594 { cache->robmap.clear(); }
595}
596
597void HltROBDataProviderSvc::eventCache_checkRobListToCache(EventCache* cache, const std::vector<uint32_t>& robIds_toCheck,
598 std::vector<const ROBF*>& robFragments_inCache,
599 std::vector<uint32_t>& robIds_missing,
600 std::optional<std::reference_wrapper<std::set<uint32_t>>> robIds_disabled )
601{
602 ATH_MSG_VERBOSE("start of " << __FUNCTION__ << " number of ROB Ids to check = " << robIds_toCheck.size());
603
604 // clear output arrays
605 robFragments_inCache.clear();
606 robIds_missing.clear();
607
608 // allocate sufficient space for output arrays
609 robFragments_inCache.reserve( robIds_toCheck.size() );
610 robIds_missing.reserve( robIds_toCheck.size() );
611
612 // check input ROB ids
613 for (uint32_t id : robIds_toCheck) {
614
615 // check for duplicate IDs on the list of missing ROBs
616 std::vector<uint32_t>::iterator missing_it = std::find(robIds_missing.begin(), robIds_missing.end(), id);
617 if (missing_it != robIds_missing.end()) {
618 ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id : 0x" << MSG::hex << id << MSG::dec <<" is already on the list of missing IDs.");
619 continue;
620 }
621
622 // check if ROB is already in cache
623 { ROBMAP::const_iterator map_it = cache->robmap.find(id);
624 if (map_it != cache->robmap.end()) {
625 ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id 0x" << MSG::hex << id << MSG::dec
626 << " found for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
627 robFragments_inCache.push_back( &(map_it->second) );
628 continue;
629 }
630 }
631
632 // check if ROB is actually enabled for readout
633 if (!m_enabledROBs.value().empty()) {
634 std::vector<uint32_t>::const_iterator rob_enabled_it =
635 std::find(m_enabledROBs.value().begin(), m_enabledROBs.value().end(),id);
636 if(rob_enabled_it == m_enabledROBs.value().end()) {
637 ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id : 0x" << MSG::hex << id << MSG::dec
638 << " will be not added, since it is not on the list of enabled ROBs.");
639 if (robIds_disabled) {
640 robIds_disabled->get().insert(id);
641 }
642 continue;
643 }
644 }
645
646 // the ROB is not in the cache and should be eventually added
647 ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id : 0x" << MSG::hex << id << MSG::dec <<" is missing ");
648 robIds_missing.push_back( id ) ;
649 } // end loop over input ROB Ids to check
650}
651
652void HltROBDataProviderSvc::eventCache_addRobData(EventCache* cache, std::vector<ROBF>&& robFragments,
653 std::optional<std::reference_wrapper<std::set<uint32_t>>> robIds_ignored)
654{
655 ATH_MSG_VERBOSE("start of " << __FUNCTION__ << " number of ROB fragments to add = " << robFragments.size());
656
657 for (const ROBF& rob : robFragments) {
658
659 // Source ID
660 uint32_t id = rob.source_id();
661 ATH_MSG_VERBOSE(__FUNCTION__ << " Id = 0x" << std::hex << id << std::dec );
662
663 // mask off the module ID for L2 and EF result for Run 1 data
664 if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
665 (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_LVL2) ) {
666 id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
667 if (!m_maskL2EFModuleID) {
668 ATH_MSG_ERROR(__FUNCTION__ << " Inconsistent flag for masking L2/EF module IDs");
670 }
671 } else if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
672 (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_EVENT_FILTER) &&
674 id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
675 }
676
677 // check if ROB is already in cache
678 { ROBMAP::const_iterator it = cache->robmap.find(id);
679 if (it != cache->robmap.end()) {
680 ATH_MSG_VERBOSE(__FUNCTION__ << " Duplicate ROB Id 0x" << MSG::hex << id << MSG::dec
681 << " found for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
682 continue;
683 }
684 }
685
686 // filter ROBs with external criteria
687 if (robmap_filterRobWithStatus(&rob)) {
688 if (rob.nstatus() > 0) {
689 const uint32_t* it_status;
690 rob.status(it_status);
691 eformat::helper::Status tmpstatus(*it_status);
692 ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << id << std::setfill('0')
693 << " with Generic Status Code = 0x" << std::setw(4) << tmpstatus.generic()
694 << " and Specific Status Code = 0x" << std::setw(4) << tmpstatus.specific() << MSG::dec
695 << " removed for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
696 }
697 if (robIds_ignored) {
698 robIds_ignored->get().insert(id);
699 }
700 continue;
701 }
702
703 // check for ROBs with no data
704 if ((rob.rod_ndata() == 0) && (m_filterEmptyROB)) {
705 ATH_MSG_VERBOSE(__FUNCTION__ << " Empty ROB Id = 0x" << MSG::hex << id << MSG::dec
706 << " removed for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
707 continue;
708 }
709
710 // add ROB to map
711 { cache->robmap.insert(std::make_pair(id,std::move(rob))); }
712 }
713}
714
716{
717 // delete event;
718 { robmap.clear(); }
719}
const boost::regex re(r_e)
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static const size_t MAX_ROBFRAGMENTS
Service to serve ROB data in online environment.
OFFLINE_FRAGMENTS_NAMESPACE::FullEventFragment RawEvent
data type for reading raw event
Definition RawEvent.h:37
std::vector< uint32_t > m_prefetchWholeROSList
virtual uint32_t getEventStatus(const EventContext &) override
Retrieve the status for the event.
virtual void setEventStatus(const EventContext &, uint32_t) override
Store the status for the event.
virtual void setNextEvent(const EventContext &, const std::vector< ROBF > &) override
Start a new event with a set of ROB fragments, e.g. from LVL1 result, in online and add the fragments...
Gaudi::Property< std::vector< uint32_t > > m_enabledROBs
ServiceHandle< ITrigCostSvc > m_trigCostSvcHandle
HltROBDataProviderSvc(const std::string &name, ISvcLocator *pSvcLocator)
OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment ROBF
ROB Fragment class.
robmonitor::ROBDataStruct robmap_getRobData(const ROBF &, robmonitor::ROBHistory)
method to get ROB fragment from ROBF input: context ROB fragment to be parsed ROB history status
void eventCache_clear(EventCache *)
method to clear an event cache in a slot input: pointer to cache
Gaudi::Property< ArrayPairIntType > m_filterRobWithStatus
bool robmap_filterRobWithStatus(const ROBF *)
method to filter ROBs with given Status code
void eventCache_checkRobListToCache(EventCache *, const std::vector< uint32_t > &, std::vector< const ROBF * > &, std::vector< uint32_t > &, std::optional< std::reference_wrapper< std::set< uint32_t > > > robIds_disabled=std::nullopt)
method to compare a list of ROB Ids to the ones in an event cache in a slot input: pointer to cache v...
virtual void addROBData(const EventContext &, const std::vector< uint32_t > &, const std::string_view callerName="UNKNOWN") override
Signal ROB fragments which should be considered for prefetching in online running.
virtual void getROBData(const EventContext &, const std::vector< uint32_t > &, std::vector< const ROBF * > &, const std::string_view callerName="UNKNOWN") override
Retrieve ROB fragments for given ROB ids from the ROB cache.
virtual StatusCode finalize() override
Gaudi::Property< bool > m_prefetchAllROBsfromROS
virtual StatusCode initialize() override
void eventCache_addRobData(EventCache *, std::vector< ROBF > &&, std::optional< std::reference_wrapper< std::set< uint32_t > > > robIds_ignored=std::nullopt)
method to add ROB fragments to an event cache in a slot input: pointer to cache vector of ROB fragmen...
virtual int collectCompleteEventData(const EventContext &, const std::string_view callerName="UNKNOWN") override
retrieve in online running all ROBs for the event from the readout system. Only those ROBs are retrie...
Gaudi::Property< ArrayPairIntType > m_filterSubDetWithStatus
virtual bool isEventComplete(const EventContext &) const override
Flag to check if all event data have been retrieved.
virtual void processCachedROBs(const EventContext &, const std::function< void(const ROBF *)> &) const override
Apply a function to all ROBs in the cache.
ToolHandle< GenericMonitoringTool > m_monTool
Monitoring tool.
virtual const RawEvent * getEvent(const EventContext &) override
Retrieve the full event fragment.
Gaudi::Property< std::vector< uint8_t > > m_prefetchSubDetROS
SG::SlotSpecificObj< EventCache > m_eventsCache
An event cache for each slot.
Gaudi::Property< bool > m_filterEmptyROB
Filter out empty ROB fragments which are send by the ROS.
Gaudi::Property< bool > m_readROBfromOKS
Gaudi::Property< bool > m_doCostMonitoring
bool m_maskL2EFModuleID
For Run 1 the module ID for the Lvl2/EF result contained the machine ID and needed to be filtered out...
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
A monitored timer.
Maintain a set of objects, one per slot.
utility class to measure time duration in AthenaMT The pattern when it is useful: AlgA tags the begin...
uint64_t microsecondsSinceEpoch() const
Thrown if event source throws an exception when new event is requested.
The structure which is used to monitor the ROB data request in L2 It is created for every addROBData ...
A structure with data about ROB properties.
const DataType * PointerType
Definition RawEvent.h:25
size_t getNSlots()
Return the number of event slots.
ROBHistory
A structure with data about ROB properties.
struct which provides the event cache for each slot
std::mutex eventCache_mtx
mutex for ROB cache updates