The Gaudi Framework  master (d98a2936)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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"
13 #include <GaudiKernel/DataObject.h>
14 #include <GaudiKernel/IRegistry.h>
15 #include <GaudiKernel/Incident.h>
16 #include <GaudiKernel/Memory.h>
17 #include <GaudiKernel/MsgStream.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;
45  return StatusCode::FAILURE;
46  }
47  m_evtDataSvc = serviceLocator()->service( "EventDataSvc" );
48  if ( !m_evtDataSvc ) {
49  fatal() << "Error retrieving EventDataSvc interface IDataProviderSvc." << endmsg;
50  return StatusCode::FAILURE;
51  }
52 
53  // Obtain the IProperty of the ApplicationMgr
55  if ( !m_appMgrProperty ) {
56  fatal() << "IProperty interface not found in ApplicationMgr." << endmsg;
57  return StatusCode::FAILURE;
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;
89  return StatusCode::FAILURE;
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 
96  return StatusCode::SUCCESS;
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;
342  StatusCode sc = m_evtSelector->next( *m_evtContext );
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 }
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:22
IService
Definition: IService.h:26
EventLoopMgr::m_endEventFired
bool m_endEventFired
Flag to avoid to fire the EnvEvent incident twice in a row (and also not before the first event)
Definition: EventLoopMgr.h:67
MinimalEventLoopMgr::createEventContext
EventContext createEventContext() override
implementation of IEventProcessor::createEventContext()
Definition: MinimalEventLoopMgr.cpp:292
EventLoopMgr::m_histoDataMgrSvc
SmartIF< IDataManagerSvc > m_histoDataMgrSvc
Reference to the Histogram Data Service.
Definition: EventLoopMgr.h:60
GaudiPython.Bindings.DataObject
DataObject
Definition: Bindings.py:82
EventLoopMgr::m_evtsel
Gaudi::Property< std::string > m_evtsel
Definition: EventLoopMgr.h:49
EventLoopMgr::m_evtDataSvc
SmartIF< IDataProviderSvc > m_evtDataSvc
Reference to the Event Data Service's IDataProviderSvc interface.
Definition: EventLoopMgr.h:54
AppReturnCode.h
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:314
EventLoopMgr.h
IOpaqueAddress
Definition: IOpaqueAddress.h:28
PropertyHolder< CommonMessaging< implements< IService, IProperty, IStateful > > >::setProperty
StatusCode setProperty(const Gaudi::Details::PropertyBase &p)
Set the property from a property.
Definition: IProperty.h:38
EventLoopMgr
Class definition of EventLoopMgr.
Definition: EventLoopMgr.h:43
Memory.h
IEvtSelector
Definition: IEvtSelector.h:26
EventLoopMgr::m_evtSelector
SmartIF< IEvtSelector > m_evtSelector
Reference to the Event Selector.
Definition: EventLoopMgr.h:56
EventLoopMgr::m_appMgrProperty
SmartIF< IProperty > m_appMgrProperty
Property interface of ApplicationMgr.
Definition: EventLoopMgr.h:64
IRegistry
Definition: IRegistry.h:29
EventLoopMgr::~EventLoopMgr
~EventLoopMgr() override
Standard Destructor.
Definition: EventLoopMgr.cpp:31
MinimalEventLoopMgr::finalize
StatusCode finalize() override
implementation of IService::finalize
Definition: MinimalEventLoopMgr.cpp:246
EventLoopMgr::m_evtDataMgrSvc
SmartIF< IDataManagerSvc > m_evtDataMgrSvc
Reference to the Event Data Service's IDataManagerSvc interface.
Definition: EventLoopMgr.h:52
Gaudi::Utils::begin
AttribStringParser::Iterator begin(const AttribStringParser &parser)
Definition: AttribStringParser.h:135
GaudiPython.Pythonizations.ctx
ctx
Definition: Pythonizations.py:578
Service::name
const std::string & name() const override
Retrieve name of the service
Definition: Service.cpp:333
StatusCode
Definition: StatusCode.h:64
Gaudi::setAppReturnCode
StatusCode setAppReturnCode(SmartIF< IProperty > &appmgr, int value, bool force=false)
Set the application return code.
Definition: AppReturnCode.h:58
MinimalEventLoopMgr::reinitialize
StatusCode reinitialize() override
implementation of IService::reinitialize
Definition: MinimalEventLoopMgr.cpp:195
MinimalEventLoopMgr::stop
StatusCode stop() override
implementation of IService::stop
Definition: MinimalEventLoopMgr.cpp:168
EventLoopMgr::nextEvent
StatusCode nextEvent(int maxevt) override
implementation of IEventProcessor::nextEvent
Definition: EventLoopMgr.cpp:251
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:198
Gaudi::ReturnCode::AlgorithmFailure
constexpr int AlgorithmFailure
Definition: AppReturnCode.h:33
IRegistry.h
EventLoopMgr::m_histoPersSvc
SmartIF< IConversionSvc > m_histoPersSvc
Reference to the Histogram Persistency Service.
Definition: EventLoopMgr.h:62
EventLoopMgr::m_evtContext
IEvtSelector::Context * m_evtContext
Event Iterator.
Definition: EventLoopMgr.h:58
StatusCode::ignore
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition: StatusCode.h:139
EventLoopMgr::stop
StatusCode stop() override
implementation of IService::stop
Definition: EventLoopMgr.cpp:159
IRegistry::address
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
StatusCode::isFailure
bool isFailure() const
Definition: StatusCode.h:129
EventLoopMgr::executeEvent
StatusCode executeEvent(EventContext &&ctx) override
implementation of IEventProcessor::executeEvent(EventContext&&)
Definition: EventLoopMgr.cpp:229
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:99
DataObject.h
SmartIF::get
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:82
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:45
EventLoopMgr::m_histPersName
Gaudi::Property< std::string > m_histPersName
Definition: EventLoopMgr.h:48
MinimalEventLoopMgr::m_incidentSvc
SmartIF< IIncidentSvc > m_incidentSvc
Reference to the incident service.
Definition: MinimalEventLoopMgr.h:70
Gaudi::StateMachine::INITIALIZED
@ INITIALIZED
Definition: StateMachine.h:24
EventLoopMgr::reinitialize
StatusCode reinitialize() override
implementation of IService::reinitialize
Definition: EventLoopMgr.cpp:99
System::kByte
@ kByte
Definition: Memory.h:50
EventContext
Definition: EventContext.h:34
IRegistry::object
virtual DataObject * object() const =0
Retrieve object behind the link.
Service::outputLevel
int outputLevel() const
get the Service's output level
Definition: Service.h:160
EventLoopMgr::finalize
StatusCode finalize() override
implementation of IService::finalize
Definition: EventLoopMgr.cpp:171
DataObject
Definition: DataObject.h:37
DEBMSG
#define DEBMSG
Definition: EventLoopMgr.cpp:28
MinimalEventLoopMgr::executeEvent
StatusCode executeEvent(EventContext &&ctx) override
implementation of IEventProcessor::executeEvent(EventContext&&)
Definition: MinimalEventLoopMgr.cpp:329
System::mappedMemory
GAUDI_API long mappedMemory(MemoryUnit unit=kByte, InfoType fetch=Memory, long pid=-1)
Basic Process Information: priority boost.
Definition: Memory.cpp:172
EventLoopMgr::getEventRoot
StatusCode getEventRoot(IOpaqueAddress *&refpAddr)
Create event address using event selector.
Definition: EventLoopMgr.cpp:340
IOTest.end
end
Definition: IOTest.py:125
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:100
Incident.h
Incident
Definition: Incident.h:24
DataObject::clID
virtual const CLID & clID() const
Retrieve reference to class definition structure.
Definition: DataObject.cpp:66
Gaudi::Accumulators::accumulate
void accumulate(Counter &counter, const Container &container, Fun f=Identity{})
A helper function for accumulating data from a container into a counter This is internally using buff...
Definition: Accumulators.h:1227
MinimalEventLoopMgr::initialize
StatusCode initialize() override
implementation of IService::initialize
Definition: MinimalEventLoopMgr.cpp:44
EventLoopMgr::initialize
StatusCode initialize() override
implementation of IService::initialize
Definition: EventLoopMgr.cpp:33
MinimalEventLoopMgr::m_scheduledStop
bool m_scheduledStop
Scheduled stop of event processing.
Definition: MinimalEventLoopMgr.h:79
MsgStream.h
Service::serviceLocator
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator
Definition: Service.cpp:336