ATLAS Offline Software
Loading...
Searching...
No Matches
TrigByteStreamInputSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Trigger includes
8
9// Athena includes
12
13// TDAQ includes
14#include "hltinterface/DataCollector.h"
15
16// System includes
17#include <charconv>
18
19namespace {
20 constexpr float wordsToKiloBytes = 0.001*sizeof(uint32_t);
21}
22
23// =============================================================================
24// Standard constructor
25// =============================================================================
26TrigByteStreamInputSvc::TrigByteStreamInputSvc(const std::string& name, ISvcLocator* svcLoc)
27: base_class(name, svcLoc) {}
28
29// =============================================================================
30// Standard destructor
31// =============================================================================
33
34// =============================================================================
35// Implementation of Service::initialize
36// =============================================================================
38 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
39
41 ATH_CHECK(m_evtStore.retrieve());
42 if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
43
44 ATH_MSG_VERBOSE("end of " << __FUNCTION__);
45 return StatusCode::SUCCESS;
46}
47
48// =============================================================================
49// Implementation of Service::finalize
50// =============================================================================
52 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
53 if (m_robDataProviderSvc.release().isFailure()) {
54 ATH_MSG_WARNING("Cannot release rob data provider");
55 }
56 ATH_MSG_VERBOSE("end of " << __FUNCTION__);
57 return StatusCode::SUCCESS;
58}
59
60// =============================================================================
61// Implementation of ByteStreamInputSvc::nextEvent
62// =============================================================================
64 ATH_MSG_VERBOSE("start of " << __FUNCTION__);
65
66 // Get the EventContext via event store because the interface doesn't allow passing it explicitly as an argument
67 // and we don't want to use ThreadLocalContext. Don't use ReadHandle here because it calls ThreadLocalContext if
68 // not given a context (which we want to retrieve).
69 const EventContext* eventContext = nullptr;
70 if (m_evtStore->retrieve(eventContext).isFailure()) {
71 ATH_MSG_ERROR("Failed to retrieve EventContext from the event store, new event cannot be read");
72 return nullptr;
73 }
74
75 ATH_MSG_DEBUG("Reading new event for event context " << *eventContext);
76
77 // Find the cache corresponding to the current slot
78 EventCache* cache = m_eventsCache.get(*eventContext);
79
80 // Free the memory allocated to the previous event processed in the current slot
81 cache->releaseEvent();
82
83 using DCStatus = hltinterface::DataCollector::Status;
84 DCStatus status = DCStatus::NO_EVENT;
85 auto monLBN = Monitored::Scalar<uint16_t>("getNext_LBN", m_maxLB);
86 auto monNoEvent = Monitored::Scalar<bool>("getNext_noEvent", false);
87 try {
88 auto t_getNext = Monitored::Timer<std::chrono::duration<float, std::milli>>("TIME_getNext");
89 status = hltinterface::DataCollector::instance()->getNext(cache->rawData);
90 auto mon = Monitored::Group(m_monTool, t_getNext);
91 }
92 catch (const std::exception& ex) {
93 ATH_MSG_ERROR("Failed to read new event, caught an unexpected exception: " << ex.what()
94 << ". Throwing hltonl::Exception::EventSourceCorrupted" );
96 }
97 catch (...) {
98 ATH_MSG_ERROR("Failed to read new event, caught an unexpected exception. "
99 << "Throwing hltonl::Exception::EventSourceCorrupted" );
101 }
102
103 if (status == DCStatus::STOP) {
104 ATH_MSG_DEBUG("DataCollector::getNext returned STOP - no more events available");
106 }
107 else if (status == DCStatus::NO_EVENT) {
108 ATH_MSG_DEBUG("DataCollector::getNext returned NO_EVENT - no events available temporarily");
109 monNoEvent = true;
110 auto mon = Monitored::Group(m_monTool, monLBN, monNoEvent);
112 }
113 else if (status != DCStatus::OK) {
114 ATH_MSG_ERROR("Unhandled return Status " << static_cast<int>(status) << " from DataCollector::getNext");
115 return nullptr;
116 }
117 ATH_MSG_VERBOSE("DataCollector::getNext returned Status::OK");
118
119 // Create a cached FullEventFragment object from the cached raw data
120 cache->fullEventFragment.reset(new RawEvent(cache->rawData.get()));
121
122 // Update LB number for monitoring
123 if (m_maxLB < cache->fullEventFragment->lumi_block()) {
124 m_maxLB = cache->fullEventFragment->lumi_block();
125 monLBN = m_maxLB;
126 }
127
128 // Monitor the input
129 auto numROBs = Monitored::Scalar<int>("L1Result_NumROBs",
130 cache->fullEventFragment->nchildren());
131 auto fragSize = Monitored::Scalar<float>("L1Result_FullEvFragSize",
132 cache->fullEventFragment->fragment_size_word()*wordsToKiloBytes);
133 std::vector<eformat::read::ROBFragment> robVec;
134 cache->fullEventFragment->robs(robVec);
135 std::vector<std::string> subdetNameVec;
136 for (const eformat::read::ROBFragment& rob : robVec) {
137 eformat::helper::SourceIdentifier sid(rob.rob_source_id());
138 subdetNameVec.push_back(sid.human_detector());
139 }
140 auto subdets = Monitored::Collection<std::vector<std::string>>("L1Result_SubDets", subdetNameVec);
141 auto mon = Monitored::Group(m_monTool, numROBs, fragSize, subdets, monLBN, monNoEvent);
142
143 // Give the FullEventFragment pointer to ROBDataProviderSvc
144 m_robDataProviderSvc->setNextEvent(*eventContext, cache->fullEventFragment.get());
145 ATH_MSG_VERBOSE("end of " << __FUNCTION__);
146
147 // Check the CTP fragment (request from readout if not part of the cache), ATR-25217
148 if (m_checkCTPFragmentModuleID.value() >= 0) {
149 const eformat::helper::SourceIdentifier sid{eformat::SubDetector::TDAQ_CTP,
150 static_cast<uint16_t>(m_checkCTPFragmentModuleID.value())};
151 std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*> vrobf;
152 m_robDataProviderSvc->getROBData(*eventContext, {sid.code()}, vrobf, name());
153 if (vrobf.empty()) {
154 ATH_MSG_INFO("The CTP ROB fragment 0x" << std::hex << sid.code() << std::dec << " is missing. "
155 << "Throwing hltonl::Exception::MissingCTPFragment");
157 }
158 uint32_t robStatus = vrobf.at(0)->nstatus()>0 ? *(vrobf.at(0)->status()) : 0;
159 if (robStatus!=0) {
160 std::string hexStatus(8, char{0});
161 std::to_chars(hexStatus.data(), hexStatus.data()+hexStatus.size(), robStatus, 16);
162 ATH_MSG_INFO("The CTP ROB fragment 0x" << std::hex << sid.code() << std::dec << " has non-zero status word: 0x"
163 << hexStatus << ". Throwing hltonl::Exception::BadCTPFragment");
164 throw hltonl::Exception::BadCTPFragment("Non-zero ROB status 0x"+hexStatus);
165 }
166 try {
167 vrobf.at(0)->check();
168 }
169 catch (const std::exception& ex) {
170 ATH_MSG_INFO("The CTP ROB fragment 0x" << std::hex << sid.code() << std::dec << " is corrupted: "
171 << ex.what() << ". Throwing hltonl::Exception::BadCTPFragment");
172 throw hltonl::Exception::BadCTPFragment(ex.what());
173 }
174 }
175
176 // Return the FullEventFragment pointer (do not transfer ownership)
177 return cache->fullEventFragment.get();
178}
179
180// =============================================================================
181// Implementation of ByteStreamInputSvc::previousEvent
182// =============================================================================
184 ATH_MSG_FATAL("The method " << __FUNCTION__ << " is not implemented for online running");
185 return nullptr;
186}
187
188// =============================================================================
189// Implementation of ByteStreamInputSvc::currentEvent
190// =============================================================================
192 ATH_MSG_FATAL("The method " << __FUNCTION__ << " is not implemented for online running");
193 return nullptr;
194}
195
196// =============================================================================
198 this->rawData.reset();
199 this->fullEventFragment.reset();
200}
#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)
Assign a CLID to EventContext.
OFFLINE_FRAGMENTS_NAMESPACE::FullEventFragment RawEvent
data type for reading raw event
Definition RawEvent.h:37
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
A monitored timer.
virtual const RawEvent * currentEvent() const override
TrigByteStreamInputSvc(const std::string &name, ISvcLocator *svcLoc)
Standard constructor.
uint16_t m_maxLB
Maximum lumi block number seen so far, used for monitoring.
virtual const RawEvent * previousEvent() override
virtual const RawEvent * nextEvent() override
SG::SlotSpecificObj< EventCache > m_eventsCache
Cache of RawEvent pointer per event slot.
virtual ~TrigByteStreamInputSvc()
Standard destructor.
virtual StatusCode finalize() override
Gaudi::Property< int > m_checkCTPFragmentModuleID
ServiceHandle< IROBDataProviderSvc > m_robDataProviderSvc
ToolHandle< GenericMonitoringTool > m_monTool
ServiceHandle< StoreGateSvc > m_evtStore
virtual StatusCode initialize() override
Thrown if the CTP ROBFragment for a new event has non-zero status word or other errors.
Thrown if event source throws an exception when new event is requested.
Thrown if the CTP ROBFragment cannot be retrieved for a new event.
Thrown if the event source cannot provide new events temporarily, e.g.
Thrown if all events are already read from the input and another one is requested.
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
setEventNumber uint32_t
std::unique_ptr< uint32_t[]> rawData
Underlying data structure.
std::unique_ptr< RawEvent > fullEventFragment
Current event fragment.