5#define GAUDISVC_EVENTLOOPMGR_CPP
25#include "GaudiKernel/IAlgManager.h"
26#include "GaudiKernel/IAlgorithm.h"
27#include "GaudiKernel/SmartIF.h"
28#include "GaudiKernel/Incident.h"
29#include "GaudiKernel/DataObject.h"
30#include "GaudiKernel/IIncidentSvc.h"
31#include "GaudiKernel/IEvtSelector.h"
32#include "GaudiKernel/IDataManagerSvc.h"
33#include "GaudiKernel/IConversionSvc.h"
34#include "GaudiKernel/GaudiException.h"
35#include "GaudiKernel/EventContext.h"
36#include "GaudiKernel/EventIDBase.h"
37#include "GaudiKernel/ThreadLocalContext.h"
38#include "GaudiKernel/AppReturnCode.h"
42#include "EventInfo/EventInfo.h"
60 : base_class(nam, svcLoc),
75 declareProperty(
"EvtStore",
m_eventStore,
"The StoreGateSvc instance to interact with for event payload" );
77 "Name of Event Selector to use. If empty string (default) "
78 "take value from ApplicationMgr");
80 "Histogram persistency technology to use: ROOT, HBOOK, NONE. "
81 "By default (empty string) get property value from "
84 "histogram write/update interval");
86 "Controls behaviour of event loop depending on return code of"
87 " Algorithms. 0: all non-SUCCESSes terminate job. "
88 "1: RECOVERABLE skips to next event, FAILURE terminates job "
89 "(DEFAULT). 2: RECOVERABLE and FAILURE skip to next events");
91 "Print event heartbeat printouts every m_eventPrintoutInterval events");
93 "heartbeat time interval is seconds rather than events"
94 "you also get a nice event rate printout then");
95 declareProperty(
"DoLiteLoop",
m_liteLoop=
false,
"Runs the bare minimum during executeEvent");
96 declareProperty(
"UseDetailChronoStat",
m_doChrono=
false);
97 declareProperty(
"ClearStorePolicy",
99 "Configure the policy wrt handling of when the "
100 "'clear-the-event-store' event shall happen: at EndEvent "
101 "(default as it is makes things easier for memory management"
102 ") or at BeginEvent (easier e.g. for interactive use)");
103 declareProperty(
"PreSelectTools",
m_tools,
"AlgTools for event pre-selection")->
106 "Require valid input attribute list to be present");
108 "In case of DoubleEventSelector use event number from secondary input");
110 "ServiceHandle for EvtIdModifierSvc");
112 "List of algorithms/sequences to execute during PreFork");
129 m_autoRetrieveTools =
false;
130 m_checkToolDeps =
false;
132 StatusCode
sc = MinimalEventLoopMgr::initialize();
133 if ( !
sc.isSuccess() )
135 ATH_MSG_ERROR (
"Failed to initialize base class MinimalEventLoopMgr" );
144 if( !
sc.isSuccess() )
146 ATH_MSG_FATAL (
"Error retrieving pointer to StoreGateSvc" );
155 if( !
sc.isSuccess() )
164 SmartIF<IProperty> prpMgr(serviceLocator());
165 if ( !prpMgr.isValid() )
167 ATH_MSG_FATAL (
"IProperty interface not found in ApplicationMgr." );
168 return StatusCode::FAILURE;
176 if( !
sc.isSuccess() )
183 if ( histPersName.length() == 0 )
188 if ( histPersName !=
"NONE" ) {
193 if( !sc.isSuccess() ) {
194 ATH_MSG_WARNING (
"Histograms cannot not be saved - though required." );
197 SmartIF<IProperty> histSvc;
198 if (histPersName ==
"ROOT") {
199 histSvc = serviceLocator()->service(
"RootHistSvc");
200 }
else if ( histPersName ==
"HBOOK" ) {
201 histSvc = serviceLocator()->service(
"HbookHistSvc");
205 ATH_MSG_ERROR (
"could not locate actual Histogram persistency service" );
207 const Gaudi::Details::PropertyBase &prop = histSvc->getProperty(
"OutputFile");
210 const StringProperty &sprop =
dynamic_cast<const StringProperty&
>( prop );
215 ATH_MSG_VERBOSE (
"could not dcast OutputFile property to a StringProperty."
216 " Need to fix Gaudi." );
218 val = prop.toString();
223 val !=
"UndefinedROOTOutputFileName" &&
224 val !=
"UndefinedHbookOutputFileName" ) {
238 ATH_MSG_DEBUG (
"EventID modifier Service not set. No run number, ... overrides will be applied." );
241 ATH_MSG_INFO (
"Could not find EventID modifier Service. No run number, ... overrides will be applied." );
247 const std::string& selName(
m_evtsel.value());
254 if( !selName.empty() && selName !=
"NONE") {
255 SmartIF<IEvtSelector> theEvtSel{serviceLocator()->service( selName )};
264 return StatusCode::FAILURE;
266 if (msgLevel(MSG::INFO)) {
267 SmartIF<INamedInterface> named(theEvtSel);
269 ATH_MSG_INFO (
"Setup EventSelector service {}", named->name( )
273 }
else if (
sc.isFailure()) {
276 return StatusCode::FAILURE;
286 return StatusCode::FAILURE;
290 m_aess = serviceLocator()->service(
"AlgExecStateSvc");
293 return StatusCode::FAILURE;
317 if ( policyName !=
"BeginEvent" &&
318 policyName !=
"EndEvent" ) {
320 ATH_MSG_FATAL (
"Unknown policy [{}] for the 'ClearStore-policy !\n"
321 "Valid values are: BeginEvent, EndEvent",
324 throw GaudiException(
"Can not setup 'ClearStore'-policy",
326 StatusCode::FAILURE);
348 unsigned int toolCtr = 0;
349 for ( ; firstTool != lastTool; ++firstTool )
369 CHECK( MinimalEventLoopMgr::stopRun() );
371 auto appProp = m_appMgrUI.as<IProperty>();
372 CHECK( Gaudi::setAppReturnCode( appProp, Gaudi::ReturnCode::ScheduledStop,
true ) );
373 return StatusCode::SUCCESS;
382 StatusCode
sc = MinimalEventLoopMgr::finalize();
383 if (
sc.isFailure()) {
388 if (sc2.isFailure()) {
404 unsigned int toolCtr = 0;
405 ATH_MSG_INFO (
"Summary of AthenaEvtLoopPreSelectTool invocation: (invoked/success/failure)" );
406 ATH_MSG_INFO (
"-----------------------------------------------------" );
408 for ( ; firstTool != lastTool; ++firstTool ) {
411 (*firstTool)->name(),
418 return (
sc.isFailure() || sc2.isFailure() ) ? StatusCode::FAILURE :
428 StatusCode
sc (StatusCode::SUCCESS);
431 std::vector<DataObject*> objects;
433 DataObject* obj = reg->object();
434 if ( !obj || obj->clID() == CLID_StatisticsFile )
return false;
435 objects.push_back( obj );
439 if ( !
sc.isSuccess() ) {
440 ATH_MSG_ERROR (
"Error while traversing Histogram data store" );
444 if ( objects.size() > 0) {
447 if (
m_nevt == 1 || force ||
448 (writeInterval != 0 &&
m_nevt%writeInterval == 0) ) {
451 sc = std::accumulate( begin( objects ), end( objects ),
sc, [&]( StatusCode isc,
auto& i ) {
452 IOpaqueAddress* pAddr =
nullptr;
454 if ( iret.isFailure() )
return iret;
455 i->registry()->setAddress( pAddr );
458 sc = std::accumulate( begin( objects ), end( objects ),
sc, [&]( StatusCode isc,
auto& i ) {
459 IRegistry* reg = i->registry();
460 StatusCode iret =
m_histoPersSvc->fillRepRefs( reg->address(), i );
461 return iret.isFailure() ? iret : isc;
463 if ( !
sc.isSuccess() ) {
468 if (force || (writeInterval != 0 &&
m_nevt%writeInterval == 0) ) {
486 ListAlg::iterator ita;
487 for ( ita = m_topAlgList.begin(); ita != m_topAlgList.end(); ++ita )
489 StatusCode
sc = (*ita)->sysInitialize();
492 ATH_MSG_ERROR(
"Unable to initialize Algorithm: {}", (*ita)->name()) ;
499 for (ita = m_outStreamList.begin(); ita != m_outStreamList.end(); ++ita )
501 StatusCode
sc = (*ita)->sysInitialize();
502 if(
sc.isFailure() ) {
503 ATH_MSG_ERROR (
"Unable to initialize Output Stream: {}", (*ita)->name() );
509 return StatusCode::SUCCESS;
518 for ( ListAlg::iterator ita = m_topAlgList.begin();
519 ita != m_topAlgList.end();
522 const StatusCode&
sc = (*ita)->sysExecute(ctx);
526 m_aess->algExecState(*ita,ctx).setState(AlgExecState::State::Done,
sc);
527 if ( !
sc.isSuccess() ) {
530 << (*ita)->name() <<
" failed with StatusCode::" <<
sc );
535 return StatusCode::SUCCESS;
546 m_incidentSvc->fireIncident(Incident(
"BeginEvent",IncidentType::BeginEvent));
548 m_incidentSvc->fireIncident(Incident(
"EndEvent",IncidentType::EndEvent));
570 bool toolsPassed=
true;
571 bool eventFailed =
false;
573 unsigned int toolCtr=0;
576 tool_store::iterator theTool =
m_tools.begin();
577 tool_store::iterator lastTool =
m_tools.end();
578 while(toolsPassed && theTool!=lastTool )
580 toolsPassed = (*theTool)->passEvent(ctx.eventID());
589 uint64_t evtNumber = ctx.eventID().event_number();
593 if (doEvtHeartbeat) {
595 ATH_MSG_INFO (
" ===>>> start processing event #{}, run #{} {} events processed so far <<<===",
598 ATH_MSG_INFO(
" ===>>> Event processing rate = {} Hz <<<===",
604 else ATH_MSG_INFO (
" ===>>> start processing event #{}, run #{} {} events read and {} events processed so far <<<===",
615 if ( m_scheduledStop ) {
616 ATH_MSG_ALWAYS (
"A stopRun was requested by an incidentListener. "
617 "Do not process this event." );
618 return (StatusCode::SUCCESS);
626 if(!
sc.isSuccess()) {
628 m_aess->setEventStatus( EventStatus::AlgFail, ctx );
635 "Skipping remaining algorithms.\n"
636 "\tNo output will be written for this event, "
637 "but job will continue to next event" );
644 "\tNo output will be written for this event, "
645 "but job will continue to next event" );
651 m_aess->setEventStatus( EventStatus::Success, ctx );
654 for (ListAlg::iterator ito = m_outStreamList.begin();
655 ito != m_outStreamList.end(); ++ito ) {
656 sc = (*ito)->sysExecute(ctx);
657 if( !
sc.isSuccess() ) {
671 if (doEvtHeartbeat) {
674 ATH_MSG_INFO(
" ===>>> done processing event #{}, run #{} {} events processed so far <<<===",
677 ATH_MSG_INFO(
" ===>>> done processing event #{}, run #{} {} events read and {} events processed so far <<<===",
680 std::ofstream outfile(
"eventLoopHeartBeat.txt");
684 std::println (outfile,
" done processing event #{}, run #{} {} events read so far <<<===",
694 return eventFailed?StatusCode::FAILURE:StatusCode::SUCCESS;
703 if (!(this->
nextEvent(maxevt)).isSuccess())
return StatusCode::FAILURE;
707 return StatusCode::SUCCESS;
716 if (0 == maxevt)
return StatusCode::SUCCESS;
718 static std::atomic<int> total_nevt = 0;
742 while(maxevt == -1 ||
m_nevt < maxevt) {
748 if ( m_scheduledStop ) {
749 m_scheduledStop =
false;
750 ATH_MSG_ALWAYS (
"A stopRun was requested. Terminating event loop." );
763 if( !
sc.isSuccess() ) {
778 IOpaqueAddress* addr =
nullptr;
782 if ( !
sc.isSuccess() )
786 sc = StatusCode::SUCCESS;
797 if (
nullptr != addr) {
800 if( !
sc.isSuccess() ) {
818 if( !
sc.isSuccess() )
820 ATH_MSG_ERROR (
"Terminating event processing loop due to errors" );
829 if( !
sc.isSuccess() ) {
853 ATH_MSG_ERROR (
"Seek failed; unsupported by event selector" );
854 return StatusCode::FAILURE;
859 ATH_MSG_FATAL (
"Can not create the event selector Context." );
860 return StatusCode::FAILURE;
866 if (
sc.isSuccess()) {
898 ATH_MSG_ERROR (
"Collection size unsupported by event selector" );
904 ATH_MSG_FATAL (
"Can not create the event selector Context." );
918 if(inc.type()!=
"BeforeFork")
922 ATH_MSG_WARNING (
"Skipping BeforeFork handler. Begin run has already passed" );
934 ATH_MSG_WARNING (
"Skipping BeforeFork handler. No event selector is provided" );
939 IOpaqueAddress* addr =
nullptr;
941 if(!
sc.isSuccess()) {
946 if (
sc.isFailure()) {
950 if (
nullptr != addr) {
953 if(!
sc.isSuccess()) {
971 throw std::runtime_error(
"Error installing event context object" );
980 ATH_MSG_ERROR (
"Unable to execute requested algorithms/sequences during PreFork!" );
988 if(!
sc.isSuccess()) {
998 IAlgManager* algMgr = Gaudi::svcLocator()->as<IAlgManager>();
1002 SmartIF<IAlgorithm>& alg = algMgr->algorithm(
name,
false);
1005 sc &= alg->sysExecute(ctx);
1017 std::unique_ptr<EventInfo> eventInfo;
1019 unsigned int conditionsRun = EventIDBase::UNDEFNUM;
1020 bool consume_modifier_stream =
false;
1026 ?
static_cast<long>(
m_nevt - 1)
1034 if (pAttrList !=
nullptr && pAttrList->size() > 6) {
1037 unsigned int runNumber = (*pAttrList)[
"RunNumber"].data<
unsigned int>();
1038 unsigned long long eventNumber = (*pAttrList)[
"EventNumber"].data<
unsigned long long>();
1039 unsigned int eventTime = (*pAttrList)[
"EventTime"].data<
unsigned int>();
1040 unsigned int eventTimeNS = (*pAttrList)[
"EventTimeNanoSec"].data<
unsigned int>();
1041 unsigned int lumiBlock = (*pAttrList)[
"LumiBlockN"].data<
unsigned int>();
1042 unsigned int bunchId = (*pAttrList)[
"BunchId"].data<
unsigned int>();
1045 consume_modifier_stream =
true;
1049 unsigned long long eventNumberSecondary{};
1050 if (!(pAttrList->exists(
"hasSecondaryInput") &&
1051 (*pAttrList)[
"hasSecondaryInput"].data<
bool>())) {
1052 ATH_MSG_FATAL(
"Secondary EventNumber requested, but secondary input does not exist!");
1053 return StatusCode::FAILURE;
1055 if (pAttrList->exists(
"EventNumber_secondary")) {
1056 eventNumberSecondary = (*pAttrList)[
"EventNumber_secondary"].data<
unsigned long long>();
1061 if (pEventSecondary) {
1062 eventNumberSecondary = pEventSecondary->
event_ID()->event_number();
1064 ATH_MSG_FATAL(
"Secondary EventNumber requested, but it does not exist!");
1065 return StatusCode::FAILURE;
1068 if (eventNumberSecondary != 0) {
1071 if (doEvtHeartbeat) {
1072 ATH_MSG_INFO(
" ===>>> using secondary event #{} instead of #{} <<<===",
1073 eventNumberSecondary, eventNumber);
1075 eventNumber = eventNumberSecondary;
1079 eventInfo = std::make_unique<EventInfo>(
1080 std::make_unique<EventID>(runNumber, eventNumber, eventTime,
1081 eventTimeNS, lumiBlock, bunchId),
1083 eventID = *(eventInfo->event_ID());
1085 if (!
m_evtIdModSvc.isSet() && pAttrList->exists(
"ConditionsRun")) {
1086 conditionsRun = (*pAttrList)[
"ConditionsRun"].data<
unsigned int>();
1088 conditionsRun = runNumber;
1106 ATH_MSG_FATAL(
"Valid input attribute list required but not present!");
1107 return StatusCode::FAILURE;
1120 if (xAODEvent ==
nullptr) {
1121 ATH_MSG_ERROR(
"Failed to get EventID from input. Tried old-style and xAOD::EventInfo");
1122 return StatusCode::FAILURE;
1126 eventInfo = std::make_unique<EventInfo>(
1129 eventID = *(eventInfo->event_ID());
1131 if (!
sc.isSuccess()) {
1133 return StatusCode::FAILURE;
1140 eventInfo = std::make_unique<EventInfo>(
1141 std::make_unique<EventID>(1,
m_nevt, 0), std::make_unique<EventType>());
1142 eventInfo->event_ID()->set_lumi_block(
m_nevt);
1143 eventID = *(eventInfo->event_ID());
1145 if (!
sc.isSuccess()) {
1147 return (StatusCode::FAILURE);
1151 ctx.setEventID( eventID );
1157 Gaudi::Hive::setCurrentContext( ctx );
1160 if (
m_eventStore->record(std::make_unique<EventContext> ( ctx ),
1161 "EventContext").isFailure())
1164 return (StatusCode::FAILURE);
1167 return StatusCode::SUCCESS;
1176 if (msgLevel(MSG::DEBUG)) {
1177 unsigned int oldrunnr=eID.run_number();
1178 unsigned int oldLB=eID.lumi_block();
1179 unsigned int oldTS=eID.time_stamp();
1180 unsigned int oldTSno=eID.time_stamp_ns_offset();
1181 ATH_MSG_DEBUG (
"modifyEventContext: use evtIdModSvc runnr={} -> {}",
1182 oldrunnr, new_eID.run_number());
1183 ATH_MSG_DEBUG (
"modifyEventContext: use evtIdModSvc LB={} -> {}",
1184 oldLB, new_eID.lumi_block());
1185 ATH_MSG_DEBUG (
"modifyEventContext: use evtIdModSvc TimeStamp={} -> {}",
1186 oldTS, new_eID.time_stamp());
1187 ATH_MSG_DEBUG (
"modifyEventContext: use evtIdModSvc TimeStamp ns Offset={} -> {}",
1188 oldTSno, new_eID.time_stamp_ns_offset());
1190 ctx.setEventID( new_eID );
1195 ctx.setEventID( eID );
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_ALWAYS(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
The default ATLAS batch event loop manager.
ClearStorePolicy::Type clearStorePolicy(const std::string &policyName, MsgStream &msg)
returns the enum-version of the policy (by name)
Helpers for checking error return status codes and reporting errors.
#define CHECK(...)
Evaluate an expression and check for errors.
Assign a CLID to EventContext.
This class provides a unique identification for each event, in terms of run/event number and/or a tim...
EventID eventIDFromxAOD(const xAOD::EventInfo *xaod)
Create EventID object from xAOD::EventInfo.
EventType eventTypeFromxAOD(const xAOD::EventInfo *xaod)
Create EventType object from xAOD::EventInfo.
This class provides general information about an event.
Extension to IEvtSelector to allow for seeking.
void setProperty(columnar::PythonToolHandle &self, const std::string &key, nb::object value)
An AttributeList represents a logical row of attributes in a metadata table.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
An AttributeList represents a logical row of attributes in a metadata table.
virtual ~AthenaEventLoopMgr()
Standard Destructor.
UnsignedIntegerProperty m_eventPrintoutInterval
IntegerProperty m_failureMode
IEvtSelector::Context * m_evtSelCtxt
Gaudi EventSelector Context (may be used as a cursor by the evt selector).
virtual int curEvent() const override
Return the current event count.
tool_stats m_toolInvoke
tool called counter
IIncidentSvc_t m_incidentSvc
Reference to the incident service.
unsigned int m_nev
events processed
StoreGateSvc_t m_eventStore
Reference to StoreGateSvc;.
bool m_useSecondaryEventNumber
read event number from secondary input
tool_stats m_toolAccept
tool returns StatusCode::SUCCESS counter
virtual void handle(const Incident &inc) override
IIncidentListenet interfaces.
bool m_requireInputAttributeList
require input attribute list
SmartIF< IAlgExecStateSvc > m_aess
Reference to the Algorithm Execution State Svc.
virtual StatusCode writeHistograms(bool force=false)
Dump out histograms as needed.
StringProperty m_histPersName
tool_stats m_toolReject
tool returns StatusCode::FAILURE counter
AthenaEventLoopMgr()
no implementation
StatusCode execAtPreFork(const EventContext &ctx) const
Execute certain algorithms/sequences in PreFork.
IConversionSvc_t m_histoPersSvc
IEvtSelector * m_evtSelector
Reference to the Event Selector.
virtual StatusCode executeEvent(EventContext &&ctx) override
implementation of IEventProcessor::executeEvent(EventContext&& ctx)
virtual StatusCode initialize() override
implementation of IAppMgrUI::initalize
virtual StatusCode seek(int evt) override
Seek to a given event.
virtual int size() override
Return the size of the collection.
IEvtIdModifierSvc_t m_evtIdModSvc
virtual StatusCode finalize() override
implementation of IAppMgrUI::finalize
IntegerProperty m_writeInterval
StringProperty m_clearStorePolicy
ServiceHandle< IConversionSvc > IConversionSvc_t
StatusCode installEventContext(EventContext &ctx)
virtual StatusCode stopRun() override
Called from ApplicationMgr::stopRun() to terminate the loop.
void setupPreSelectTools(Gaudi::Details::PropertyBase &)
property update handler:sets up the Pre-selection tools
virtual const std::string & name() const override
virtual StatusCode executeAlgorithms(const EventContext &)
Run the algorithms for the current event.
StringArrayProperty m_execAtPreFork
virtual void modifyEventContext(EventContext &ctx, const EventID &eID, bool consume_modifier_stream)
number_type m_currentRun
current run number
unsigned int m_intervalInSeconds
StatusCode initializeAlgorithms()
Initialize all algorithms and output streams.
tool_store::const_iterator tool_iterator
tool_store m_tools
internal tool store
virtual StatusCode executeRun(int maxevt) override
implementation of IEventProcessor::executeRun(int maxevt)
virtual StatusCode nextEvent(int maxevt) override
implementation of IAppMgrUI::nextEvent. maxevt==0 returns immediately
ServiceHandle< IChronoStatSvc > m_chronoStatSvc
ServiceHandle< Athena::IConditionsCleanerSvc > m_conditionsCleaner
IDataManagerSvc_t m_histoDataMgrSvc
Reference to the Histogram Data Service.
virtual void setNextEventModifierIndex(long idx) override
Supply absolute input event index for EvtIdModifierSvc. See IEventSeek.h.
void setClearStorePolicy(Gaudi::Details::PropertyBase &clearStorePolicy)
property update handler:set the clear-store policy value and check its value.
void resetTimeout(Timeout &instance)
Reset timeout.
static Timeout & instance()
Get reference to Timeout singleton.
void setConditionsRun(EventIDBase::number_type conditionsRun)
This class provides a unique identification for each event, in terms of run/event number and/or a tim...
This class provides general information about an event.
EventID * event_ID()
the unique identification of the event.
Abstract interface for seeking for an event selector.
virtual StatusCode seek(IEvtSelector::Context &c, int evtnum) const =0
Seek to a given event number.
virtual int size(IEvtSelector::Context &c) const =0
Return the size of the collection, or -1 if we can't get the size.
uint32_t runNumber() const
The current event's run number.
void setExtendedEventContext(EventContext &ctx, ExtendedEventContext &&ectx)
Move an extended context into a context object.
const ExtendedEventContext & getExtendedEventContext(const EventContext &ctx)
Retrieve an extended context from a context object.
event_number_t eventIndex
EventInfo_v1 EventInfo
Definition of the latest event info version.