ATLAS Offline Software
HltROBDataProviderSvc.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 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
23 static const size_t MAX_ROBFRAGMENTS = 4096;
24 
25 HltROBDataProviderSvc::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
168  m_prefetchWholeROSList.clear();
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 
201 void 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 
239 void 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 
246 void 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
272  OFFLINE_FRAGMENTS_NAMESPACE::PointerType robF[MAX_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
285  eventCache_addRobData(cache, std::move(rob_fragments)) ;
286 
287  ATH_MSG_DEBUG(" ---> setNextEvent for " << name() );
288  ATH_MSG_DEBUG(" current [global id, LVL1 id] = [" << cache->globalEventNumber << "," << cache->currentLvl1ID << "]" );
289  ATH_MSG_DEBUG(" number of received ROBs = " << rob_fragments.size() );
290  ATH_MSG_DEBUG(" size of ROB cache = " << cache->robmap.size() );
291 
292  //------------------------------+
293  // Initiate whole ROS retrieval |
294  //------------------------------+
295  if ( m_prefetchAllROBsfromROS.value() && !m_prefetchWholeROSList.empty() ) {
296  addROBData( context, m_prefetchWholeROSList, "prefetch_HLTROBDataProviderSvc" );
297  ATH_MSG_DEBUG(" ROS prefetch init. size = " << m_prefetchWholeROSList.size() );
298  }
299 
300  return;
301 }
302 
304 void HltROBDataProviderSvc::getROBData(const EventContext& context,
305  const std::vector<uint32_t>& robIds, std::vector<const ROBF*>& robFragments,
306  const std::string_view callerName)
307 {
308  EventCache* cache = m_eventsCache.get( context );
309 
310  // lock for event cache update with DCM
311  std::lock_guard<std::mutex> lock( cache->eventCache_mtx );
312 
313  TrigTimeStamp rosStartTime;
314 
315  ATH_MSG_VERBOSE("start of " << __FUNCTION__ << ": Number of ROB Ids to get = " << robIds.size()
316  << " caller name = " << callerName);
317 
318  // allocate vector of missing ROB Ids
319  std::vector<uint32_t> robIds_missing ;
320 
321  // check input ROB list against cache
322  eventCache_checkRobListToCache(cache, robIds, robFragments, robIds_missing) ;
323 
324  // no missing ROB fragments, return the found ROB fragments
325  if (robIds_missing.empty()) {
326  ATH_MSG_DEBUG( __FUNCTION__ << ": All requested ROB Ids were found in the cache. ");
327  return;
328  }
329 
330  // There were missing ROB fragments retrieve them from the DCM and add them to the cache
331  ATH_MSG_DEBUG( __FUNCTION__ << ": Number of ROB Ids to retrieve with DCM = " << robIds_missing.size());
332 
333  typedef std::vector<hltinterface::DCM_ROBInfo> ROBInfoVec;
334  ROBInfoVec vRobInfos;
335 
336  // Get ROB Fragments with DataCollector
337  vRobInfos.reserve( robIds_missing.size() ) ;
338  try {
339  auto mon_rob_t = Monitored::Timer("TIME_ROBRequest");
340  hltinterface::DataCollector::instance()->collect(vRobInfos, cache->globalEventNumber, robIds_missing);
341  mon_rob_t.stop();
342  // Fill monitoring histograms
343  auto mon_rob_nROBs = Monitored::Scalar("NUMBER_ROBRequest",vRobInfos.size());
344  auto mon = Monitored::Group(m_monTool, mon_rob_t, mon_rob_nROBs);
345  } catch (const std::exception& ex) {
346  ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
347  << "Failed to collect ROBs, caught an unexpected exception: " << ex.what()
348  << ". Throwing hltonl::Exception::EventSourceCorrupted" );
350  } catch (...) {
351  ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
352  << "Failed to collect ROBs, caught an unexpected exception. "
353  << "Throwing hltonl::Exception::EventSourceCorrupted" );
355  }
356 
357  // Store retrieved ROB data in the cache
358  std::vector<ROBF> robFragments_missing;
359  robFragments_missing.reserve( vRobInfos.size() );
360  for(ROBInfoVec::const_iterator it=vRobInfos.begin(); it!=vRobInfos.end(); ++it) {
361  ATH_MSG_DEBUG(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << it->robFragment.source_id() << MSG::dec
362  << " retrieved from DCM for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
363  robFragments_missing.push_back( it->robFragment );
364  }
365 
366  // Check if event should be monitored and monitor ROB data
367  auto monitorData = robmonitor::ROBDataMonitorStruct(cache->currentLvl1ID, std::string(callerName));
368  if (m_doCostMonitoring && m_trigCostSvcHandle->isMonitoredEvent(context, /*includeMultiSlot =*/ false)) {
369  // Monitor HLT cached ROBs
370  for (const ROBF* robFrag : robFragments) {
371  monitorData.requested_ROBs[robFrag->source_id()] = robmap_getRobData(*robFrag, robmonitor::HLT_CACHED);
372  }
373 
374  // Add the ROBs to the cache/rob map and collect ignored robs
375  std::set<uint32_t> robIds_ignored;
376  eventCache_addRobData(cache, std::move(robFragments_missing), robIds_ignored);
377 
378  // Monitor DCM ROBs
379  for (const hltinterface::DCM_ROBInfo& robInfo : vRobInfos) {
381 
382  // Check ROB history
383  if (robIds_ignored.find(robInfo.robFragment.source_id()) != robIds_ignored.end()) {
385  }
386  else {
387  status = robInfo.robIsCached ? robmonitor::DCM_CACHED : robmonitor::RETRIEVED;
388  }
389 
390  monitorData.requested_ROBs[robInfo.robFragment.source_id()] = robmap_getRobData(robInfo.robFragment, status);
391  }
392 
393  // Return all the requested ROB fragments from the cache and collect disabled ROBs
394  std::set<uint32_t> robIds_disabled;
395  eventCache_checkRobListToCache(cache, robIds, robFragments, robIds_missing, robIds_disabled);
396 
397  // Fill undefined (not enabled) ROBs
398  for (uint32_t robId : robIds_disabled) {
399  monitorData.requested_ROBs[robId] = robmonitor::ROBDataStruct(robId);
400  monitorData.requested_ROBs[robId].rob_history = robmonitor::UNDEFINED;
401  }
402  }
403  else {
404  // add the ROBs to the cache/rob map
405  eventCache_addRobData(cache, std::move(robFragments_missing)) ;
406 
407  // return all the requested ROB fragments from the cache
408  eventCache_checkRobListToCache(cache, robIds, robFragments, robIds_missing) ;
409  }
410 
411  // Save ROS processing time and pass ROS data to CostMonitor
412  if (m_doCostMonitoring && m_trigCostSvcHandle->isMonitoredEvent(context, /*includeMultiSlot =*/ false)) {
413  TrigTimeStamp rosEndTime;
414 
415  monitorData.start_time = rosStartTime.microsecondsSinceEpoch();
416  monitorData.end_time = rosEndTime.microsecondsSinceEpoch();
417 
418  // Check if ROBMonitorDataStruct is move-constructible
420  if (m_trigCostSvcHandle->monitorROS(context, std::move(monitorData)).isFailure()) {
421  ATH_MSG_WARNING("TrigCost ROS monitoring failed!");
422  }
423  }
424 }
425 
427 {
428  auto robData = robmonitor::ROBDataStruct(robFrag.source_id());
429  robData.rob_size = robFrag.fragment_size_word();
430  robData.rob_status_word = robFrag.nstatus() ? robFrag.status()[0] : 0;
431  robData.rob_history = robStatus;
432 
433  return robData;
434 }
435 
437 const RawEvent* HltROBDataProviderSvc::getEvent(const EventContext& context)
438 {
439  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
440  return m_eventsCache.get( context )->event;
441 }
442 
444 void HltROBDataProviderSvc::setEventStatus(const EventContext& context, uint32_t status)
445 {
446  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
447  m_eventsCache.get(context)->eventStatus = status;
448 }
449 
452 {
453  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
454  return m_eventsCache.get( context )->eventStatus;
455 }
456 
458 void HltROBDataProviderSvc::processCachedROBs(const EventContext& context, const std::function< void(const ROBF* )>& fn) const
459 {
460  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
461  for ( const auto& el : m_eventsCache.get( context )->robmap )
462  {
463  fn( &el.second );
464  }
465 }
466 
468 bool HltROBDataProviderSvc::isEventComplete(const EventContext& context) const
469 {
470  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
471  return m_eventsCache.get( context )->isEventComplete;
472 }
473 
475 int HltROBDataProviderSvc::collectCompleteEventData(const EventContext& context, const std::string_view callerName)
476 {
477  ATH_MSG_VERBOSE("start of " << __FUNCTION__ << " caller name = " << callerName);
478 
479  EventCache* cache = m_eventsCache.get( context );
480 
481  // lock for event cache update with DCM
482  std::lock_guard<std::mutex> lock( cache->eventCache_mtx );
483 
484  // return if event is already complete
485  if (cache->isEventComplete) return 0;
486 
487  typedef std::vector<hltinterface::DCM_ROBInfo> ROBInfoVec;
488  ROBInfoVec vRobInfos ;
489  if (!m_enabledROBs.value().empty()) {
490  vRobInfos.reserve( m_enabledROBs.value().size() ) ;
491  } else {
492  vRobInfos.reserve( MAX_ROBFRAGMENTS ) ;
493  }
494 
495  // Get ROB Fragments for complete event with DataCollector
496  try {
497  auto mon_col_t = Monitored::Timer("TIME_CollectAllROBs");
498  hltinterface::DataCollector::instance()->collect(vRobInfos, cache->globalEventNumber);
499  mon_col_t.stop();
500  ATH_MSG_DEBUG( __FUNCTION__ << ": Number of received ROB Ids = " << vRobInfos.size() );
501  // Fill monitoring histograms
502  auto mon_col_nROBs = Monitored::Scalar("NUMBER_CollectAllROBs",vRobInfos.size());
503  auto mon = Monitored::Group(m_monTool, mon_col_t, mon_col_nROBs);
504  } catch (const std::exception& ex) {
505  ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
506  << "Failed to collect complete event, caught an unexpected exception: " << ex.what()
507  << ". Throwing hltonl::Exception::EventSourceCorrupted" );
509  } catch (...) {
510  ATH_MSG_ERROR( __FUNCTION__ << ":" << __LINE__
511  << "Failed to collect complete event, caught an unexpected exception. "
512  << "Throwing hltonl::Exception::EventSourceCorrupted" );
514  }
515 
516  // Store retrieved ROB data in the cache
517  std::vector<ROBF> robFragments_missing;
518  robFragments_missing.reserve( vRobInfos.size() );
519  for(ROBInfoVec::const_iterator it=vRobInfos.begin(); it!=vRobInfos.end(); ++it) {
520  ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << it->robFragment.source_id() << MSG::dec
521  << " retrieved from DCM for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
522  robFragments_missing.push_back( it->robFragment );
523  }
524  // add the ROBs to the cache/rob map
525  eventCache_addRobData(cache, std::move(robFragments_missing)) ;
526 
527  // update event complete flag
528  cache->isEventComplete = true;
529 
530  return vRobInfos.size();
531 }
532 
535 {
536  // No filter criteria defined
537  if (m_filterRobMap.empty() && m_filterSubDetMap.empty()) {
538  return(false);
539  }
540 
541  // There should be at least one status element if there was an error
542  // in case there are 0 status elements then there was no known error
543  // (see event format document ATL-D-ES-0019 (EDMS))
544  const uint32_t* rob_it_status;
545  const uint32_t null_status(0);
546  // The ROB has no status elements
547  if (rob->nstatus() == 0) {
548  rob_it_status = &null_status;
549  } else {
550  // The ROB has at least one status element, access it via an iterator
551  rob->status(rob_it_status);
552  }
553 
554  // Build the full ROB Sourceidentifier
555  eformat::helper::SourceIdentifier tmpsrc(rob->rob_source_id());
556 
557  // Check if there is a ROB specific filter rule defined for this ROB Id and match the status code
558  FilterRobMap::iterator map_it_rob = m_filterRobMap.find(tmpsrc.code());
559  if (map_it_rob != m_filterRobMap.end()) {
560  for (auto it_status: (*map_it_rob).second) {
561  if (*rob_it_status == it_status) {
562  ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << tmpsrc.code()
563  << " with status = 0x" << *rob_it_status << MSG::dec
564  << " removed due to ROB filter rule.");
565  return(true);
566  }
567  }
568  }
569 
570  // Check if there is a sub detector specific filter rule defined for this ROB Id and match the status code
571  FilterSubDetMap::iterator map_it_subdet = m_filterSubDetMap.find(tmpsrc.subdetector_id());
572  if (map_it_subdet != m_filterSubDetMap.end()) {
573  for (auto it_status: (*map_it_subdet).second) {
574  if (*rob_it_status == it_status) {
575  ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << tmpsrc.code()
576  << " with status = 0x" << *rob_it_status << MSG::dec
577  << " removed due to SubDet filter rule.");
578  return(true);
579  }
580  }
581  }
582  return(false);
583 }
584 
586 {
587  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
588  cache->event = nullptr;
589  cache->currentLvl1ID = 0;
590  cache->globalEventNumber = 0;
591  cache->eventStatus = 0;
592  cache->isEventComplete = false;
593  { cache->robmap.clear(); }
594 }
595 
596 void HltROBDataProviderSvc::eventCache_checkRobListToCache(EventCache* cache, const std::vector<uint32_t>& robIds_toCheck,
597  std::vector<const ROBF*>& robFragments_inCache,
598  std::vector<uint32_t>& robIds_missing,
599  std::optional<std::reference_wrapper<std::set<uint32_t>>> robIds_disabled )
600 {
601  ATH_MSG_VERBOSE("start of " << __FUNCTION__ << " number of ROB Ids to check = " << robIds_toCheck.size());
602 
603  // clear output arrays
604  robFragments_inCache.clear();
605  robIds_missing.clear();
606 
607  // allocate sufficient space for output arrays
608  robFragments_inCache.reserve( robIds_toCheck.size() );
609  robIds_missing.reserve( robIds_toCheck.size() );
610 
611  // check input ROB ids
612  for (uint32_t id : robIds_toCheck) {
613 
614  // check for duplicate IDs on the list of missing ROBs
615  std::vector<uint32_t>::iterator missing_it = std::find(robIds_missing.begin(), robIds_missing.end(), id);
616  if (missing_it != robIds_missing.end()) {
617  ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id : 0x" << MSG::hex << id << MSG::dec <<" is already on the list of missing IDs.");
618  continue;
619  }
620 
621  // check if ROB is already in cache
622  { ROBMAP::const_iterator map_it = cache->robmap.find(id);
623  if (map_it != cache->robmap.end()) {
624  ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id 0x" << MSG::hex << id << MSG::dec
625  << " found for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
626  robFragments_inCache.push_back( &(map_it->second) );
627  continue;
628  }
629  }
630 
631  // check if ROB is actually enabled for readout
632  if (!m_enabledROBs.value().empty()) {
633  std::vector<uint32_t>::const_iterator rob_enabled_it =
634  std::find(m_enabledROBs.value().begin(), m_enabledROBs.value().end(),id);
635  if(rob_enabled_it == m_enabledROBs.value().end()) {
636  ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id : 0x" << MSG::hex << id << MSG::dec
637  << " will be not added, since it is not on the list of enabled ROBs.");
638  if (robIds_disabled) {
639  robIds_disabled->get().insert(id);
640  }
641  continue;
642  }
643  }
644 
645  // the ROB is not in the cache and should be eventually added
646  ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id : 0x" << MSG::hex << id << MSG::dec <<" is missing ");
647  robIds_missing.push_back( id ) ;
648  } // end loop over input ROB Ids to check
649 }
650 
651 void HltROBDataProviderSvc::eventCache_addRobData(EventCache* cache, std::vector<ROBF>&& robFragments,
652  std::optional<std::reference_wrapper<std::set<uint32_t>>> robIds_ignored)
653 {
654  ATH_MSG_VERBOSE("start of " << __FUNCTION__ << " number of ROB fragments to add = " << robFragments.size());
655 
656  for (const ROBF& rob : robFragments) {
657 
658  // Source ID
659  uint32_t id = rob.source_id();
660  ATH_MSG_VERBOSE(__FUNCTION__ << " Id = 0x" << std::hex << id << std::dec );
661 
662  // mask off the module ID for L2 and EF result for Run 1 data
663  if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
664  (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_LVL2) ) {
665  id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
666  if (!m_maskL2EFModuleID) {
667  ATH_MSG_ERROR(__FUNCTION__ << " Inconsistent flag for masking L2/EF module IDs");
668  m_maskL2EFModuleID=true;
669  }
670  } else if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
671  (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_EVENT_FILTER) &&
672  (m_maskL2EFModuleID) ) {
673  id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
674  }
675 
676  // check if ROB is already in cache
677  { ROBMAP::const_iterator it = cache->robmap.find(id);
678  if (it != cache->robmap.end()) {
679  ATH_MSG_VERBOSE(__FUNCTION__ << " Duplicate ROB Id 0x" << MSG::hex << id << MSG::dec
680  << " found for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
681  continue;
682  }
683  }
684 
685  // filter ROBs with external criteria
686  if (robmap_filterRobWithStatus(&rob)) {
687  if (rob.nstatus() > 0) {
688  const uint32_t* it_status;
689  rob.status(it_status);
690  eformat::helper::Status tmpstatus(*it_status);
691  ATH_MSG_VERBOSE(__FUNCTION__ << " ROB Id = 0x" << MSG::hex << id << std::setfill('0')
692  << " with Generic Status Code = 0x" << std::setw(4) << tmpstatus.generic()
693  << " and Specific Status Code = 0x" << std::setw(4) << tmpstatus.specific() << MSG::dec
694  << " removed for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
695  }
696  if (robIds_ignored) {
697  robIds_ignored->get().insert(id);
698  }
699  continue;
700  }
701 
702  // check for ROBs with no data
703  if ((rob.rod_ndata() == 0) && (m_filterEmptyROB)) {
704  ATH_MSG_VERBOSE(__FUNCTION__ << " Empty ROB Id = 0x" << MSG::hex << id << MSG::dec
705  << " removed for (global Id, L1 Id) = (" << cache->globalEventNumber << "," << cache->currentLvl1ID <<")" );
706  continue;
707  }
708 
709  // add ROB to map
710  { cache->robmap.insert(std::make_pair(id,std::move(rob))); }
711  }
712 }
713 
715 {
716  // delete event;
717  { robmap.clear(); }
718 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
HltROBDataProviderSvc::finalize
virtual StatusCode finalize() override
Definition: HltROBDataProviderSvc.cxx:192
robmonitor::UNDEFINED
@ UNDEFINED
Definition: ROBDataMonitor.h:32
robmonitor::ROBDataMonitorStruct
The structure which is used to monitor the ROB data request in L2 It is created for every addROBData ...
Definition: ROBDataMonitor.h:81
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
TrigDefs::Group
Group
Properties of a chain group.
Definition: GroupProperties.h:13
HltROBDataProviderSvc::setNextEvent
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...
Definition: HltROBDataProviderSvc.cxx:239
get_generator_info.result
result
Definition: get_generator_info.py:21
HltROBDataProviderSvc::getEventStatus
virtual uint32_t getEventStatus(const EventContext &) override
Retrieve the status for the event.
Definition: HltROBDataProviderSvc.cxx:451
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:557
HltExceptions.h
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
robmonitor::ROBDataStruct
A structure with data about ROB properties.
Definition: ROBDataMonitor.h:39
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
HltROBDataProviderSvc.h
Service to serve ROB data in online environment.
hltonl::Exception::EventSourceCorrupted
Thrown if event source throws an exception when new event is requested.
Definition: HltExceptions.h:33
robmonitor::ROBHistory
ROBHistory
A structure with data about ROB properties.
Definition: ROBDataMonitor.h:26
HltROBDataProviderSvc::getROBData
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.
Definition: HltROBDataProviderSvc.cxx:304
HltROBDataProviderSvc::m_eventsCache
SG::SlotSpecificObj< EventCache > m_eventsCache
An event cache for each slot.
Definition: HltROBDataProviderSvc.h:104
robmonitor::DCM_CACHED
@ DCM_CACHED
Definition: ROBDataMonitor.h:30
HltROBDataProviderSvc::m_filterSubDetMap
FilterSubDetMap m_filterSubDetMap
Definition: HltROBDataProviderSvc.h:122
HltROBDataProviderSvc::m_prefetchAllROBsfromROS
Gaudi::Property< bool > m_prefetchAllROBsfromROS
Definition: HltROBDataProviderSvc.h:141
RawEvent
OFFLINE_FRAGMENTS_NAMESPACE::FullEventFragment RawEvent
data type for reading raw event
Definition: RawEvent.h:37
HltROBDataProviderSvc::EventCache
struct which provides the event cache for each slot
Definition: HltROBDataProviderSvc.h:91
skel.it
it
Definition: skel.GENtoEVGEN.py:423
HltROBDataProviderSvc::EventCache::~EventCache
~EventCache()
Definition: HltROBDataProviderSvc.cxx:714
HltROBDataProviderSvc::EventCache::event
const RawEvent * event
Definition: HltROBDataProviderSvc.h:93
HltROBDataProviderSvc::m_filterEmptyROB
Gaudi::Property< bool > m_filterEmptyROB
Filter out empty ROB fragments which are send by the ROS.
Definition: HltROBDataProviderSvc.h:125
athena.value
value
Definition: athena.py:124
HltROBDataProviderSvc::robmap_getRobData
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
Definition: HltROBDataProviderSvc.cxx:426
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
python.selector.AtlRunQuerySelectorLhcOlc.sd
sd
Definition: AtlRunQuerySelectorLhcOlc.py:612
instance
std::map< std::string, double > instance
Definition: Run_To_Get_Tags.h:8
HltROBDataProviderSvc::EventCache::robmap
ROBMAP robmap
Definition: HltROBDataProviderSvc.h:98
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
robmonitor::IGNORED
@ IGNORED
Definition: ROBDataMonitor.h:31
OFFLINE_FRAGMENTS_NAMESPACE::PointerType
const DataType * PointerType
Definition: RawEvent.h:25
SG::SlotSpecificObj
Maintain a set of objects, one per slot.
Definition: AthenaKernel/AthenaKernel/SlotSpecificObj.h:70
python.getCurrentFolderTag.fn
fn
Definition: getCurrentFolderTag.py:65
HltROBDataProviderSvc::processCachedROBs
virtual void processCachedROBs(const EventContext &, const std::function< void(const ROBF *)> &) const override
Apply a function to all ROBs in the cache.
Definition: HltROBDataProviderSvc.cxx:458
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
HltROBDataProviderSvc::initialize
virtual StatusCode initialize() override
Definition: HltROBDataProviderSvc.cxx:30
eformat::ROBFragment
Definition: L1CaloBsDecoderUtil.h:12
lumiFormat.i
int i
Definition: lumiFormat.py:85
TrigTimeStamp
utility class to measure time duration in AthenaMT The pattern when it is useful: AlgA tags the begin...
Definition: TrigTimeStamp.h:23
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
HltROBDataProviderSvc::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Monitoring tool.
Definition: HltROBDataProviderSvc.h:205
calibdata.exception
exception
Definition: calibdata.py:496
plotIsoValidation.el
el
Definition: plotIsoValidation.py:197
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
HltROBDataProviderSvc::eventCache_clear
void eventCache_clear(EventCache *)
method to clear an event cache in a slot input: pointer to cache
Definition: HltROBDataProviderSvc.cxx:585
HltROBDataProviderSvc::m_maskL2EFModuleID
bool m_maskL2EFModuleID
For Run 1 the module ID for the Lvl2/EF result contained the machine ID and needed to be filtered out...
Definition: HltROBDataProviderSvc.h:130
HltROBDataProviderSvc::m_prefetchSubDetROS
Gaudi::Property< std::vector< uint8_t > > m_prefetchSubDetROS
Definition: HltROBDataProviderSvc.h:149
HltROBDataProviderSvc::EventCache::eventStatus
uint32_t eventStatus
Definition: HltROBDataProviderSvc.h:96
HltROBDataProviderSvc::m_readROBfromOKS
Gaudi::Property< bool > m_readROBfromOKS
Definition: HltROBDataProviderSvc.h:133
HltROBDataProviderSvc::m_filterRobMap
FilterRobMap m_filterRobMap
Definition: HltROBDataProviderSvc.h:119
HltROBDataProviderSvc::m_filterSubDetWithStatus
Gaudi::Property< ArrayPairIntType > m_filterSubDetWithStatus
Definition: HltROBDataProviderSvc.h:114
TrigTimeStamp::microsecondsSinceEpoch
uint64_t microsecondsSinceEpoch() const
Definition: TrigTimeStamp.cxx:15
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
HltROBDataProviderSvc::m_doCostMonitoring
Gaudi::Property< bool > m_doCostMonitoring
Definition: HltROBDataProviderSvc.h:154
HltROBDataProviderSvc::setEventStatus
virtual void setEventStatus(const EventContext &, uint32_t) override
Store the status for the event.
Definition: HltROBDataProviderSvc.cxx:444
HltROBDataProviderSvc::m_trigCostSvcHandle
ServiceHandle< ITrigCostSvc > m_trigCostSvcHandle
Definition: HltROBDataProviderSvc.h:157
HltROBDataProviderSvc::ROBF
OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment ROBF
ROB Fragment class.
Definition: HltROBDataProviderSvc.h:41
robmonitor::RETRIEVED
@ RETRIEVED
Definition: ROBDataMonitor.h:28
robmonitor::HLT_CACHED
@ HLT_CACHED
Definition: ROBDataMonitor.h:29
HltROBDataProviderSvc::eventCache_addRobData
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...
Definition: HltROBDataProviderSvc.cxx:651
Athena::Status
Status
Athena specific StatusCode values.
Definition: AthStatusCode.h:22
HltROBDataProviderSvc::addROBData
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.
Definition: HltROBDataProviderSvc.cxx:201
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
HltROBDataProviderSvc::EventCache::globalEventNumber
uint64_t globalEventNumber
Definition: HltROBDataProviderSvc.h:95
HltROBDataProviderSvc::HltROBDataProviderSvc
HltROBDataProviderSvc(const std::string &name, ISvcLocator *pSvcLocator)
Definition: HltROBDataProviderSvc.cxx:25
HltROBDataProviderSvc::isEventComplete
virtual bool isEventComplete(const EventContext &) const override
Flag to check if all event data have been retrieved.
Definition: HltROBDataProviderSvc.cxx:468
SG::getNSlots
size_t getNSlots()
Return the number of event slots.
Definition: SlotSpecificObj.cxx:64
re
const boost::regex re(r_e)
plotBeamSpotMon.mon
mon
Definition: plotBeamSpotMon.py:67
HltROBDataProviderSvc::collectCompleteEventData
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...
Definition: HltROBDataProviderSvc.cxx:475
HltROBDataProviderSvc::EventCache::eventCache_mtx
std::mutex eventCache_mtx
mutex for ROB cache updates
Definition: HltROBDataProviderSvc.h:100
merge.status
status
Definition: merge.py:17
HltROBDataProviderSvc::getEvent
virtual const RawEvent * getEvent(const EventContext &) override
Retrieve the full event fragment.
Definition: HltROBDataProviderSvc.cxx:437
HltROBDataProviderSvc::m_enabledROBs
Gaudi::Property< std::vector< uint32_t > > m_enabledROBs
Definition: HltROBDataProviderSvc.h:137
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
HltROBDataProviderSvc::m_filterRobWithStatus
Gaudi::Property< ArrayPairIntType > m_filterRobWithStatus
Definition: HltROBDataProviderSvc.h:112
TrigTimeStamp.h
HltROBDataProviderSvc::EventCache::isEventComplete
bool isEventComplete
Definition: HltROBDataProviderSvc.h:97
HltROBDataProviderSvc::EventCache::currentLvl1ID
uint32_t currentLvl1ID
Definition: HltROBDataProviderSvc.h:94
HltROBDataProviderSvc::m_prefetchWholeROSList
std::vector< uint32_t > m_prefetchWholeROSList
Definition: HltROBDataProviderSvc.h:152
Monitored::Timer
A monitored timer.
Definition: MonitoredTimer.h:32
HltROBDataProviderSvc::robmap_filterRobWithStatus
bool robmap_filterRobWithStatus(const ROBF *)
method to filter ROBs with given Status code
Definition: HltROBDataProviderSvc.cxx:534
ServiceHandle< Gaudi::Interfaces::IOptionsSvc >
HltROBDataProviderSvc::eventCache_checkRobListToCache
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...
Definition: HltROBDataProviderSvc.cxx:596