The Gaudi Framework  master (82fdf313)
Loading...
Searching...
No Matches
EventLoopMgr.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11#include "EventLoopMgr.h"
16#include <GaudiKernel/Memory.h>
18#include <chrono>
19#include <numeric>
20#include <utility>
21#include <vector>
22
24
25#define ON_DEBUG if ( outputLevel() <= MSG::DEBUG )
26#define ON_VERBOSE if ( outputLevel() <= MSG::VERBOSE )
27
28#define DEBMSG ON_DEBUG debug()
29#define VERMSG ON_VERBOSE verbose()
30
32
34 // Initialize the base class
36 if ( !sc.isSuccess() ) {
37 DEBMSG << "Error Initializing base class MinimalEventLoopMgr." << endmsg;
38 return sc;
39 }
40
41 // Setup access to event data services
42 m_evtDataMgrSvc = serviceLocator()->service( "EventDataSvc" );
43 if ( !m_evtDataMgrSvc ) {
44 fatal() << "Error retrieving EventDataSvc interface IDataManagerSvc." << endmsg;
46 }
47 m_evtDataSvc = serviceLocator()->service( "EventDataSvc" );
48 if ( !m_evtDataSvc ) {
49 fatal() << "Error retrieving EventDataSvc interface IDataProviderSvc." << endmsg;
51 }
52
53 // Obtain the IProperty of the ApplicationMgr
55 if ( !m_appMgrProperty ) {
56 fatal() << "IProperty interface not found in ApplicationMgr." << endmsg;
58 }
59
60 // We do not expect a Event Selector necessarily being declared
61 setProperty( m_appMgrProperty->getProperty( "EvtSel" ) ).ignore();
62
63 if ( m_evtsel != "NONE" || m_evtsel.empty() ) {
64 m_evtSelector = serviceLocator()->service( "EventSelector" );
65 if ( m_evtSelector ) {
66 // Setup Event Selector
67 sc = m_evtSelector->createContext( m_evtContext );
68 if ( !sc.isSuccess() ) {
69 fatal() << "Can not create the event selector Context." << endmsg;
70 return sc;
71 }
72 } else {
73 fatal() << "EventSelector not found." << endmsg;
74 return sc;
75 }
76 } else {
77 m_evtSelector = nullptr;
78 m_evtContext = nullptr;
79 info() << "Unable to locate service \"EventSelector\": "
80 << "No events will be processed from external input." << endmsg;
81 }
82
83 setProperty( m_appMgrProperty->getProperty( "HistogramPersistency" ) ).ignore();
84 if ( m_histPersName != "NONE" && !m_histPersName.empty() ) {
85 // Setup access to histogramming services
86 m_histoDataMgrSvc = serviceLocator()->service( "HistogramDataSvc" );
87 if ( !m_histoDataMgrSvc ) {
88 fatal() << "Error retrieving HistogramDataSvc." << endmsg;
90 }
91 // Setup histogram persistency
92 m_histoPersSvc = serviceLocator()->service( "HistogramPersistencySvc" );
93 if ( !m_histoPersSvc ) { warning() << "Histograms cannot not be saved - though required." << endmsg; }
94 }
95
97}
98
100
101 // Initialize the base class
103 if ( !sc.isSuccess() ) {
104 DEBMSG << "Error Initializing base class MinimalEventLoopMgr." << endmsg;
105 return sc;
106 }
107
108 // Check to see whether a new Event Selector has been specified
109 if ( sc = setProperty( m_appMgrProperty->getProperty( "EvtSel" ) ); !sc ) return sc;
110 if ( m_evtsel != "NONE" || m_evtsel.length() == 0 ) {
111 auto theSvc = serviceLocator()->service<IService>( "EventSelector" );
112 auto theEvtSel = theSvc.as<IEvtSelector>();
113 if ( theEvtSel && ( theEvtSel.get() != m_evtSelector.get() ) ) {
114 // Setup Event Selector
115 if ( m_evtSelector.get() && m_evtContext ) {
116 // Need to release context before switching to new event selector
117 if ( sc = m_evtSelector->releaseContext( m_evtContext ); !sc ) return sc;
118 m_evtContext = nullptr;
119 }
120 m_evtSelector = theEvtSel;
121 if ( theSvc->FSMState() == Gaudi::StateMachine::INITIALIZED ) {
122 sc = theSvc->reinitialize();
123 if ( !sc.isSuccess() ) {
124 error() << "Failure Reinitializing EventSelector " << theSvc->name() << endmsg;
125 return sc;
126 }
127 } else {
128 sc = theSvc->sysInitialize();
129 if ( !sc.isSuccess() ) {
130 error() << "Failure Initializing EventSelector " << theSvc->name() << endmsg;
131 return sc;
132 }
133 }
134 sc = m_evtSelector->createContext( m_evtContext );
135 if ( !sc.isSuccess() ) {
136 error() << "Can not create Context " << theSvc->name() << endmsg;
137 return sc;
138 }
139 info() << "EventSelector service changed to " << theSvc->name() << endmsg;
140 } else if ( m_evtSelector ) {
141 if ( m_evtContext ) {
142 if ( sc = m_evtSelector->releaseContext( m_evtContext ); !sc ) return sc;
143 m_evtContext = nullptr;
144 }
145 sc = m_evtSelector->createContext( m_evtContext );
146 if ( !sc.isSuccess() ) {
147 error() << "Can not create Context " << theSvc->name() << endmsg;
148 return sc;
149 }
150 }
151 } else if ( m_evtSelector && m_evtContext ) {
152 sc = m_evtSelector->releaseContext( m_evtContext );
153 m_evtSelector = nullptr;
154 m_evtContext = nullptr;
155 }
156 return sc;
157}
158
160 if ( !m_endEventFired ) {
161 // Fire pending EndEvent incident
162 m_incidentSvc->fireIncident( Incident( name(), IncidentType::EndEvent ) );
163 m_endEventFired = true;
164 }
165 return m_evtDataMgrSvc
166 ->clearStore() //
167 .andThen( [this]() { return MinimalEventLoopMgr::stop(); } ) //
168 .orElse( [this]() { DEBMSG << "Clear of Event data store failed" << endmsg; } );
169}
170
172 // Finalize base class
174 if ( !sc.isSuccess() ) {
175 error() << "Error finalizing base class" << endmsg;
176 return sc;
177 }
178
179 // Save Histograms Now
180 if ( m_histoPersSvc ) {
181 std::vector<DataObject*> objects;
182 sc = m_histoDataMgrSvc->traverseTree( [&objects]( IRegistry* reg, int ) {
183 DataObject* obj = reg->object();
184 if ( !obj || obj->clID() == CLID_StatisticsFile ) return false;
185 objects.push_back( obj );
186 return true;
187 } );
188 if ( sc.isSuccess() ) {
189 // skip /stat entry!
190 sc = std::accumulate( begin( objects ), end( objects ), sc, [&]( StatusCode isc, auto& i ) {
191 IOpaqueAddress* pAddr = nullptr;
192 StatusCode iret = m_histoPersSvc->createRep( i, pAddr );
193 if ( iret.isFailure() ) return iret;
194 i->registry()->setAddress( pAddr );
195 return isc;
196 } );
197 sc = std::accumulate( begin( objects ), end( objects ), sc, [&]( StatusCode isc, auto& i ) {
198 IRegistry* reg = i->registry();
199 StatusCode iret = m_histoPersSvc->fillRepRefs( reg->address(), i );
200 return iret.isFailure() ? iret : isc;
201 } );
202 if ( sc.isSuccess() ) {
203 info() << "Histograms converted successfully according to request." << endmsg;
204 } else {
205 error() << "Error while saving Histograms." << endmsg;
206 }
207 } else {
208 error() << "Error while traversing Histogram data store" << endmsg;
209 }
210 }
211
212 // Release event selector context
213 if ( m_evtSelector && m_evtContext ) {
214 m_evtSelector->releaseContext( m_evtContext ).ignore();
215 m_evtContext = nullptr;
216 }
217
218 // Release all interfaces...
219 m_histoDataMgrSvc = nullptr;
220 m_histoPersSvc = nullptr;
221
222 m_evtSelector = nullptr;
223 m_evtDataSvc = nullptr;
224 m_evtDataMgrSvc = nullptr;
225
226 return StatusCode::SUCCESS;
227}
228
230
231 // DP Monitoring
232
233 // Fire BeginEvent "Incident"
234 m_incidentSvc->fireIncident( Incident( name(), IncidentType::BeginEvent ) );
235 // An incident may schedule a stop, in which case is better to exit before the actual execution.
236 if ( m_scheduledStop ) {
237 always() << "Terminating event processing loop due to a stop scheduled by an incident listener" << endmsg;
238 return StatusCode::SUCCESS;
239 }
240
241 // Execute Algorithms
242 m_incidentSvc->fireIncident( Incident( name(), IncidentType::BeginProcessing ) );
243 StatusCode sc = MinimalEventLoopMgr::executeEvent( std::move( ctx ) );
244 m_incidentSvc->fireIncident( Incident( name(), IncidentType::EndProcessing ) );
245
246 // Check if there was an error processing current event
247 if ( !sc.isSuccess() ) { error() << "Terminating event processing loop due to errors" << endmsg; }
248 return sc;
249}
250
252
253 // DP Monitoring
254 // Calculate runtime
255 typedef std::chrono::high_resolution_clock Clock;
256 typedef Clock::time_point time_point;
257
258 const float oneOver1024 = 1.f / 1024.f;
259
260 DataObject* pObject = nullptr;
262
263 // loop over events if the maxevt (received as input) if different from -1.
264 // if evtmax is -1 it means infinite loop
265 time_point start_time = Clock::now();
266 for ( int nevt = 0; maxevt == -1 || nevt < maxevt; ++nevt ) {
267
268 if ( 1 == nevt ) // reset after first evt
269 start_time = Clock::now();
270
271 auto ctx = createEventContext();
272
273 // always() << "Event Number = " << total_nevt
274 // << " WSS (MB) = " << System::mappedMemory(System::MemoryUnit::kByte)*oneOver1024
275 // << " Time (s) = " << secsFromStart(start_time) << endmsg;
276
277 // Check if there is a scheduled stop issued by some algorithm/service
278 if ( m_scheduledStop ) {
279 m_scheduledStop = false;
280 always() << "Terminating event processing loop due to scheduled stop" << endmsg;
281 break;
282 }
283 // Clear the event store, if used in the event loop
284 if ( 0 != ctx.evt() ) {
285
286 if ( !m_endEventFired ) {
287 // Fire EndEvent "Incident" (it is considered part of the clearing of the TS)
288 m_incidentSvc->fireIncident( Incident( name(), IncidentType::EndEvent ) );
289 m_endEventFired = true;
290 }
291 sc = m_evtDataMgrSvc->clearStore();
292 if ( !sc.isSuccess() ) { DEBMSG << "Clear of Event data store failed" << endmsg; }
293 }
294
295 // Setup event in the event store
296 if ( m_evtContext ) {
297 IOpaqueAddress* addr = nullptr;
298 // Only if there is a EventSelector
299 sc = getEventRoot( addr );
300 if ( !sc.isSuccess() ) {
301 info() << "No more events in event selection " << endmsg;
302 break;
303 }
304 // Set root clears the event data store first
305 sc = m_evtDataMgrSvc->setRoot( "/Event", addr );
306 if ( !sc.isSuccess() ) {
307 warning() << "Error declaring event root address." << endmsg;
308 continue;
309 }
310 sc = m_evtDataSvc->retrieveObject( "/Event", pObject );
311 if ( !sc.isSuccess() ) {
312 warning() << "Unable to retrieve Event root object" << endmsg;
313 break;
314 }
315 } else {
316 sc = m_evtDataMgrSvc->setRoot( "/Event", new DataObject() );
317 if ( !sc.isSuccess() ) { warning() << "Error declaring event root DataObject" << endmsg; }
318 }
319 // Execute event for all required algorithms
320 sc = executeEvent( std::move( ctx ) );
321 m_endEventFired = false;
322 if ( !sc.isSuccess() ) {
323 error() << "Terminating event processing loop due to errors" << endmsg;
325 return sc;
326 }
327 }
328
329 if ( outputLevel() <= MSG::DEBUG )
330 debug() << "---> Loop Finished - "
331 << " WSS " << System::mappedMemory( System::MemoryUnit::kByte ) * oneOver1024
332 << " | total time (skipping 1st evt) "
333 << std::chrono::duration_cast<std::chrono::nanoseconds>( Clock::now() - start_time ).count() << " ns"
334 << endmsg;
335
336 return StatusCode::SUCCESS;
337}
338
341 refpAddr = nullptr;
343 if ( !sc.isSuccess() ) return sc;
344 // Create root address and assign address to data service
345 sc = m_evtSelector->createAddress( *m_evtContext, refpAddr );
346 if ( !sc.isSuccess() ) {
347 sc = m_evtSelector->next( *m_evtContext );
348 if ( sc.isSuccess() ) {
349 sc = m_evtSelector->createAddress( *m_evtContext, refpAddr );
350 if ( !sc.isSuccess() ) warning() << "Error creating IOpaqueAddress." << endmsg;
351 }
352 }
353 return sc;
354}
bool PyHelper setProperty(IInterface *p, char *name, char *value)
#define DEBMSG
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
#define DECLARE_COMPONENT(type)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
MsgStream & always() const
shortcut for the method msgStream(MSG::ALWAYS)
A DataObject is the base class of any identifiable object on any data store.
Definition DataObject.h:37
virtual const CLID & clID() const
Retrieve reference to class definition structure.
This class represents an entry point to all the event specific data.
Class definition of EventLoopMgr.
SmartIF< IEvtSelector > m_evtSelector
Reference to the Event Selector.
StatusCode getEventRoot(IOpaqueAddress *&refpAddr)
Create event address using event selector.
StatusCode reinitialize() override
implementation of IService::reinitialize
StatusCode stop() override
implementation of IService::stop
IEvtSelector::Context * m_evtContext
Event Iterator.
Gaudi::Property< std::string > m_histPersName
StatusCode nextEvent(int maxevt) override
implementation of IEventProcessor::nextEvent
SmartIF< IProperty > m_appMgrProperty
Property interface of ApplicationMgr.
Gaudi::Property< std::string > m_evtsel
SmartIF< IDataProviderSvc > m_evtDataSvc
Reference to the Event Data Service's IDataProviderSvc interface.
StatusCode finalize() override
implementation of IService::finalize
~EventLoopMgr() override
Standard Destructor.
StatusCode executeEvent(EventContext &&ctx) override
implementation of IEventProcessor::executeEvent(EventContext&&)
SmartIF< IDataManagerSvc > m_histoDataMgrSvc
Reference to the Histogram Data Service.
bool m_endEventFired
Flag to avoid to fire the EnvEvent incident twice in a row (and also not before the first event)
StatusCode initialize() override
implementation of IService::initialize
SmartIF< IConversionSvc > m_histoPersSvc
Reference to the Histogram Persistency Service.
SmartIF< IDataManagerSvc > m_evtDataMgrSvc
Reference to the Event Data Service's IDataManagerSvc interface.
The Event Selector Interface.
Opaque address interface definition.
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition IRegistry.h:29
virtual DataObject * object() const =0
Retrieve object behind the link.
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
General service interface definition.
Definition IService.h:26
virtual SmartIF< IService > & service(const Gaudi::Utils::TypeNameString &typeName, const bool createIf=true)=0
Returns a smart pointer to a service.
Base class for all Incidents (computing events).
Definition Incident.h:24
StatusCode stop() override
implementation of IService::stop
bool m_scheduledStop
Scheduled stop of event processing.
EventContext createEventContext() override
implementation of IEventProcessor::createEventContext()
SmartIF< IIncidentSvc > m_incidentSvc
Reference to the incident service.
StatusCode finalize() override
implementation of IService::finalize
StatusCode executeEvent(EventContext &&ctx) override
implementation of IEventProcessor::executeEvent(EventContext&&)
StatusCode initialize() override
implementation of IService::initialize
StatusCode reinitialize() override
implementation of IService::reinitialize
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator.
Definition Service.cpp:336
const std::string & name() const override
Retrieve name of the service.
Definition Service.cpp:333
int outputLevel() const
get the Service's output level
Definition Service.h:160
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isFailure() const
Definition StatusCode.h:129
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition StatusCode.h:139
bool isSuccess() const
Definition StatusCode.h:314
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
constexpr int AlgorithmFailure
StatusCode setAppReturnCode(SmartIF< IProperty > &appmgr, int value, bool force=false)
Set the application return code.
@ DEBUG
Definition IMessageSvc.h:22
GAUDI_API long mappedMemory(MemoryUnit unit=kByte, InfoType fetch=Memory, long pid=-1)
Basic Process Information: priority boost.
Definition Memory.cpp:172
@ kByte
Definition Memory.h:50