7#include "GaudiKernel/AppReturnCode.h"
19using Clock = std::chrono::high_resolution_clock;
48 return StatusCode::SUCCESS;
71 return StatusCode::FAILURE;
73 if (maxEvt < 0 || (skipEvts + maxEvt) > evt) {
74 maxEvt = evt - skipEvts;
76 ATH_MSG_INFO(
"Will be processing " << maxEvt <<
" events");
80 std::vector<bool> workers_done(
m_clusterSvc->numRanks(),
false);
83 int num_workers_done = 1;
84 std::vector<ClusterMessage::WorkerStatus> statuses(
m_clusterSvc->numRanks());
90 auto start = Clock::now();
91 for (
int evt = skipEvts; evt < skipEvts + maxEvt;) {
94 if (
msg.messageType == ClusterMessageType::RequestEvent) {
102 if (
msg.messageType == ClusterMessageType::WorkerError) {
105 workers_done.at(
msg.source) =
109 if (!workers_done.at(i)) {
113 workers_done[i] =
true;
120 if (
msg.messageType == ClusterMessageType::FinalWorkerStatus) {
123 workers_done.at(
msg.source) =
true;
130 msg.messageType,
msg.source);
132 auto all_provided = Clock::now() - start;
133 ATH_MSG_INFO(
"Provided all events to workers, waiting for them to complete.");
135 while (num_workers_done < m_clusterSvc->numRanks()) {
138 if (
msg.messageType == ClusterMessageType::RequestEvent) {
144 if (
msg.messageType == ClusterMessageType::WorkerError) {
147 workers_done.at(
msg.source) =
151 if (!workers_done.at(i)) {
155 workers_done[i] =
true;
162 if (
msg.messageType == ClusterMessageType::FinalWorkerStatus) {
165 workers_done.at(
msg.source) =
true;
172 msg.messageType,
msg.source);
174 auto all_done = Clock::now() - start;
180 StatusCode
sc = StatusCode::SUCCESS;
182 for (
const auto& worker_status : statuses) {
183 if (worker_status.status.isFailure() &&
184 worker_status.status != StatusCode(9999)) {
185 sc = worker_status.status;
187 n_created += worker_status.createdEvents;
188 n_skipped += worker_status.skippedEvents;
189 n_finished += worker_status.finishedEvents;
191 if ((worker_idx++) != 0) {
192 ATH_MSG_INFO(
"Worker " << worker_idx <<
": SC " << worker_status.status
193 <<
", created " << worker_status.createdEvents
194 <<
", skipped " << worker_status.skippedEvents
195 <<
", finished " << worker_status.finishedEvents);
199 ATH_MSG_INFO(
"Overall: SC " <<
sc <<
", created " << n_created <<
", skipped "
200 << n_skipped <<
", finished " << n_finished);
202 std::chrono::hh_mm_ss(all_provided));
204 std::chrono::hh_mm_ss(all_done));
210 bool end_of_stream =
false;
213 auto start = Clock::now();
225 if (
sc.isFailure()) {
237 auto start_time = Clock::now();
241 auto request_time = Clock::now() - start_time;
242 if (
msg.messageType == ClusterMessageType::EmergencyStop) {
245 std::size_t numSlots =
m_whiteboard->getNumberOfStores();
251 return StatusCode::FAILURE;
254 if (
msg.messageType == ClusterMessageType::EventsDone) {
255 auto loop_time = Clock::now() - start;
256 ATH_MSG_INFO(
"Worker {} DONE. Loop took {} to process {} events.",
258 std::chrono::hh_mm_ss(loop_time),
264 StatusCode
sc = StatusCode::SUCCESS;
265 std::size_t numSlots =
m_whiteboard->getNumberOfStores();
274 0,
ClusterMessage(ClusterMessageType::FinalWorkerStatus, status));
279 if (
msg.messageType != ClusterMessageType::ProvideEvent ||
282 msg.messageType,
msg.source);
284 status.status = StatusCode::FAILURE;
290 return StatusCode::FAILURE;
297 std::chrono::duration_cast<std::chrono::nanoseconds>(request_time)
299 if (
sc.isFailure() && !
sc.isRecoverable()) {
310 auto loop_time = Clock::now() - start;
311 ATH_MSG_INFO(
"Worker {} DONE. Loop took to process events.",
313 std::chrono::hh_mm_ss(loop_time),
318 StatusCode
sc = StatusCode::SUCCESS;
319 std::size_t numSlots =
m_whiteboard->getNumberOfStores();
328 0,
ClusterMessage(ClusterMessageType::FinalWorkerStatus, status));
336 std::int64_t requestTime_ns) {
342 Gaudi::Hive::setCurrentContext(ctx);
348 return StatusCode::FAILURE;
351 const std::size_t slot = ctx.slot();
357 ATH_MSG_ERROR(
"Cannot jump backwards by {} events", nToJump);
358 return StatusCode::FAILURE;
369 m_clusterSvc->log_addEvent(eventIdx, evtID.run_number(), evtID.event_number(),
370 requestTime_ns, slot);
372 if (
sc.isRecoverable()) {
374 }
else if (
sc.isSuccess()) {
384 StatusCode
sc(StatusCode::SUCCESS);
387 std::vector<std::unique_ptr<EventContext>> finishedEvtContexts;
389 EventContext* finishedEvtContext(
nullptr);
392 ATH_MSG_DEBUG(
"drainLocalScheduler: [{}] Waiting for a context",
397 if (
sc.isSuccess()) {
398 ATH_MSG_DEBUG(
"drainLocalScheduler: scheduler not empty: Context "
399 << finishedEvtContext);
400 finishedEvtContexts.emplace_back(finishedEvtContext);
404 return StatusCode::SUCCESS;
408 while (
m_schedulerSvc->tryPopFinishedEvent(finishedEvtContext).isSuccess()) {
409 finishedEvtContexts.emplace_back(finishedEvtContext);
413 StatusCode fail(StatusCode::SUCCESS);
414 for (
auto& thisFinishedEvtContext : finishedEvtContexts) {
415 if (!thisFinishedEvtContext) {
417 fail = StatusCode::FAILURE;
423 thisFinishedEvtContext->evt(),
424 thisFinishedEvtContext->eventID().run_number(),
425 thisFinishedEvtContext->eventID().event_number(),
426 m_aess->eventStatus(*thisFinishedEvtContext));
428 if (
m_aess->eventStatus(*thisFinishedEvtContext) != EventStatus::Success) {
430 << thisFinishedEvtContext <<
" w/ fail mode: "
431 <<
m_aess->eventStatus(*thisFinishedEvtContext));
436 fail = StatusCode::FAILURE;
445 EventID::event_number_t n_evt(0);
447 if (
m_whiteboard->selectStore(thisFinishedEvtContext->slot()).isSuccess()) {
448 n_run = thisFinishedEvtContext->eventID().run_number();
449 n_evt = thisFinishedEvtContext->eventID().event_number();
452 thisFinishedEvtContext->slot());
453 thisFinishedEvtContext.reset();
454 fail = StatusCode::FAILURE;
460 Gaudi::Hive::setCurrentContext(*thisFinishedEvtContext);
462 Incident(
name(), IncidentType::EndProcessing, *thisFinishedEvtContext));
464 ATH_MSG_DEBUG(
"Clearing slot {} (event {}) of the whiteboard",
465 thisFinishedEvtContext->slot(),
466 thisFinishedEvtContext->evt());
469 if (!
sc.isSuccess()) {
470 ATH_MSG_ERROR(
"Whiteboard slot {} could not be properly cleared",
471 thisFinishedEvtContext->slot());
472 if (fail != StatusCode::FAILURE) {
475 thisFinishedEvtContext.reset();
486 ATH_MSG_INFO(
" ===>>> done processing event #{}, run #{} on slot {}, {} events processed so far <<<===",
487 n_evt, n_run, thisFinishedEvtContext->slot(),
m_proc);
489 ATH_MSG_INFO(
" ===>>> done processing event #{}, run #{} on slot {}, {} events read and {} events processed so far <<<===",
490 n_evt, n_run, thisFinishedEvtContext->slot(),
m_nev,
m_proc);
493 std::ofstream outfile(
"eventLoopHeartBeat.txt");
496 fail = StatusCode::FAILURE;
497 thisFinishedEvtContext.reset();
500 std::println (outfile,
" done processing event #{}, run #{} {} events read so far <<<===",
501 n_evt, n_run,
m_nev);
506 << thisFinishedEvtContext);
508 thisFinishedEvtContext.reset();
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
std::chrono::high_resolution_clock Clock
The MPI event loop manager.
IEvtSelector * m_evtSelector
Reference to the Event Selector.
virtual StatusCode initialize() override
implementation of IAppMgrUI::initalize
SmartIF< IHiveWhiteBoard > m_whiteboard
Reference to the Whiteboard interface.
virtual int size() override
Return the size of the collection.
SmartIF< IAlgExecStateSvc > m_aess
Reference to the Algorithm Execution State Svc.
virtual const std::string & name() const override
unsigned int m_nev
events processed
IIncidentSvc_t m_incidentSvc
Reference to the incident service.
SmartIF< IProperty > m_appMgrProperty
Property interface of ApplicationMgr.
MsgStream & msg() const
The standard message stream.
EvtContext * m_evtContext
Gaudi event selector Context (may be used as a cursor by the evt selector).
AthenaHiveEventLoopMgr(const std::string &nam, ISvcLocator *svcLoc)
Standard Constructor.
virtual StatusCode finalize() override
implementation of IAppMgrUI::finalize
virtual StatusCode executeEvent(EventContext &&ctx) override
implementation of IEventProcessor::executeEvent(void* par)
EventContext m_lastEventContext
virtual EventContext createEventContext() override
Create event context.
StatusCode clearWBSlot(int evtSlot)
Clear a slot in the WB.
virtual StatusCode writeHistograms(bool force=false)
Dump out histograms as needed.
SmartIF< IScheduler > m_schedulerSvc
A shortcut for the scheduler.
EventIDBase::number_type number_type
StatusCode workerEventLoop()
Worker event loop (runs on worker, requests events over MPI).
StatusCode drainLocalScheduler()
Drain the local scheduler of any (at least one) completed events.
int m_contiguousFailedEvts
ServiceHandle< IMPIClusterSvc > m_clusterSvc
Reference to the MPIClusterSvc.
MPIHiveEventLoopMgr(const std::string &name, ISvcLocator *svcLoc)
Standard Constructor.
virtual StatusCode finalize() override
implementation of IAppMgrUI::finalize
virtual ~MPIHiveEventLoopMgr()
Standard Destructor.
virtual StatusCode nextEvent(int maxevt) override
implementation of IAppMgrUI::nextEvent. maxevt==0 returns immediately
StatusCode masterEventLoop(int maxEvt)
Master event loop (runs on master, provides events over MPI).
virtual StatusCode initialize() override
implementation of IAppMgrUI::initalize
StatusCode insertEvent(int eventIdx, bool &endOfStream, std::int64_t requestTime_ns)
Insert an event into the local scheduler.
UnsignedIntegerProperty m_firstEventIndex
int m_evtSelectorCurrentPos
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
int count(std::string s, const std::string ®x)
count how many occurances of a regx are in a string
A class describing a message sent between nodes in a cluster.