ATLAS Offline Software
Loading...
Searching...
No Matches
ROBDataProviderSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5//===================================================================
6// Implementation of ROBDataProviderSvc
7// Revision: November 2017
8// MT readiness
9// Revision: July 11, 2002
10// Modified for eformat
11// Revision: Aug 18, 2003
12// Modified to use ROBFragments directly and include methods
13// for online
14// Revision: Apr 21, 2005
15// Remove dependency on Level-2 Data Collector, create special
16// version for online
17// Revision: Oct 29, 2006
18// Increase MAX_ROBFRAGMENTS to 2048 to cover the special case
19// when in a "localhost" partition the complete event is given
20// to the Event Filter as one single ROS fragment (this case
21// should not happen for normal running when several ROSes are
22// used and the ROB fragments are grouped under different ROS
23// fragments)
24// Revision: Nov 10, 2008
25// Mask off the module ID from the ROB source identifier of the
26// L2 and EF result when storing it in the ROB map. This is necessary
27// when the L2/PT node ID is stored in the source identifier as
28// module ID. With this modification the L2 and EF result can still be
29// found as 0x7b0000 and 0x7c0000
30// Revision: Jan 12, 2009
31// Allow removal of individual ROBs and ROBs from given subdetectors
32// from the internal ROB map according to a given status code.
33// This may be necessary when corrupted and incomplete ROB fragments
34// are forwarded to the algorithms and the converters are not yet
35// prepared to handle the specific cases.
36// The filtering can be configured with job options as:
37//
38// for individual ROBs as :
39// ------------------------
40// ROBDataProviderSvc.filterRobWithStatus = [ (ROB SourceId, StatusCode to remove),
41// (ROB SourceId 2, StatusCode to remove 2), ... ]
42// and:
43// ROBDataProviderSvc.filterRobWithStatus += [ (ROB SourceId n, StatusCode to remove n) ]
44//
45// Example:
46// ROBDataProviderSvc.filterRobWithStatus = [ (0x42002a,0x0000000f), (0x42002e,0x00000008) ]
47// ROBDataProviderSvc.filterRobWithStatus += [ (0x42002b,0x00000000) ]
48//
49// for all ROBs of a given sub detector as :
50// -----------------------------------------
51// ROBDataProviderSvc.filterSubDetWithStatus = [ (Sub Det Id, StatusCode to remove),
52// (Sub Det Id 2, StatusCode to remove 2), ... ]
53// and:
54// ROBDataProviderSvc.filterSubDetWithStatus += [ (Sub Det Id n, StatusCode to remove n) ]
55//
56// Example:
57// ROBDataProviderSvc.filterSubDetWithStatus = [ (0x41,0x00000000), (0x42,0x00000000) ]
58// ROBDataProviderSvc.filterSubDetWithStatus += [ (0x41,0xcb0002) ]
59//
60// For valid ROB Source Ids, Sub Det Ids and ROB Status elements see the event format
61// document ATL-D-ES-0019 (EDMS)
62// Revision: Jan 28, 2014
63// For Run 1 the module ID from the ROB source identifier of the
64// L2 and EF result needed to be masked off before storing the ROB fragment
65// in the ROB map. The module ID for these fragments contained an identifier
66// of the machine on which they were produced. This produced as many different ROB IDs
67// for these fragments as HLT processors were used. The module IDs were not useful
68// for analysis and needed to be masked off from these fragments in the ROB map in order
69// to allow the access to the L2 or the EF result with the generic identifiers
70// 0x7b0000 and 0x7c0000. Also an event contained only one L2 and EF result.
71// From Run 2 on (eformat version 5) the HLT processor identifier is not anymore
72// stored in the module ID of the HLT result. Further there can be in one event several HLT result
73// records with the source identifier 0x7c. The different HLT results are distinguished
74// now with the module ID. A module ID 0 indicates a physiscs HLT result as before, while
75// HLT results with module IDs different from zero are produced by data scouting chains.
76// In Run 2 the module ID should be therefore not any more masked.
77// The masking of the moduleID is switched on when a L2 result is found in the event or the
78// event header contains L2 trigger info words. This means the data were produced with run 1 HLT system.
79//
80//===================================================================
81
82// Include files.
84#include "eformat/Status.h"
85
86// Constructor.
87ROBDataProviderSvc::ROBDataProviderSvc(const std::string& name, ISvcLocator* svcloc)
88 : base_class(name, svcloc) {}
89
90
91// Initialization
93 ATH_MSG_INFO("Initializing");
95
96 for (unsigned int i = 0; i < m_filterRobWithStatus.value().size(); i++) {
97 eformat::helper::SourceIdentifier tmpsrc(m_filterRobWithStatus.value()[i].first);
98 if (tmpsrc.human_detector() != "UNKNOWN") {
99 m_filterRobMap[tmpsrc.code()].push_back(m_filterRobWithStatus.value()[i].second);
100 }
101 }
102 for (unsigned int i = 0; i < m_filterSubDetWithStatus.value().size(); i++) {
103 eformat::helper::SourceIdentifier tmpsrc((eformat::SubDetector)m_filterSubDetWithStatus.value()[i].first, 0);
104 if (tmpsrc.human_detector() != "UNKNOWN") {
105 m_filterSubDetMap[tmpsrc.subdetector_id()].push_back(m_filterSubDetWithStatus.value()[i].second);
106 }
107 }
108 ATH_MSG_INFO(" ---> Filter out empty ROB fragments = " << m_filterEmptyROB);
109 ATH_MSG_INFO(" ---> Filter out specific ROBs by Status Code: # ROBs = " << m_filterRobMap.size());
110 for (const auto& p : m_filterRobMap) {
111 eformat::helper::SourceIdentifier tmpsrc(p.first);
112 ATH_MSG_INFO(" RobId=0x" << MSG::hex << p.first << " -> in Sub Det = " << tmpsrc.human_detector());
113 for (uint32_t status : p.second) {
114 eformat::helper::Status tmpstatus(status);
115 ATH_MSG_INFO(" Status Code=0x"
116 << MSG::hex << std::setfill( '0' ) << std::setw(8) << tmpstatus.code()
117 << " Generic Part=0x" << std::setw(4) << tmpstatus.generic()
118 << " Specific Part=0x" << std::setw(4) << tmpstatus.specific());
119 }
120 }
121
122 ATH_MSG_INFO(" ---> Filter out Sub Detector ROBs by Status Code: # Sub Detectors = " << m_filterSubDetMap.size());
123 for (const auto& p : m_filterSubDetMap) {
124 eformat::helper::SourceIdentifier tmpsrc(p.first, 0);
125 ATH_MSG_INFO(" SubDetId=0x" << MSG::hex << p.first << " -> " << tmpsrc.human_detector());
126 for (uint32_t status : p.second) {
127 eformat::helper::Status tmpstatus(status);
128 ATH_MSG_INFO(" Status Code=0x"
129 << MSG::hex << std::setfill( '0' ) << std::setw(8) << tmpstatus.code()
130 << " Generic Part=0x" << std::setw(4) << tmpstatus.generic()
131 << " Specific Part=0x" << std::setw(4) << tmpstatus.specific());
132 }
133 }
134 return(StatusCode::SUCCESS);
135}
136
137
142
143void ROBDataProviderSvc::addROBData(const EventContext& context, const std::vector<uint32_t>& robIds, const std::string_view callerName) {
144 EventCache* cache = m_eventsCache.get( context );
145
146 // Copy missing ROB ids to vector with pthread allocator
147 ATH_MSG_DEBUG(" ---> Number of ROB Id s requested : " << robIds.size() << ", Caller Name = " << callerName);
148 // for offline running all requested ROBs should be found in cache
149 // if not issue error
150 for (uint32_t id : robIds) {
151 // mask off the module ID for L2 and EF result for Run 1 data
152 if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
153 (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_LVL2) ) {
154 id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
155 // TB if it is inconsistent we should not continue like this?
156 if ( !m_maskL2EFModuleID ) {
157 ATH_MSG_ERROR("Inconsistent flag for masking L2/EF module IDs");
159 }
160 } else if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
161 (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_EVENT_FILTER) &&
162 ( m_maskL2EFModuleID ) ) {
163 id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
164 }
165 ROBMAP& robmap( cache->robmap );
166 ROBMAP::iterator map_it = robmap.find(id) ;
167 if (map_it != robmap.end()) {
168 ATH_MSG_DEBUG(" ---> Found ROB Id : 0x" << MSG::hex << (*map_it).second->source_id()
169 << MSG::dec << " in cache");
170 } else {
171 ATH_MSG_DEBUG(" ---> ROB Id : 0x" << MSG::hex << id
172 << MSG::dec << " not found in cache for running mode OFFLINE (method addROBData),");
173 ATH_MSG_DEBUG(" Lvl1 id = " << cache->currentLvl1ID);
174 }
175 }
176 return;
177}
178
182void ROBDataProviderSvc::setNextEvent(const EventContext& /*context*/, const std::vector<ROBF>& result) {
183 // clear the old map
184 // TB honestly, why do any action if this is FATAL mistake
185 // robmapClear( m_eventsCache.get(context)->robmap );
186
187 // This method should never be used by offline
188 ATH_MSG_FATAL(" +-----------------------------------------------------------------+ ");
189 ATH_MSG_FATAL(" | The method ROBDataProviderSvc::setNextEvent(const ROBF* result) | ");
190 ATH_MSG_FATAL(" | is not implemented for this version of ROBDataProviderSvc | ");
191 ATH_MSG_FATAL(" | Use the version from the HLT repository if you need it. | ");
192 ATH_MSG_FATAL(" +-----------------------------------------------------------------+ ");
193 ATH_MSG_FATAL(" ---> The " << result.size() << " ROB fragments in the call will not be used.");
194 return;
195}
196
197
198
199
203
204void ROBDataProviderSvc::setNextEvent( const EventContext& context, const RawEvent* re ) {
205 EventCache* cache = m_eventsCache.get( context );
206
207 cache->event=re;
208 // clear the old map
209 robmapClear( cache->robmap );
210 // set the LVL1 id
211 cache->currentLvl1ID = re->lvl1_id();
212 // set flag for masking L2/EF module ID, this is only necessary for the separate L2 and EF systems from Run 1
213 m_maskL2EFModuleID = (re->nlvl2_trigger_info() != 0);
214
215 // get all the ROBFragments
216 constexpr size_t MAX_ROBFRAGMENTS = 4096;
217 std::vector<OFFLINE_FRAGMENTS_NAMESPACE::PointerType> robF(MAX_ROBFRAGMENTS);
219 re->start(rePointer);
220 size_t robcount = re->children(robF.data(), MAX_ROBFRAGMENTS);
221 if (robcount == MAX_ROBFRAGMENTS) {
222 ATH_MSG_ERROR("ROB buffer overflow");
223 }
224 // loop over all ROBs
225 for (size_t irob = 0; irob < robcount; irob++) {
226 // add to the map
227 //const ROBF* rob = new ROBF(robF[irob]);
228 std::unique_ptr<const ROBF> rob=std::make_unique<const ROBF>(robF[irob]);
229 uint32_t id = rob->source_id();
230 // mask off the module ID for L2 and EF result for Run 1 data
231 if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
232 (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_LVL2) ) {
233 id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
234 if (!m_maskL2EFModuleID) {
235 ATH_MSG_ERROR("Inconsistent flag for masking L2/EF module IDs");
237 }
238 } else if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
239 (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_EVENT_FILTER) &&
241 id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
242 }
243 if (filterRobWithStatus(rob.get())) {
244 if (rob->nstatus() > 0) {
245 const uint32_t* it_status;
246 rob->status(it_status);
247 eformat::helper::Status tmpstatus(*it_status);
248 ATH_MSG_DEBUG(" ---> ROB Id = 0x" << MSG::hex << id << std::setfill('0')
249 << " with Generic Status Code = 0x" << std::setw(4) << tmpstatus.generic()
250 << " and Specific Status Code = 0x" << std::setw(4) << tmpstatus.specific() << MSG::dec
251 << " removed for L1 Id = " << cache->currentLvl1ID);
252 }
253 rob.reset();
254 } else if ((rob->rod_ndata() == 0) && (m_filterEmptyROB.value())) {
255 ATH_MSG_DEBUG( " ---> Empty ROB Id = 0x" << MSG::hex << id << MSG::dec
256 << " removed for L1 Id = " << cache->currentLvl1ID);
257 rob.reset();
258 } else {
259 ROBMAP::const_iterator it = cache->robmap.find(id);
260 if (it != cache->robmap.end()) {
261 ATH_MSG_WARNING(" ROBDataProviderSvc:: Duplicate ROBID 0x" << MSG::hex << id
262 << " found. " << MSG::dec << " Overwriting the previous one ");
263 }
264 cache->robmap[id]=std::move(rob);
265
266 }
267 }
268 ATH_MSG_DEBUG(" ---> setNextEvent offline for " << name() );
269 ATH_MSG_DEBUG(" current LVL1 id = " << cache->currentLvl1ID );
270 ATH_MSG_DEBUG(" size of ROB cache = " << cache->robmap.size() );
271 return;
272}
273
275
276void ROBDataProviderSvc::getROBData(const EventContext& context, const std::vector<uint32_t>& ids, std::vector<const ROBF*>& v,
277 const std::string_view callerName) {
278 EventCache* cache = m_eventsCache.get( context );
279
280 for (uint32_t id : ids) {
281 // mask off the module ID for L2 and EF result for Run 1 data
282 if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
283 (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_LVL2) ) {
284 id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
285 if (!m_maskL2EFModuleID) {
286 ATH_MSG_ERROR("Inconsistent flag for masking L2/EF module IDs");
288 }
289 } else if ( (eformat::helper::SourceIdentifier(id).module_id() != 0) &&
290 (eformat::helper::SourceIdentifier(id).subdetector_id() == eformat::TDAQ_EVENT_FILTER) &&
292 id = eformat::helper::SourceIdentifier(eformat::helper::SourceIdentifier(id).subdetector_id(),0).code();
293 }
294 ROBMAP::iterator map_it = cache->robmap.find(id);
295 if (map_it != cache->robmap.end()) {
296 v.push_back((*map_it).second.get());
297 } else {
298 ATH_MSG_DEBUG("Failed to find ROB for id 0x" << MSG::hex << id << MSG::dec << ", Caller Name = " << callerName);
299#ifndef NDEBUG
300 int nrob = 0;
301 ATH_MSG_VERBOSE(" --- Dump of ROB cache ids --- total size = " << cache->robmap.size());
302 for (const auto& p : cache->robmap) {
303 ++nrob;
304 ATH_MSG_VERBOSE(" # = " << nrob << " id = 0x" << MSG::hex << p.second->source_id() << MSG::dec);
305 }
306#endif
307 }
308 }
309 return;
310}
311
314 for (auto& it : toclear) {
315 it.second.reset();
316 }
317 toclear.clear();
318}
319
320const RawEvent* ROBDataProviderSvc::getEvent( const EventContext& context ) {
321
322 return m_eventsCache.get( context )->event;
323}
324
325
327
328void ROBDataProviderSvc::setEventStatus(const EventContext& context, uint32_t status) {
329 m_eventsCache.get(context)->eventStatus = status;
330}
331
332
333uint32_t ROBDataProviderSvc::getEventStatus( const EventContext& context ) {
334 return m_eventsCache.get( context )->eventStatus;
335}
336
337void ROBDataProviderSvc::processCachedROBs(const EventContext& context,
338 const std::function< void(const ROBF* )>& fn ) const {
339 for ( const auto& el : m_eventsCache.get( context )->robmap ) {
340 fn( el.second.get() );
341 }
342}
343
344
345
349 // No filter criteria defined
350 if ((m_filterRobMap.size() == 0) && (m_filterSubDetMap.size() == 0)) {
351 return(false);
352 }
353 // There should be at least one status element if there was an error
354 // in case there are 0 status elements then there was no known error
355 // (see event format document ATL-D-ES-0019 (EDMS))
356 if (rob->nstatus() == 0) {
357 return(false);
358 }
359 // The ROB has at least one status element, access it via an iterator
360 const uint32_t* rob_it_status;
361 rob->status(rob_it_status);
362 // Build the full ROB Sourceidentifier
363 eformat::helper::SourceIdentifier tmpsrc(rob->rob_source_id());
364 // Check if there is a ROB specific filter rule defined for this ROB Id and match the status code
365 FilterRobMap::iterator map_it_rob = m_filterRobMap.find(tmpsrc.code());
366 if (map_it_rob != m_filterRobMap.end()) {
367 for (uint32_t status : map_it_rob->second) {
368 if (*rob_it_status == status) {
369 return(true);
370 }
371 }
372 }
373 // Check if there is a sub detector specific filter rule defined for this ROB Id and match the status code
374 FilterSubDetMap::iterator map_it_subdet = m_filterSubDetMap.find(tmpsrc.subdetector_id());
375 if (map_it_subdet != m_filterSubDetMap.end()) {
376 for (uint32_t status : map_it_subdet->second) {
377 if (*rob_it_status == status) {
378 return(true);
379 }
380 }
381 }
382 return(false);
383}
const boost::regex re(r_e)
#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
OFFLINE_FRAGMENTS_NAMESPACE::FullEventFragment RawEvent
data type for reading raw event
Definition RawEvent.h:37
virtual void setNextEvent(const EventContext &context, const std::vector< OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment > &result) override
Add a given LVL1/LVL2 ROBFragment to cache.
virtual void setEventStatus(const EventContext &context, uint32_t status) override
Store the status for the event.
std::map< uint32_t, std::unique_ptr< const ROBF >, std::less< uint32_t > > ROBMAP
vector of ROBFragment class
Gaudi::Property< ArrayPairIntType > m_filterSubDetWithStatus
virtual StatusCode initialize() override
initialize the service
virtual void addROBData(const EventContext &context, const std::vector< uint32_t > &robIds, const std::string_view callerName="UNKNOWN") override
Add ROBFragments to cache for given ROB ids, ROB fragments may be retrieved with DataCollector.
Gaudi::Property< ArrayPairIntType > m_filterRobWithStatus
Gaudi::Property< bool > m_filterEmptyROB
Filter out empty ROB fragments which are send by the ROS.
virtual void getROBData(const EventContext &context, const std::vector< uint32_t > &robIds, VROBFRAG &robFragments, const std::string_view callerName="UNKNOWN") override
Retrieve ROBFragments for given ROB ids from cache.
ROBDataProviderSvc(const std::string &name, ISvcLocator *svcloc)
Constructor.
virtual void processCachedROBs(const EventContext &context, const std::function< void(const ROBF *)> &fn) const override
static void robmapClear(ROBMAP &toclear)
bool filterRobWithStatus(const ROBF *rob)
method to filter ROBs with given Status code
virtual uint32_t getEventStatus(const EventContext &context) override
Retrieve the status for the event.
OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment ROBF
ROB Fragment class.
SG::SlotSpecificObj< EventCache > m_eventsCache
virtual const RawEvent * getEvent(const EventContext &context) override
Retrieve the whole event.
FilterSubDetMap m_filterSubDetMap
Maintain a set of objects, one per slot.
const DataType * PointerType
Definition RawEvent.h:25
size_t getNSlots()
Return the number of event slots.