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