The Gaudi Framework  master (37c0b60a)
EventLoopMgr.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2024 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/MsgStream.h>
17 #include <chrono>
18 
19 // Instantiation of a static factory class used by clients to create instances of this service
21 
22 #define ON_DEBUG if ( outputLevel() <= MSG::DEBUG )
23 #define ON_VERBOSE if ( outputLevel() <= MSG::VERBOSE )
24 
25 #define DEBMSG ON_DEBUG debug()
26 #define VERMSG ON_VERBOSE verbose()
27 
28 //--------------------------------------------------------------------------------------------
29 // Standard Destructor
30 //--------------------------------------------------------------------------------------------
32 
33 //--------------------------------------------------------------------------------------------
34 // implementation of IAppMgrUI::initialize
35 //--------------------------------------------------------------------------------------------
37  // Initialize the base class
39  if ( !sc.isSuccess() ) {
40  DEBMSG << "Error Initializing base class MinimalEventLoopMgr." << endmsg;
41  return sc;
42  }
43 
44  // Setup access to event data services
45  m_evtDataMgrSvc = serviceLocator()->service( "EventDataSvc" );
46  if ( !m_evtDataMgrSvc ) {
47  fatal() << "Error retrieving EventDataSvc interface IDataManagerSvc." << endmsg;
48  return StatusCode::FAILURE;
49  }
50  m_evtDataSvc = serviceLocator()->service( "EventDataSvc" );
51  if ( !m_evtDataSvc ) {
52  fatal() << "Error retrieving EventDataSvc interface IDataProviderSvc." << endmsg;
53  return StatusCode::FAILURE;
54  }
55 
56  // Obtain the IProperty of the ApplicationMgr
58  if ( !m_appMgrProperty ) {
59  fatal() << "IProperty interface not found in ApplicationMgr." << endmsg;
60  return StatusCode::FAILURE;
61  }
62 
63  // We do not expect a Event Selector necessarily being declared
64  setProperty( m_appMgrProperty->getProperty( "EvtSel" ) ).ignore();
65 
66  if ( m_evtsel != "NONE" || m_evtsel.empty() ) {
67  m_evtSelector = serviceLocator()->service( "EventSelector" );
68  if ( m_evtSelector ) {
69  // Setup Event Selector
70  sc = m_evtSelector->createContext( m_evtContext );
71  if ( !sc.isSuccess() ) {
72  fatal() << "Can not create the event selector Context." << endmsg;
73  return sc;
74  }
75  } else {
76  fatal() << "EventSelector not found." << endmsg;
77  return sc;
78  }
79  } else {
80  m_evtSelector = nullptr;
81  m_evtContext = nullptr;
82  if ( m_warnings ) {
83  warning() << "Unable to locate service \"EventSelector\" " << endmsg;
84  warning() << "No events will be processed from external input." << endmsg;
85  }
86  }
87 
88  // Setup access to histogramming services
89  m_histoDataMgrSvc = serviceLocator()->service( "HistogramDataSvc" );
90  if ( !m_histoDataMgrSvc ) {
91  fatal() << "Error retrieving HistogramDataSvc." << endmsg;
92  return sc;
93  }
94  // Setup histogram persistency
95  m_histoPersSvc = serviceLocator()->service( "HistogramPersistencySvc" );
96  if ( !m_histoPersSvc ) {
97  warning() << "Histograms cannot not be saved - though required." << endmsg;
98  return sc;
99  }
100 
101  return StatusCode::SUCCESS;
102 }
103 //--------------------------------------------------------------------------------------------
104 // implementation of IService::reinitialize
105 //--------------------------------------------------------------------------------------------
107 
108  // Initialize the base class
110  if ( !sc.isSuccess() ) {
111  DEBMSG << "Error Initializing base class MinimalEventLoopMgr." << endmsg;
112  return sc;
113  }
114 
115  // Check to see whether a new Event Selector has been specified
116  if ( sc = setProperty( m_appMgrProperty->getProperty( "EvtSel" ) ); !sc ) return sc;
117  if ( m_evtsel != "NONE" || m_evtsel.length() == 0 ) {
118  auto theSvc = serviceLocator()->service<IService>( "EventSelector" );
119  auto theEvtSel = theSvc.as<IEvtSelector>();
120  if ( theEvtSel && ( theEvtSel.get() != m_evtSelector.get() ) ) {
121  // Setup Event Selector
122  if ( m_evtSelector.get() && m_evtContext ) {
123  // Need to release context before switching to new event selector
124  if ( sc = m_evtSelector->releaseContext( m_evtContext ); !sc ) return sc;
125  m_evtContext = nullptr;
126  }
127  m_evtSelector = theEvtSel;
128  if ( theSvc->FSMState() == Gaudi::StateMachine::INITIALIZED ) {
129  sc = theSvc->reinitialize();
130  if ( !sc.isSuccess() ) {
131  error() << "Failure Reinitializing EventSelector " << theSvc->name() << endmsg;
132  return sc;
133  }
134  } else {
135  sc = theSvc->sysInitialize();
136  if ( !sc.isSuccess() ) {
137  error() << "Failure Initializing EventSelector " << theSvc->name() << endmsg;
138  return sc;
139  }
140  }
141  sc = m_evtSelector->createContext( m_evtContext );
142  if ( !sc.isSuccess() ) {
143  error() << "Can not create Context " << theSvc->name() << endmsg;
144  return sc;
145  }
146  info() << "EventSelector service changed to " << theSvc->name() << endmsg;
147  } else if ( m_evtSelector ) {
148  if ( m_evtContext ) {
149  if ( sc = m_evtSelector->releaseContext( m_evtContext ); !sc ) return sc;
150  m_evtContext = nullptr;
151  }
152  sc = m_evtSelector->createContext( m_evtContext );
153  if ( !sc.isSuccess() ) {
154  error() << "Can not create Context " << theSvc->name() << endmsg;
155  return sc;
156  }
157  }
158  } else if ( m_evtSelector && m_evtContext ) {
159  sc = m_evtSelector->releaseContext( m_evtContext );
160  m_evtSelector = nullptr;
161  m_evtContext = nullptr;
162  }
163  return sc;
164 }
165 
166 //--------------------------------------------------------------------------------------------
167 // implementation of IService::stop
168 //--------------------------------------------------------------------------------------------
170  if ( !m_endEventFired ) {
171  // Fire pending EndEvent incident
172  m_incidentSvc->fireIncident( Incident( name(), IncidentType::EndEvent ) );
173  m_endEventFired = true;
174  }
175  return m_evtDataMgrSvc
176  ->clearStore() //
177  .andThen( [this]() { return MinimalEventLoopMgr::stop(); } ) //
178  .orElse( [this]() { DEBMSG << "Clear of Event data store failed" << endmsg; } );
179 }
180 
181 //--------------------------------------------------------------------------------------------
182 // implementation of IAppMgrUI::finalize
183 //--------------------------------------------------------------------------------------------
185  // Finalize base class
187  if ( !sc.isSuccess() ) {
188  error() << "Error finalizing base class" << endmsg;
189  return sc;
190  }
191 
192  // Save Histograms Now
193  if ( m_histoPersSvc ) {
194  std::vector<DataObject*> objects;
195  sc = m_histoDataMgrSvc->traverseTree( [&objects]( IRegistry* reg, int ) {
196  DataObject* obj = reg->object();
197  if ( !obj || obj->clID() == CLID_StatisticsFile ) return false;
198  objects.push_back( obj );
199  return true;
200  } );
201  if ( sc.isSuccess() ) {
202  // skip /stat entry!
203  sc = std::accumulate( begin( objects ), end( objects ), sc, [&]( StatusCode isc, auto& i ) {
204  IOpaqueAddress* pAddr = nullptr;
205  StatusCode iret = m_histoPersSvc->createRep( i, pAddr );
206  if ( iret.isFailure() ) return iret;
207  i->registry()->setAddress( pAddr );
208  return isc;
209  } );
210  sc = std::accumulate( begin( objects ), end( objects ), sc, [&]( StatusCode isc, auto& i ) {
211  IRegistry* reg = i->registry();
212  StatusCode iret = m_histoPersSvc->fillRepRefs( reg->address(), i );
213  return iret.isFailure() ? iret : isc;
214  } );
215  if ( sc.isSuccess() ) {
216  info() << "Histograms converted successfully according to request." << endmsg;
217  } else {
218  error() << "Error while saving Histograms." << endmsg;
219  }
220  } else {
221  error() << "Error while traversing Histogram data store" << endmsg;
222  }
223  }
224 
225  // Release event selector context
226  if ( m_evtSelector && m_evtContext ) {
227  m_evtSelector->releaseContext( m_evtContext ).ignore();
228  m_evtContext = nullptr;
229  }
230 
231  // Release all interfaces...
232  m_histoDataMgrSvc = nullptr;
233  m_histoPersSvc = nullptr;
234 
235  m_evtSelector = nullptr;
236  m_evtDataSvc = nullptr;
237  m_evtDataMgrSvc = nullptr;
238 
239  return StatusCode::SUCCESS;
240 }
241 
242 //--------------------------------------------------------------------------------------------
243 // executeEvent(void* par)
244 //--------------------------------------------------------------------------------------------
246 
247  // DP Monitoring
248 
249  // Fire BeginEvent "Incident"
250  m_incidentSvc->fireIncident( Incident( name(), IncidentType::BeginEvent ) );
251  // An incident may schedule a stop, in which case is better to exit before the actual execution.
252  if ( m_scheduledStop ) {
253  always() << "Terminating event processing loop due to a stop scheduled by an incident listener" << endmsg;
254  return StatusCode::SUCCESS;
255  }
256 
257  // Execute Algorithms
258  m_incidentSvc->fireIncident( Incident( name(), IncidentType::BeginProcessing ) );
260  m_incidentSvc->fireIncident( Incident( name(), IncidentType::EndProcessing ) );
261 
262  // Check if there was an error processing current event
263  if ( !sc.isSuccess() ) { error() << "Terminating event processing loop due to errors" << endmsg; }
264  return sc;
265 }
266 
267 //--------------------------------------------------------------------------------------------
268 // implementation of IAppMgrUI::nextEvent
269 //--------------------------------------------------------------------------------------------
270 // External libraries
271 #include <GaudiKernel/Memory.h>
273 
274  // DP Monitoring
275  // Calculate runtime
277  typedef Clock::time_point time_point;
278 
279  const float oneOver1024 = 1.f / 1024.f;
280 
281  DataObject* pObject = nullptr;
283 
284  // loop over events if the maxevt (received as input) if different from -1.
285  // if evtmax is -1 it means infinite loop
286  time_point start_time = Clock::now();
287  for ( int nevt = 0; maxevt == -1 || nevt < maxevt; ++nevt ) {
288 
289  if ( 1 == nevt ) // reset after first evt
290  start_time = Clock::now();
291 
292  auto ctx = createEventContext();
293 
294  // always() << "Event Number = " << total_nevt
295  // << " WSS (MB) = " << System::mappedMemory(System::MemoryUnit::kByte)*oneOver1024
296  // << " Time (s) = " << secsFromStart(start_time) << endmsg;
297 
298  // Check if there is a scheduled stop issued by some algorithm/service
299  if ( m_scheduledStop ) {
300  m_scheduledStop = false;
301  always() << "Terminating event processing loop due to scheduled stop" << endmsg;
302  break;
303  }
304  // Clear the event store, if used in the event loop
305  if ( 0 != ctx.evt() ) {
306 
307  if ( !m_endEventFired ) {
308  // Fire EndEvent "Incident" (it is considered part of the clearing of the TS)
309  m_incidentSvc->fireIncident( Incident( name(), IncidentType::EndEvent ) );
310  m_endEventFired = true;
311  }
312  sc = m_evtDataMgrSvc->clearStore();
313  if ( !sc.isSuccess() ) { DEBMSG << "Clear of Event data store failed" << endmsg; }
314  }
315 
316  // Setup event in the event store
317  if ( m_evtContext ) {
318  IOpaqueAddress* addr = nullptr;
319  // Only if there is a EventSelector
320  sc = getEventRoot( addr );
321  if ( !sc.isSuccess() ) {
322  info() << "No more events in event selection " << endmsg;
323  break;
324  }
325  // Set root clears the event data store first
326  sc = m_evtDataMgrSvc->setRoot( "/Event", addr );
327  if ( !sc.isSuccess() ) {
328  warning() << "Error declaring event root address." << endmsg;
329  continue;
330  }
331  sc = m_evtDataSvc->retrieveObject( "/Event", pObject );
332  if ( !sc.isSuccess() ) {
333  warning() << "Unable to retrieve Event root object" << endmsg;
334  break;
335  }
336  } else {
337  sc = m_evtDataMgrSvc->setRoot( "/Event", new DataObject() );
338  if ( !sc.isSuccess() ) { warning() << "Error declaring event root DataObject" << endmsg; }
339  }
340  // Execute event for all required algorithms
341  sc = executeEvent( std::move( ctx ) );
342  m_endEventFired = false;
343  if ( !sc.isSuccess() ) {
344  error() << "Terminating event processing loop due to errors" << endmsg;
346  return sc;
347  }
348  }
349 
350  if ( outputLevel() <= MSG::DEBUG )
351  debug() << "---> Loop Finished - "
352  << " WSS " << System::mappedMemory( System::MemoryUnit::kByte ) * oneOver1024
353  << " | total time (skipping 1st evt) "
354  << std::chrono::duration_cast<std::chrono::nanoseconds>( Clock::now() - start_time ).count() << " ns"
355  << endmsg;
356 
357  return StatusCode::SUCCESS;
358 }
359 
362  refpAddr = nullptr;
363  StatusCode sc = m_evtSelector->next( *m_evtContext );
364  if ( !sc.isSuccess() ) return sc;
365  // Create root address and assign address to data service
366  sc = m_evtSelector->createAddress( *m_evtContext, refpAddr );
367  if ( !sc.isSuccess() ) {
368  sc = m_evtSelector->next( *m_evtContext );
369  if ( sc.isSuccess() ) {
370  sc = m_evtSelector->createAddress( *m_evtContext, refpAddr );
371  if ( !sc.isSuccess() ) warning() << "Error creating IOpaqueAddress." << endmsg;
372  }
373  }
374  return sc;
375 }
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:25
IService
Definition: IService.h:28
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:69
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:62
GaudiPython.Bindings.DataObject
DataObject
Definition: Bindings.py:82
EventLoopMgr::m_evtsel
Gaudi::Property< std::string > m_evtsel
Definition: EventLoopMgr.h:50
EventLoopMgr::m_evtDataSvc
SmartIF< IDataProviderSvc > m_evtDataSvc
Reference to the Event Data Service's IDataProviderSvc interface.
Definition: EventLoopMgr.h:56
AppReturnCode.h
std::move
T move(T... args)
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:314
EventLoopMgr.h
IOpaqueAddress
Definition: IOpaqueAddress.h:33
std::vector< DataObject * >
PropertyHolder< CommonMessaging< implements< IService, IProperty, IStateful > > >::setProperty
StatusCode setProperty(const Gaudi::Details::PropertyBase &p)
Set the property from a property.
Definition: IProperty.h:39
EventLoopMgr
Class definition of EventLoopMgr.
Definition: EventLoopMgr.h:44
Memory.h
IEvtSelector
Definition: IEvtSelector.h:28
EventLoopMgr::m_warnings
Gaudi::Property< bool > m_warnings
Definition: EventLoopMgr.h:51
EventLoopMgr::m_evtSelector
SmartIF< IEvtSelector > m_evtSelector
Reference to the Event Selector.
Definition: EventLoopMgr.h:58
EventLoopMgr::m_appMgrProperty
SmartIF< IProperty > m_appMgrProperty
Property interface of ApplicationMgr.
Definition: EventLoopMgr.h:66
IRegistry
Definition: IRegistry.h:32
EventLoopMgr::~EventLoopMgr
~EventLoopMgr() override
Standard Destructor.
Definition: EventLoopMgr.cpp:31
MinimalEventLoopMgr::finalize
StatusCode finalize() override
implementation of IService::finalize
Definition: MinimalEventLoopMgr.cpp:246
std::chrono::high_resolution_clock
std::vector::push_back
T push_back(T... args)
EventLoopMgr::m_evtDataMgrSvc
SmartIF< IDataManagerSvc > m_evtDataMgrSvc
Reference to the Event Data Service's IDataManagerSvc interface.
Definition: EventLoopMgr.h:54
Gaudi::Utils::begin
AttribStringParser::Iterator begin(const AttribStringParser &parser)
Definition: AttribStringParser.h:136
GaudiPython.Pythonizations.ctx
ctx
Definition: Pythonizations.py:578
Service::name
const std::string & name() const override
Retrieve name of the service
Definition: Service.cpp:332
StatusCode
Definition: StatusCode.h:65
Gaudi::setAppReturnCode
StatusCode setAppReturnCode(SmartIF< IProperty > &appmgr, int value, bool force=false)
Set the application return code.
Definition: AppReturnCode.h:59
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:272
std::accumulate
T accumulate(T... args)
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
Gaudi::ReturnCode::AlgorithmFailure
constexpr int AlgorithmFailure
Definition: AppReturnCode.h:34
IRegistry.h
EventLoopMgr::m_histoPersSvc
SmartIF< IConversionSvc > m_histoPersSvc
Reference to the Histogram Persistency Service.
Definition: EventLoopMgr.h:64
EventLoopMgr::m_evtContext
IEvtSelector::Context * m_evtContext
Event Iterator.
Definition: EventLoopMgr.h:60
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:169
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:245
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
DataObject.h
SmartIF::get
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:86
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
MinimalEventLoopMgr::m_incidentSvc
SmartIF< IIncidentSvc > m_incidentSvc
Reference to the incident service.
Definition: MinimalEventLoopMgr.h:71
Gaudi::StateMachine::INITIALIZED
@ INITIALIZED
Definition: StateMachine.h:25
EventLoopMgr::reinitialize
StatusCode reinitialize() override
implementation of IService::reinitialize
Definition: EventLoopMgr.cpp:106
System::kByte
@ kByte
Definition: Memory.h:65
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:208
EventLoopMgr::finalize
StatusCode finalize() override
implementation of IService::finalize
Definition: EventLoopMgr.cpp:184
DataObject
Definition: DataObject.h:36
DEBMSG
#define DEBMSG
Definition: EventLoopMgr.cpp:25
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:197
EventLoopMgr::getEventRoot
StatusCode getEventRoot(IOpaqueAddress *&refpAddr)
Create event address using event selector.
Definition: EventLoopMgr.cpp:361
IOTest.end
end
Definition: IOTest.py:125
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
Incident.h
Incident
Definition: Incident.h:27
DataObject::clID
virtual const CLID & clID() const
Retrieve reference to class definition structure.
Definition: DataObject.cpp:66
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:36
MinimalEventLoopMgr::m_scheduledStop
bool m_scheduledStop
Scheduled stop of event processing.
Definition: MinimalEventLoopMgr.h:80
MsgStream.h
Service::serviceLocator
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator
Definition: Service.cpp:335