ATLAS Offline Software
Loading...
Searching...
No Matches
AthenaMtesEventLoopMgr.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "ClearStorePolicy.h"
8
15#include "CxxUtils/xmalloc.h"
16
17#include "GaudiKernel/IAlgorithm.h"
18#include "GaudiKernel/SmartIF.h"
19#include "GaudiKernel/Incident.h"
20#include "GaudiKernel/DataObject.h"
21#include "GaudiKernel/IIncidentSvc.h"
22#include "GaudiKernel/IDataManagerSvc.h"
23#include "GaudiKernel/IDataProviderSvc.h"
24#include "GaudiKernel/IConversionSvc.h"
25#include "GaudiKernel/GaudiException.h"
26#include "GaudiKernel/AppReturnCode.h"
27#include "GaudiKernel/MsgStream.h"
28#include "GaudiKernel/EventIDBase.h"
29#include "GaudiKernel/ThreadLocalContext.h"
30#include "GaudiKernel/FileIncident.h"
31
33
34#include "EventInfo/EventInfo.h"
35#include "EventInfo/EventID.h"
36#include "EventInfo/EventType.h"
39
40#include "tbb/tick_count.h"
41#include <yampl/ISocket.h>
42#include "yampl/SocketFactory.h"
43
44#include <cassert>
45#include <ios>
46#include <iostream>
47#include <fstream>
48#include <iomanip>
49#include <cstdlib>
50#include <print>
51#include <unistd.h>
52
53namespace {
54 bool
55 leftString(std::string & s, char sc){
56 bool truncated{false};
57 auto n = s.find(sc);
58 if (n!=std::string::npos){
59 s.resize(n);
60 truncated=true;
61 }
62 return truncated;
63}
64
65 bool
66 leftString(std::string & s, int n){
67 bool truncated{false};
68 if (static_cast<size_t>(n) < s.size()){
69 s.resize(n);
70 truncated=true;
71 }
72 return truncated;
73 }
74}
75
77 , ISvcLocator* svcLoc)
78 : base_class(nam, svcLoc)
79 , m_incidentSvc ( "IncidentSvc", nam )
80 , m_eventStore( "StoreGateSvc", nam )
81 , m_evtSelector{nullptr}
82 , m_evtContext{nullptr}
83 , m_histoDataMgrSvc( "HistogramDataSvc", nam )
84 , m_histoPersSvc ( "HistogramPersistencySvc", nam )
85 , m_evtIdModSvc("", nam)
86 , m_currentRun(0)
87 , m_firstRun(true)
88 , m_tools(this)
89 , m_nevt(0)
90 , m_writeHists(false)
91 , m_nev(0)
92 , m_proc(0)
93 , m_useTools(false)
94 , m_doEvtHeartbeat(false)
95 , m_conditionsCleaner( "Athena::ConditionsCleanerSvc", nam )
96 , m_outSeqSvc("OutputStreamSequencerSvc", nam)
97{
98 declareProperty("EvtSel", m_evtsel,
99 "Name of Event Selector to use. If empty string (default) "
100 "take value from ApplicationMgr");
101 declareProperty("HistogramPersistency", m_histPersName="",
102 "Histogram persistency technology to use: ROOT, HBOOK, NONE. "
103 "By default (empty string) get property value from "
104 "ApplicationMgr");
105 declareProperty("HistWriteInterval", m_writeInterval=0 ,
106 "histogram write/update interval");
107 declareProperty("FailureMode", m_failureMode=1 ,
108 "Controls behaviour of event loop depending on return code of"
109 " Algorithms. 0: all non-SUCCESSes terminate job. "
110 "1: RECOVERABLE skips to next event, FAILURE terminates job "
111 "(DEFAULT). 2: RECOVERABLE and FAILURE skip to next events");
112 declareProperty("EventPrintoutInterval", m_eventPrintoutInterval=1,
113 "Print event heartbeat printouts every m_eventPrintoutInterval events");
114 declareProperty("ClearStorePolicy",
115 m_clearStorePolicy = "EndEvent",
116 "Configure the policy wrt handling of when the "
117 "'clear-the-event-store' event shall happen: at EndEvent "
118 "(default as it is makes things easier for memory management"
119 ") or at BeginEvent (easier e.g. for interactive use)");
120 declareProperty("PreSelectTools",m_tools,"AlgTools for event pre-selection")->
121 declareUpdateHandler( &AthenaMtesEventLoopMgr::setupPreSelectTools, this );
122
123 declareProperty("SchedulerSvc", m_schedulerName="ForwardSchedulerSvc",
124 "Name of the scheduler to be used");
125
126 declareProperty("WhiteboardSvc", m_whiteboardName="EventDataSvc",
127 "Name of the Whiteboard to be used");
128
129 declareProperty("EventStore", m_eventStore);
130
131 declareProperty("EvtIdModifierSvc", m_evtIdModSvc,
132 "ServiceHandle for EvtIdModifierSvc");
133
134 declareProperty("FakeLumiBlockInterval", m_flmbi = 0,
135 "Event interval at which to increment lumiBlock# when "
136 "creating events without an EventSelector. Zero means "
137 "don't increment it");
138 declareProperty("FakeTimestampInterval", m_timeStampInt = 1,
139 "timestamp interval between events when creating Events "
140 "without an EventSelector");
141 declareProperty("RequireInputAttributeList", m_requireInputAttributeList = false,
142 "Require valid input attribute list to be present");
143 declareProperty("UseSecondaryEventNumber", m_useSecondaryEventNumber = false,
144 "In case of DoubleEventSelector use event number from secondary input");
145
146 declareProperty("ESTestPilotMessages", m_testPilotMessages, "List of messages from fake pilot for test mode");
147
148 m_scheduledStop = false;
149
150}
151
155
157{
158 ATH_MSG_INFO ( "Initializing {}", name() ) ;
159
160 StatusCode sc = MinimalEventLoopMgr::initialize();
161 if(!sc.isSuccess()) {
162 ATH_MSG_ERROR ( "Failed to initialize base class MinimalEventLoopMgr" );
163 return sc;
164 }
165
166//-------------------------------------------------------------------------
167// Setup stuff for hive
168//-------------------------------------------------------------------------
169
170 m_whiteboard = serviceLocator()->service(m_whiteboardName);
171 if(!m_whiteboard.isValid()) {
172 ATH_MSG_FATAL ( "Error retrieving {} interface IHiveWhiteBoard.", m_whiteboardName );
173 return StatusCode::FAILURE;
174 }
175
176 m_schedulerSvc = serviceLocator()->service(m_schedulerName);
177 if(!m_schedulerSvc.isValid()) {
178 ATH_MSG_FATAL ( "Error retrieving SchedulerSvc interface ISchedulerSvc." );
179 return StatusCode::FAILURE;
180 }
181
182 m_algResourcePool = serviceLocator()->service("AlgResourcePool");
183 if(!m_algResourcePool.isValid()) {
184 ATH_MSG_FATAL ( "Error retrieving AlgResourcePool" );
185 return StatusCode::FAILURE;
186 }
187
188 m_aess = serviceLocator()->service("AlgExecStateSvc");
189 if(!m_aess.isValid()) {
190 ATH_MSG_FATAL ( "Error retrieving AlgExecStateSvc" );
191 return StatusCode::FAILURE;
192 }
193
194 ATH_CHECK(m_eventStore.retrieve());
195 ATH_CHECK(m_incidentSvc.retrieve());
196
197//--------------------------------------------------------------------------
198// Access Property Manager interface:
199//--------------------------------------------------------------------------
200 SmartIF<IProperty> prpMgr(serviceLocator());
201 if(!prpMgr.isValid()) {
202 ATH_MSG_FATAL ( "IProperty interface not found in ApplicationMgr." );
203 return StatusCode::FAILURE;
204 }
205
206 ATH_CHECK(m_histoDataMgrSvc.retrieve());
207
208 const std::string& histPersName(m_histPersName.value());
209 if(histPersName.empty()) {
210 ATH_CHECK(setProperty(prpMgr->getProperty("HistogramPersistency")));
211 }
212
213 if(histPersName != "NONE") {
214
215 m_histoPersSvc = IConversionSvc_t( "HistogramPersistencySvc",
216 this->name() );
217
218 SmartIF<IProperty> histSvc{serviceLocator()->service("RootHistSvc")};
219
220 if (!histSvc) {
221 ATH_MSG_ERROR ( "could not locate actual Histogram persistency service" );
222 }
223 else {
224 const Gaudi::Details::PropertyBase &prop = histSvc->getProperty("OutputFile");
225 std::string val;
226 try {
227 const StringProperty &sprop = dynamic_cast<const StringProperty&>(prop);
228 val = sprop.value();
229 }
230 catch (...) {
231 ATH_MSG_VERBOSE ( "could not dcast OutputFile property to a StringProperty."
232 " Need to fix Gaudi." );
233 val = prop.toString();
234 }
235
236 if (val != ""
237 && val != "UndefinedROOTOutputFileName") {
238 m_writeHists = true;
239 }
240 }
241 }
242 else {
243 ATH_MSG_DEBUG ( "Histograms saving not required." );
244 }
245
246 //--------------------------------------------------------------------------
247 // Set up the EventID modifier Service
248 //--------------------------------------------------------------------------
249 if (m_evtIdModSvc.empty()) {
250 ATH_MSG_DEBUG ( "EventID modifier Service not set. No run number, ... overrides will be applied." );
251 } else if (!m_evtIdModSvc.retrieve().isSuccess()) {
252 ATH_MSG_DEBUG ( "Could not find EventID modifier Service. No run number, ... overrides will be applied." );
253 }
254
255 //-------------------------------------------------------------------------
256 // Setup EventSelector service
257 //-------------------------------------------------------------------------
258 const std::string& selName(m_evtsel.value());
259 // the evt sel is usually specified as a property of ApplicationMgr
260 if (selName.empty()) {
261 sc = setProperty(prpMgr->getProperty("EvtSel"));
262 }
263 if (sc.isFailure()) ATH_MSG_WARNING ( "Unable to set EvtSel property" );
264
265 // We do not expect a Event Selector necessarily being declared
266 if( !selName.empty() && selName != "NONE") {
267 SmartIF<IEvtSelector> theEvtSel{serviceLocator()->service(selName)};
268 if(theEvtSel && (theEvtSel != m_evtSelector)) {
269 // Event Selector changed (or setup for the first time)
270 m_evtSelector = theEvtSel;
271
272 // reset iterator
273 if (m_evtSelector->createContext(m_evtContext).isFailure()) {
274 ATH_MSG_FATAL ( "Can not create the event selector Context." );
275 return StatusCode::FAILURE;
276 }
277 if (msgLevel(MSG::INFO)) {
278 SmartIF<INamedInterface> named{theEvtSel};
279 if (named) {
280 ATH_MSG_INFO ( "Setup EventSelector service {}", named->name( ) );
281 }
282 }
283 }
284 else if (sc.isFailure()) {
285 ATH_MSG_FATAL ( "No valid event selector called {}", selName );
286 return StatusCode::FAILURE;
287 }
288 }
289
290//-------------------------------------------------------------------------
291// Setup 'Clear-Store' policy
292//-------------------------------------------------------------------------
293 try {
295 } catch(...) {
296 return StatusCode::FAILURE;
297 }
298
299 // Listen to the BeforeFork incident
300 m_incidentSvc->addListener(this,"BeforeFork",0);
301
302 CHECK( m_conditionsCleaner.retrieve() );
303 CHECK( m_outSeqSvc.retrieve() );
304
305 // Print if we override the event number using the one from secondary event
307 ATH_MSG_INFO ( "Using secondary event number." );
308 }
309
310 if( m_testPilotMessages.value().size() > 0 ) {
311 ATH_MSG_INFO( "running in standalone TEST MODE" );
312 ATH_MSG_INFO( " test contains {} event ranges",
313 m_testPilotMessages.value().size() );
314 for( const std::string& range: m_testPilotMessages.value() ) {
315 ATH_MSG_DEBUG (" {}", range);
316 }
317 m_inTestMode = true;
318 }
319 return sc;
320}
321
322//=========================================================================
323// property handlers
324//=========================================================================
325void
326AthenaMtesEventLoopMgr::setClearStorePolicy(Gaudi::Details::PropertyBase&) {
327 const std::string& policyName = m_clearStorePolicy.value();
328
329 if ( policyName != "BeginEvent" &&
330 policyName != "EndEvent" ) {
331
332 ATH_MSG_FATAL ( "Unknown policy [{}] for the 'ClearStore-policy !\n"
333 "Valid values are: BeginEvent, EndEvent",
334 policyName
335 );
336 throw GaudiException("Can not setup 'ClearStore'-policy",
337 name(),
338 StatusCode::FAILURE);
339 }
340
341 return;
342}
343
344void
345AthenaMtesEventLoopMgr::setupPreSelectTools(Gaudi::Details::PropertyBase&) {
346
347 m_toolInvoke.clear();
348 m_toolReject.clear();
349 m_toolAccept.clear();
350
351 m_tools.retrieve().ignore();
352 if(m_tools.size() > 0) {
353 m_useTools=true;
354 m_toolInvoke.resize(m_tools.size());
355 m_toolReject.resize(m_tools.size());
356 m_toolAccept.resize(m_tools.size());
357
358 tool_iterator firstTool = m_tools.begin();
359 tool_iterator lastTool = m_tools.end();
360 unsigned int toolCtr = 0;
361 for ( ; firstTool != lastTool; ++firstTool )
362 {
363 // reset statistics
364 m_toolInvoke[toolCtr] = 0;
365 m_toolReject[toolCtr] = 0;
366 m_toolAccept[toolCtr] = 0;
367 toolCtr++;
368 }
369 }
370
371 return;
372
373}
374
375//=========================================================================
376// implementation of IAppMgrUI::finalize
377//=========================================================================
379{
380
381 StatusCode sc = MinimalEventLoopMgr::finalize();
382 if (sc.isFailure())
383 {
384 ATH_MSG_ERROR ( "Error in Service base class Finalize" );
385 }
386
387 StatusCode sc2 = writeHistograms(true);
388 if (sc2.isFailure())
389 {
390 ATH_MSG_ERROR ( "Error in writing Histograms" );
391 }
392
393 // Release all interfaces (ignore StatusCodes)
394 m_histoDataMgrSvc.release().ignore();
395 m_histoPersSvc.release().ignore();
396
397 m_whiteboard = 0;
399 m_schedulerSvc = 0;
400 // m_evtDataSvc = 0;
401
402 m_incidentSvc.release().ignore();
403
404 // Release event selector context
405 if ( m_evtSelector && m_evtContext ) {
406 m_evtSelector->releaseContext(m_evtContext).ignore();
407 // m_evtSelector = releaseInterface(m_evtSelector);
408 delete m_evtContext; m_evtContext = 0;
409 }
410
411
412 if(m_useTools) {
413 tool_iterator firstTool = m_tools.begin();
414 tool_iterator lastTool = m_tools.end();
415 unsigned int toolCtr = 0;
416 ATH_MSG_INFO ( "Summary of AthenaEvtLoopPreSelectTool invocation: (invoked/success/failure)" );
417 ATH_MSG_INFO ( "-----------------------------------------------------" );
418
419 for ( ; firstTool != lastTool; ++firstTool ) {
420 ATH_MSG_INFO ( "{:>2}.) {:.<48} ({:>6}/{:>6}/{:>6})",
421 toolCtr+1,
422 (*firstTool)->name(),
423 m_toolInvoke[toolCtr],
424 m_toolAccept[toolCtr],
425 m_toolReject[toolCtr]);
426 toolCtr++;
427 }
428 }
429
430 return ( sc.isFailure() || sc2.isFailure() ) ? StatusCode::FAILURE :
431 StatusCode::SUCCESS;
432
433}
434
435//=========================================================================
436// write out the histograms
437//=========================================================================
439
440 StatusCode sc (StatusCode::SUCCESS);
441
442 if ( 0 != m_histoPersSvc && m_writeHists ) {
443 std::vector<DataObject*> objects;
444 sc = m_histoDataMgrSvc->traverseTree( [&objects]( IRegistry* reg, int ) {
445 DataObject* obj = reg->object();
446 if ( !obj || obj->clID() == CLID_StatisticsFile ) return false;
447 objects.push_back( obj );
448 return true;
449 } );
450
451 if ( !sc.isSuccess() ) {
452 ATH_MSG_ERROR ( "Error while traversing Histogram data store" );
453 return sc;
454 }
455
456 if ( objects.size() > 0) {
457 int writeInterval(m_writeInterval.value());
458
459 if ( m_nevt == 1 || force ||
460 (writeInterval != 0 && m_nevt%writeInterval == 0) ) {
461
462 // skip /stat entry!
463 sc = std::accumulate( begin( objects ), end( objects ), sc, [&]( StatusCode isc, auto& i ) {
464 IOpaqueAddress* pAddr = nullptr;
465 StatusCode iret = m_histoPersSvc->createRep( i, pAddr );
466 if ( iret.isFailure() ) return iret;
467 i->registry()->setAddress( pAddr );
468 return isc;
469 } );
470 sc = std::accumulate( begin( objects ), end( objects ), sc, [&]( StatusCode isc, auto& i ) {
471 IRegistry* reg = i->registry();
472 StatusCode iret = m_histoPersSvc->fillRepRefs( reg->address(), i );
473 return iret.isFailure() ? iret : isc;
474 } );
475 if ( ! sc.isSuccess() ) {
476 ATH_MSG_ERROR ( "Error while saving Histograms." );
477 }
478 }
479
480 if (force || (writeInterval != 0 && m_nevt%writeInterval == 0) ) {
481 ATH_MSG_DEBUG ( "committing Histograms" );
482 m_histoPersSvc->conversionSvc()->commitOutput("",true).ignore();
483 }
484 }
485
486 }
487
488 return sc;
489}
490
491//=========================================================================
492// Call sysInitialize() on all algorithms and output streams
493//=========================================================================
495
496 return StatusCode::SUCCESS;
497}
498
499//=========================================================================
500// Run the algorithms for the current event
501//=========================================================================
503
504 return StatusCode::SUCCESS;
505}
506
507
508//=========================================================================
509// executeEvent( EventContext &&ctx )
510//=========================================================================
511StatusCode AthenaMtesEventLoopMgr::executeEvent( EventContext &&ctx )
512{
513
514 // An incident may schedule a stop, in which case is better to exit before the actual execution.
515 if ( m_scheduledStop ) {
516 ATH_MSG_ALWAYS ( "A stopRun was requested by an incidentListener. "
517 "Do not process this event." );
518 m_terminateLoop = true;
519 return (StatusCode::SUCCESS);
520 }
521
522 m_aess->reset( ctx );
523
524 // Make sure context with slot is set before calling es->next().
525 Gaudi::Hive::setCurrentContext ( ctx );
526
527 int declEvtRootSc = declareEventRootAddress(ctx);
528 if (declEvtRootSc == 0 ) { // We ran out of events!
529 m_terminateLoop = true; // we have finished!
530 return StatusCode::SUCCESS;
531 } else if ( declEvtRootSc == -1) {
532 // No std::format for EventContext
533 ATH_MSG_ERROR ( "declareEventRootAddress for context " << ctx << " failed" );
534 return StatusCode::FAILURE;
535 }
536
537 EventID::event_number_t evtNumber = ctx.eventID().event_number();
538 unsigned int conditionsRun = ctx.eventID().run_number();
539 if (!m_evtIdModSvc.isSet()) {
540 const AthenaAttributeList* attr = nullptr;
541 if (m_eventStore->contains<AthenaAttributeList>("Input") &&
542 m_eventStore->retrieve(attr, "Input").isSuccess()) {
543 if (attr->exists("ConditionsRun")) {
544 conditionsRun = (*attr)["ConditionsRun"].data<unsigned int>();
545 }
546 }
547 }
549 Gaudi::Hive::setCurrentContext ( ctx );
550
551 // Record EventContext in current whiteboard
552 if (m_eventStore->record(std::make_unique<EventContext> (ctx),
553 "EventContext").isFailure())
554 {
555 ATH_MSG_ERROR ( "Error recording event context object" );
556 return (StatusCode::FAILURE);
557 }
558
560 if (m_firstRun || (m_currentRun != ctx.eventID().run_number()) ) {
561 // Fire EndRun incident unless this is the first run
562 if (!m_firstRun) {
563 // FIXME!!!
564 m_incidentSvc->fireIncident(Incident(name(), IncidentType::EndRun));
565 }
566 m_firstRun=false;
567 m_currentRun = ctx.eventID().run_number();
568
569 ATH_MSG_INFO ( " ===>>> start of run {} <<<===", m_currentRun);
570
571 // FIXME!!! Fire BeginRun "Incident"
572 m_incidentSvc->fireIncident(Incident(name(),IncidentType::BeginRun,ctx));
573
574 }
575
576 bool toolsPassed=true;
577 // CGL: FIXME
578 // bool eventFailed = false;
579
580 // Call any attached tools to reject events early
581 unsigned int toolCtr=0;
582 if(m_useTools) {
583 tool_store::iterator theTool = m_tools.begin();
584 tool_store::iterator lastTool = m_tools.end();
585 while(toolsPassed && theTool!=lastTool )
586 {
587 toolsPassed = (*theTool)->passEvent(ctx.eventID());
588 m_toolInvoke[toolCtr]++;
589 {toolsPassed ? m_toolAccept[toolCtr]++ : m_toolReject[toolCtr]++;}
590 ++toolCtr;
591 ++theTool;
592 }
593 }
594
596 0 == (m_nev % m_eventPrintoutInterval.value()));
597 if (m_doEvtHeartbeat) {
598 if(!m_useTools)
599 ATH_MSG_INFO ( " ===>>> start processing event #{}, run #{} on slot {}, {} events processed so far <<<===",
600 evtNumber, m_currentRun, ctx.slot(), m_proc);
601 else
602 ATH_MSG_INFO ( " ===>>> start processing event #{}, run #{} on slot {}, {} events read and {} events processed so far <<<===",
603 evtNumber, m_currentRun, ctx.slot(), m_nev, m_proc);
604 }
605
606 // Reset the timeout singleton
608 if(toolsPassed) {
609
610 CHECK( m_conditionsCleaner->event (ctx, true) );
611
612 // Remember the last event context for after event processing finishes.
613 m_lastEventContext = ctx;
614
615 // Now add event to the scheduler
616 ATH_MSG_DEBUG ( "Adding event {}, slot {} to the scheduler",
617 ctx.evt(), ctx.slot());
618
619 m_incidentSvc->fireIncident(Incident(name(), IncidentType::BeginProcessing,
620 ctx));
621 StatusCode addEventStatus = m_schedulerSvc->pushNewEvent( new EventContext{ std::move(ctx) } );
622
623 // If this fails, we need to wait for something to complete
624 if (!addEventStatus.isSuccess()){
625 ATH_MSG_FATAL ( "An event processing slot should be now free in the scheduler, but it appears not to be the case." );
626 }
627
628 } // end of toolsPassed test
629
630 ++m_nev;
631
632 ++m_nevt;
633
634 // invalidate thread local context once outside of event execute loop
635 Gaudi::Hive::setCurrentContext( EventContext() );
636
637 return StatusCode::SUCCESS;
638
639}
640
641//=========================================================================
642// implementation of IEventProcessor::executeRun
643//=========================================================================
645{
646 StatusCode sc = nextEvent(maxevt);
647 if (sc.isSuccess()) {
648 m_incidentSvc->fireIncident(Incident(name(),"EndEvtLoop"));
649 }
650 return sc;
651}
652
653//-----------------------------------------------------------------------------
654// Implementation of IEventProcessor::stopRun()
655//-----------------------------------------------------------------------------
657 // Set the application return code
658 SmartIF<IProperty> appmgr(serviceLocator());
659 if(Gaudi::setAppReturnCode(appmgr, Gaudi::ReturnCode::ScheduledStop, true).isFailure()) {
660 ATH_MSG_ERROR ( "Could not set return code of the application ({})",
661 Gaudi::ReturnCode::ScheduledStop);
662 }
663 m_scheduledStop = true;
664 return StatusCode::SUCCESS;
665}
666
667
668//-----------------------------------------------------------------------------
669// Implementation of IService::stop()
670//-----------------------------------------------------------------------------
672{
673 // To enable conditions access during stop we set an invalid EventContext
674 // (no event/slot number) but with valid EventID (and extended EventContext).
675 m_lastEventContext.setValid(false);
676 Gaudi::Hive::setCurrentContext( m_lastEventContext );
677
678 StatusCode sc = MinimalEventLoopMgr::stop();
679
680 // If we exit the event loop early due to an error, some event stores
681 // may not have been cleared. This can lead to segfaults later,
682 // as DetectorStore will usually get finalized before HiveSvcMgr.
683 // So make sure that all stores have been cleared at this point.
684 size_t nslot = m_whiteboard->getNumberOfStores();
685 for (size_t islot = 0; islot < nslot; islot++) {
686 sc &= clearWBSlot (islot);
687 }
688
689 Gaudi::Hive::setCurrentContext( EventContext() );
690 return sc;
691}
692
693
695{
696 if(maxevt==0) return StatusCode::SUCCESS;
697
698 // Create a socket to communicate with the Pilot
699 m_socket =
700 std::unique_ptr<yampl::ISocket>{yampl::SocketFactory().createClientSocket(
701 yampl::Channel{m_eventRangeChannel.value(), yampl::LOCAL},
702 yampl::MOVE_DATA)};
703
704 // Reset the application return code.
706
707 int finishedEvts =0;
708 int createdEvts =0;
709 ATH_MSG_INFO ( "Starting loop on events" );
710
711 StatusCode sc(StatusCode::SUCCESS);
712
713 // Calculate runtime
714 auto start_time = tbb::tick_count::now();
715 auto secsFromStart = [&start_time]()->double{
716 return (tbb::tick_count::now()-start_time).seconds();
717 };
718
719 std::unique_ptr<RangeStruct> range;
720 while(!range) {
721 range = getNextRange(m_socket.get());
722 usleep(1000);
723 }
724
725 bool loop_ended = range->eventRangeID.empty();
726 if(!loop_ended) {
727 m_currentEvntNum = range->startEvent;
728 // Fire NextRange incident
729 m_incidentSvc->fireIncident(FileIncident(name(), "NextEventRange",range->eventRangeID));
730 }
731
732 bool no_more_events = false;
733
734 while(!loop_ended) {
735
736 ATH_MSG_DEBUG ( " -> createdEvts: {}", createdEvts );
737
738 if(!m_terminateLoop // No scheduled loop termination
739 && !no_more_events // We are not yet done getting events
740 && m_schedulerSvc->freeSlots()>0) { // There are still free slots in the scheduler
741
742 ATH_MSG_DEBUG ( "createdEvts: {}, freeslots: {}",
743 createdEvts, m_schedulerSvc->freeSlots());
744
745 auto ctx = createEventContext();
746
747 if ( !ctx.valid() ) {
748 sc = StatusCode::FAILURE;
749 }
750 else {
751 sc = executeEvent( std::move(ctx) );
752 }
753
754 if (sc.isFailure()) {
755 ATH_MSG_ERROR ( "Terminating event processing loop due to errors" );
756 loop_ended = true;
757 }
758 else {
759 ++createdEvts;
760 if(++m_currentEvntNum > range->lastEvent) {
761 // Fetch next event range
762 range.reset();
763 while(!range) {
764 range = getNextRange(m_socket.get());
765 usleep(1000);
766 }
767 if(range->eventRangeID.empty()) {
768 no_more_events = true;
769 }
770 else {
771 m_currentEvntNum = range->startEvent;
772 // Fire NextRange incident
773 m_incidentSvc->fireIncident(FileIncident(name(), "NextEventRange",range->eventRangeID));
774 }
775 }
776 }
777 }
778 else {
779 // all the events were created but not all finished or the slots were
780 // all busy: the scheduler should finish its job
781
782 ATH_MSG_DEBUG ( "Draining the scheduler" );
783
784 // Pull out of the scheduler the finished events
785 int ir = drainScheduler(finishedEvts,true);
786 if(ir < 0) {
787 // some sort of error draining scheduler;
788 loop_ended = true;
789 sc = StatusCode::FAILURE;
790 }
791 else if(ir == 0) {
792 // no more events in scheduler
793 if(no_more_events) {
794 // We are done
795 loop_ended = true;
796 sc = StatusCode::SUCCESS;
797 }
798 }
799 else {
800 // keep going!
801 }
802 }
803 } // end main loop on finished events
804
805 ATH_MSG_INFO ( "---> Loop Finished (seconds): {}", secsFromStart() );
806
807 return sc;
808}
809
810
811//=========================================================================
812// Seek to a given event.
813// The event selector must support the IEventSeek interface for this to work.
814//=========================================================================
816{
817 IEvtSelectorSeek* is = dynamic_cast<IEvtSelectorSeek*> (m_evtSelector);
818 if (is == 0) {
819 ATH_MSG_ERROR ( "Seek failed; unsupported by event selector" );
820 return StatusCode::FAILURE;
821 }
822 //cppcheck-suppress nullPointerRedundantCheck
823 if (!m_evtContext) {
824 if (m_evtSelector->createContext(m_evtContext).isFailure()) {
825 ATH_MSG_FATAL ( "Can not create the event selector Context." );
826 return StatusCode::FAILURE;
827 }
828 }
829 //m_evtContext cannot be null if createContext succeeded
830 //cppcheck-suppress nullPointerRedundantCheck
831 StatusCode sc = is->seek (*m_evtContext, evt);
832 if (sc.isSuccess()) {
833 m_nevt = evt;
834 }
835 else {
836 ATH_MSG_ERROR ( "Seek failed." );
837 }
838 return sc;
839}
840
841
842//=========================================================================
843// Return the current event count.
844//=========================================================================
846{
847 return m_nevt;
848}
849
850//=========================================================================
851// Return the collection size
852//=========================================================================
854{
855 IEvtSelectorSeek* cs = dynamic_cast<IEvtSelectorSeek*> (m_evtSelector);
856 if (cs == 0) {
857 ATH_MSG_ERROR ( "Collection size unsupported by event selector" );
858 return -1;
859 }
860 //cppcheck-suppress nullPointerRedundantCheck
861 if (!m_evtContext) {
862 if (m_evtSelector->createContext(m_evtContext).isFailure()) {
863 ATH_MSG_FATAL ( "Can not create the event selector Context." );
864 return -1;
865 }
866 }
867 //cppcheck-suppress nullPointerRedundantCheck
868 return cs->size (*m_evtContext);
869}
870
871//=========================================================================
872// Handle Incidents
873//=========================================================================
874void AthenaMtesEventLoopMgr::handle(const Incident& inc)
875{
876
877 if(inc.type()!="BeforeFork")
878 return;
879
880 if(!m_evtContext || !m_firstRun) {
881 ATH_MSG_WARNING ( "Skipping BeforeFork handler. Either no event selector is provided or begin run has already passed" );
882 }
883
884 // Initialize Algorithms and Output Streams
885 StatusCode sc = initializeAlgorithms();
886 if(sc.isFailure()) {
887 ATH_MSG_ERROR ( "Failed to initialize Algorithms" );
888 return;
889 }
890
891 // Construct EventInfo
892 const EventInfo* pEvent(0);
893 IOpaqueAddress* addr = 0;
894 sc = m_evtSelector->next(*m_evtContext);
895 if(!sc.isSuccess()) {
896 ATH_MSG_INFO ( "No more events in event selection " );
897 return;
898 }
899 sc = m_evtSelector->createAddress(*m_evtContext, addr);
900 if (sc.isFailure()) {
901 ATH_MSG_ERROR ( "Could not create an IOpaqueAddress" );
902 return;
903 }
904 if (0 != addr) {
905 //create its proxy
906 sc = m_eventStore->recordAddress(addr);
907 if(!sc.isSuccess()) {
908 ATH_MSG_ERROR ( "Error declaring Event object" );
909 return;
910 }
911 }
912
913 if(m_eventStore->loadEventProxies().isFailure()) {
914 ATH_MSG_WARNING ( "Error loading Event proxies" );
915 return;
916 }
917
918 // Retrieve the Event object
919 sc = m_eventStore->retrieve(pEvent);
920 if(!sc.isSuccess()) {
921 ATH_MSG_ERROR ( "Unable to retrieve Event root object" );
922 return;
923 }
924
925 m_firstRun=false;
926 m_currentRun = pEvent->event_ID()->run_number();
927
928 // Clear Store
929 const ClearStorePolicy::Type s_clearStore = clearStorePolicy( m_clearStorePolicy.value(), msgStream() );
930 if(s_clearStore==ClearStorePolicy::EndEvent) {
931 sc = m_eventStore->clearStore();
932 if(!sc.isSuccess()) {
933 ATH_MSG_ERROR ( "Clear of Event data store failed" );
934 }
935 }
936}
937
938//---------------------------------------------------------------------------
939
941StatusCode AthenaMtesEventLoopMgr::getEventRoot(IOpaqueAddress*& refpAddr) {
942 refpAddr = 0;
943 StatusCode sc = m_evtSelector->next(*m_evtContext);
944 if ( !sc.isSuccess() ) {
945 return sc;
946 }
947 // Create root address and assign address to data service
948 sc = m_evtSelector->createAddress(*m_evtContext,refpAddr);
949 if( !sc.isSuccess() ) {
950 sc = m_evtSelector->next(*m_evtContext);
951 if ( sc.isSuccess() ) {
952 sc = m_evtSelector->createAddress(*m_evtContext,refpAddr);
953 if ( !sc.isSuccess() ) {
954 ATH_MSG_WARNING ( "Error creating IOpaqueAddress." );
955 }
956 }
957 }
958 return sc;
959}
960
961//---------------------------------------------------------------------------
962
964
965 // return codes:
966 // -1 : error
967 // 0 : no more events in selection
968 // 1 : ok
969
970 StatusCode sc(StatusCode::SUCCESS);
971
972 //-----------------------------------------------------------------------
973 // we need an EventInfo Object to fire the incidents.
974 //-----------------------------------------------------------------------
975 std::unique_ptr<const EventInfo> pEvent;
976 if ( m_evtContext ) {
977 // Deal with the case when an EventSelector is provided
978
979 //
980 // FIXME: flow control if no more events in selector, etc.
981 //
982
983 IOpaqueAddress* addr = 0;
984
985 IEvtSelectorSeek* is = dynamic_cast<IEvtSelectorSeek*> (m_evtSelector);
986 if (is == 0) {
987 ATH_MSG_ERROR ( "Seek failed; unsupported by event selector" );
988 return 0;
989 }
990
992 if(sc.isFailure()) {
993 ATH_MSG_ERROR( "Seek failed to Evt={}", m_currentEvntNum-1);
994 return 0;
995 }
996
997 sc = m_evtSelector->next(*m_evtContext);
998
999 if ( !sc.isSuccess() ) {
1000 // This is the end of the loop. No more events in the selection
1001 ATH_MSG_INFO ( "No more events in event selection " );
1002 return 0;
1003 }
1004
1005 if (m_evtSelector->createAddress(*m_evtContext, addr).isFailure()) {
1006 ATH_MSG_ERROR ( "Could not create an IOpaqueAddress" );
1007 return -1;
1008 }
1009
1010
1011 // Most iterators provide the IOA of an event header (EventInfo, DataHeader)
1012 if (0 != addr) {
1013 //create its proxy
1014 sc = m_eventStore->recordAddress(addr);
1015 if( !sc.isSuccess() ) {
1017 ATH_MSG_WARNING ( "Error declaring Event object" );
1018 return 0;
1019 }
1020 } if ((sc=m_eventStore->loadEventProxies()).isFailure()) {
1021 ATH_MSG_ERROR ( "Error loading Event proxies" );
1022 return -1;
1023 }
1024 bool consume_modifier_stream = false;
1025 // Read the attribute list
1026 const AthenaAttributeList* pAttrList = m_eventStore->tryConstRetrieve<AthenaAttributeList>("Input");
1027 if ( pAttrList != nullptr && pAttrList->size() > 6 ) { // Try making EventID-only EventInfo object from in-file TAG
1028 try {
1029 unsigned int runNumber = (*pAttrList)["RunNumber"].data<unsigned int>();
1030 unsigned long long eventNumber = (*pAttrList)["EventNumber"].data<unsigned long long>();
1031 unsigned int eventTime = (*pAttrList)["EventTime"].data<unsigned int>();
1032 unsigned int eventTimeNS = (*pAttrList)["EventTimeNanoSec"].data<unsigned int>();
1033 unsigned int lumiBlock = (*pAttrList)["LumiBlockN"].data<unsigned int>();
1034 unsigned int bunchId = (*pAttrList)["BunchId"].data<unsigned int>();
1035
1036 consume_modifier_stream = true;
1037 // an option to override primary eventNumber with the secondary one in case of DoubleEventSelector
1039 unsigned long long eventNumberSecondary{};
1040 if ( !(pAttrList->exists("hasSecondaryInput") && (*pAttrList)["hasSecondaryInput"].data<bool>()) ) {
1041 ATH_MSG_FATAL ( "Secondary EventNumber requested, but secondary input does not exist!" );
1042 return -1;
1043 }
1044 if ( pAttrList->exists("EventNumber_secondary") ) {
1045 eventNumberSecondary = (*pAttrList)["EventNumber_secondary"].data<unsigned long long>();
1046 }
1047 else {
1048 // try legacy EventInfo if secondary input did not have attribute list
1049 // primary input should not have this EventInfo type
1050 const EventInfo* pEventSecondary = m_eventStore->tryConstRetrieve<EventInfo>();
1051 if (pEventSecondary) {
1052 eventNumberSecondary = pEventSecondary->event_ID()->event_number();
1053 }
1054 else {
1055 ATH_MSG_FATAL ( "Secondary EventNumber requested, but it does not exist!" );
1056 return -1;
1057 }
1058 }
1059 if (eventNumberSecondary != 0) {
1060 if (m_doEvtHeartbeat) {
1061 ATH_MSG_INFO ( " ===>>> using secondary event #{} instead of #{} <<<===",
1062 eventNumberSecondary, eventNumber);
1063 }
1064 eventNumber = eventNumberSecondary;
1065 }
1066 }
1067
1068 // never recorded in the eventStore
1069 pEvent = std::make_unique<EventInfo>(
1070 std::make_unique<EventID>(runNumber, eventNumber, eventTime,
1071 eventTimeNS, lumiBlock, bunchId),
1072 nullptr);
1073 } catch (...) {
1074 }
1075 } else if (m_requireInputAttributeList) {
1076 ATH_MSG_FATAL ( "Valid input attribute list required but not present!" );
1077 return -1;
1078 }
1079
1080 // Absolute input event index, matching the
1081 // is->seek(*m_evtContext,m_currentEvntNum-1) target above
1082 const long evtModIdx = m_currentEvntNum - 1;
1083
1084 const EventInfo* pEventObserver{pEvent.get()};
1085 if (!pEventObserver) {
1086 // Retrieve the Event object
1088 pEventObserver = m_eventStore->tryConstRetrieve<EventInfo>();
1089 if( !pEventObserver ) {
1090
1091 // Try to get the xAOD::EventInfo
1092 const xAOD::EventInfo* pXEvent{nullptr};
1093 sc = m_eventStore->retrieve(pXEvent);
1094 if( !sc.isSuccess() ) {
1095 ATH_MSG_ERROR ( "Unable to retrieve Event root object" );
1096 return -1;
1097 }
1098 consume_modifier_stream = true;
1099 // Build the old-style Event Info object for those clients that still need it
1100 pEvent = std::make_unique<EventInfo>(
1101 std::make_unique<EventID>(eventIDFromxAOD(pXEvent)),
1102 std::make_unique<EventType>(eventTypeFromxAOD(pXEvent)));
1103 pEventObserver = pEvent.get();
1104 sc = m_eventStore->record(std::move(pEvent), "");
1105 if( !sc.isSuccess() ) {
1106 ATH_MSG_ERROR ( "Error declaring event data object" );
1107 return -1;
1108 }
1109 } else {
1110 consume_modifier_stream = false;
1111 }
1112 }
1113
1114 // the pEvent was moved to the eventStore, the object is still 'alive'.
1115 // so the raw pEventObserver pointer is also still valid
1116 // cppcheck-suppress invalidLifetime
1117 modifyEventContext(ctx, *(pEventObserver->event_ID()),
1118 consume_modifier_stream, evtModIdx);
1119
1120 } else {
1121
1122 // with no iterator it's up to us to create an EventInfo
1123 // first event # == 1
1124 unsigned int runNmb{1}, evtNmb{m_nevt + 1};
1125
1126 // increment the run/lumiBlock number if desired
1127 if (m_flmbi != 0) {
1128 runNmb = m_nevt / m_flmbi + 1;
1129 evtNmb = m_nevt % m_flmbi + 1;
1130 }
1131 auto eid = std::make_unique<EventID> (runNmb,evtNmb, m_timeStamp);
1132 // Change lumiBlock# to match runNumber
1133 eid->set_lumi_block( runNmb );
1134
1136
1137 pEvent = std::make_unique<EventInfo>(std::move(eid),
1138 std::make_unique<EventType>());
1139
1140 modifyEventContext(ctx,*(pEvent->event_ID()), true, ctx.evt());
1141
1142 ATH_MSG_DEBUG ( "selecting store: {}", ctx.slot() );
1143
1144 m_whiteboard->selectStore( ctx.slot() ).ignore();
1145
1146 // EventInfo not working with format
1147 ATH_MSG_DEBUG ( "recording EventInfo " << *pEvent->event_ID() << " in "
1148 << m_eventStore->name() );
1149 sc = m_eventStore->record(std::move(pEvent), "McEventInfo");
1150 if( !sc.isSuccess() ) {
1151 ATH_MSG_ERROR ( "Error declaring event data object" );
1152 return -1;
1153 }
1154 }
1155 return 1;
1156}
1157
1158//---------------------------------------------------------------------------
1160 const EventID& eID,
1161 bool consume_modifier_stream,
1162 long evtModIdx) {
1163
1164 if (m_evtIdModSvc.isSet()) {
1165 EventID new_eID(eID);
1166 // use absolute input index, so modification tracks input position
1167 // not the per-worker counter (they differ under AthenaMP)
1168 m_evtIdModSvc->modify_evtid(new_eID, evtModIdx, consume_modifier_stream);
1169 if (msgLevel(MSG::DEBUG)) {
1170 unsigned int oldrunnr = eID.run_number();
1171 unsigned int oldLB = eID.lumi_block();
1172 unsigned int oldTS = eID.time_stamp();
1173 unsigned int oldTSno = eID.time_stamp_ns_offset();
1174 ATH_MSG_DEBUG ( "modifyEventContext: use evtIdModSvc runnr={} -> {}",
1175 oldrunnr, new_eID.run_number());
1176 ATH_MSG_DEBUG ( "modifyEventContext: use evtIdModSvc LB={} -> {}",
1177 oldLB, new_eID.lumi_block());
1178 ATH_MSG_DEBUG ( "modifyEventContext: use evtIdModSvc TimeStamp={} -> {}",
1179 oldTS, new_eID.time_stamp());
1180 ATH_MSG_DEBUG ( "modifyEventContext: use evtIdModSvc TimeStamp ns Offset={} -> {}",
1181 oldTSno, new_eID.time_stamp_ns_offset());
1182 }
1183 ctx.setEventID(new_eID);
1185 ctx.eventID().run_number());
1186 return;
1187 }
1188
1189 ctx.setEventID(eID);
1190}
1191
1192//---------------------------------------------------------------------------
1194
1195 EventContext ctx{ m_nevt, m_whiteboard->allocateStore( m_nevt ) };
1196
1197 StatusCode sc = m_whiteboard->selectStore( ctx.slot() );
1198 if (sc.isFailure()) {
1199 ATH_MSG_FATAL ( "Slot {} could not be selected for the WhiteBoard",
1200 ctx.slot());
1201 return EventContext{}; // invalid EventContext
1202 } else {
1204
1205 ATH_MSG_DEBUG ( "created EventContext, num: {} in slot: {}",
1206 ctx.evt(), ctx.slot());
1207 }
1208
1209 return ctx;
1210}
1211
1213{
1214 Gaudi::setAppReturnCode(m_appMgrProperty, Gaudi::ReturnCode::Success, true).ignore();
1215}
1216
1220
1224//---------------------------------------------------------------------------
1225
1226int
1227AthenaMtesEventLoopMgr::drainScheduler(int& finishedEvts,bool report){
1228
1229 StatusCode sc(StatusCode::SUCCESS);
1230
1231 // maybe we can do better
1232 std::vector<std::unique_ptr<EventContext>> finishedEvtContexts;
1233
1234 EventContext* finishedEvtContext{nullptr};
1235
1236 // Here we wait not to loose cpu resources
1237 ATH_MSG_DEBUG ( "drainScheduler: [{}] Waiting for a context", finishedEvts);
1238 sc = m_schedulerSvc->popFinishedEvent(finishedEvtContext);
1239
1240 // We got past it: cache the pointer
1241 if (sc.isSuccess()){
1242 // EventContext not working with std::format
1243 ATH_MSG_DEBUG ( "drainScheduler: scheduler not empty: Context "
1244 << finishedEvtContext );
1245 finishedEvtContexts.emplace_back(finishedEvtContext);
1246 } else{
1247 // no more events left in scheduler to be drained
1248 ATH_MSG_DEBUG ( "drainScheduler: scheduler empty" );
1249 return 0;
1250 }
1251
1252 // Let's see if we can pop other event contexts
1253 while (m_schedulerSvc->tryPopFinishedEvent(finishedEvtContext).isSuccess()){
1254 finishedEvtContexts.emplace_back(finishedEvtContext);
1255 }
1256
1257 // Now we flush them
1258 bool fail(false);
1259 for (auto& thisFinishedEvtContext : finishedEvtContexts){
1260 if (!thisFinishedEvtContext) {
1261 ATH_MSG_FATAL ( "Detected nullptr ctxt while clearing WB!");
1262 fail = true;
1263 continue;
1264 }
1265
1266 if (m_aess->eventStatus(*thisFinishedEvtContext) != EventStatus::Success) {
1267 ATH_MSG_FATAL ( "Failed event detected on " << thisFinishedEvtContext
1268 << " w/ fail mode: "
1269 << m_aess->eventStatus(*thisFinishedEvtContext) );
1270 fail = true;
1271 continue;
1272 }
1273
1274 EventID::number_type n_run(0);
1275 EventID::event_number_t n_evt(0);
1276
1277 if (m_whiteboard->selectStore(thisFinishedEvtContext->slot()).isSuccess()) {
1278 n_run = thisFinishedEvtContext->eventID().run_number();
1279 n_evt = thisFinishedEvtContext->eventID().event_number();
1280 } else {
1281 ATH_MSG_ERROR ( "DrainSched: unable to select store {}",
1282 thisFinishedEvtContext->slot() );
1283 fail = true;
1284 continue;
1285 }
1286
1287 // m_incidentSvc->fireIncident(Incident(name(), IncidentType::EndEvent,
1288 // *thisFinishedEvtContext ));
1289
1290 // Some code still needs global context in addition to that passed in the incident
1291 Gaudi::Hive::setCurrentContext( *thisFinishedEvtContext );
1292 ATH_MSG_INFO( "Firing EndProcessing" );
1293 m_incidentSvc->fireIncident(Incident(name(), IncidentType::EndProcessing, *thisFinishedEvtContext ));
1294
1295 if(report) {
1296 // If we completed an event range, then report it to the pilot
1297 OutputStreamSequencerSvc::RangeReport_ptr rangeReport = m_outSeqSvc->getRangeReport();
1298 if(rangeReport) {
1299 std::string outputFileReport = rangeReport->second + std::string(",ID:")
1300 + rangeReport->first + std::string(",CPU:N/A,WALL:N/A");
1301 if( not m_inTestMode ) {
1302 // In standalone test mode there is no pilot to talk to
1303 void* message2pilot = CxxUtils::xmalloc(outputFileReport.size());
1304 memcpy(message2pilot,outputFileReport.data(),outputFileReport.size());
1305 m_socket->send(message2pilot,outputFileReport.size());
1306 }
1307 ATH_MSG_INFO( "Reported the output {}", outputFileReport );
1308 }
1309 }
1310
1311 ATH_MSG_DEBUG( "Clearing slot {} (event {}) of the whiteboard",
1312 thisFinishedEvtContext->slot(),
1313 thisFinishedEvtContext->evt() );
1314
1315 StatusCode sc = clearWBSlot(thisFinishedEvtContext->slot());
1316 if (!sc.isSuccess()) {
1317 ATH_MSG_ERROR ( "Whiteboard slot {} could not be properly cleared",
1318 thisFinishedEvtContext->slot() );
1319 fail = true;
1320 continue;
1321 }
1322
1323 finishedEvts++;
1324
1325 writeHistograms().ignore();
1326 ++m_proc;
1327
1328 if (m_doEvtHeartbeat) {
1329 if(!m_useTools)
1330 ATH_MSG_INFO ( " ===>>> done processing event #{}, run #{} on slot {}, {} events processed so far <<<===",
1331 n_evt, n_run, thisFinishedEvtContext->slot(), m_proc);
1332 else
1333 ATH_MSG_INFO ( " ===>>> done processing event #{}, run #{} on slot {}, {} events read and {} events processed so far <<<===",
1334 n_evt, n_run, thisFinishedEvtContext->slot(), m_nev, m_proc);
1335 std::ofstream outfile( "eventLoopHeartBeat.txt");
1336 if ( !outfile ) {
1337 ATH_MSG_ERROR ( " unable to open: eventLoopHeartBeat.txt" );
1338 fail = true;
1339 continue;
1340 } else {
1341 std::println (outfile, " done processing event #{}, run #{} {} events read so far <<<===",
1342 n_evt, n_run, m_nev);
1343 outfile.close();
1344 }
1345 }
1346
1347 ATH_MSG_DEBUG ( "drainScheduler thisFinishedEvtContext: " << thisFinishedEvtContext );
1348 }
1349
1350 return ( fail ? -1 : 1 );
1351
1352}
1353
1354//---------------------------------------------------------------------------
1355
1357 StatusCode sc = m_whiteboard->clearStore(evtSlot);
1358 if( !sc.isSuccess() ) {
1359 ATH_MSG_WARNING ( "Clear of Event data store failed" );
1360 }
1361 return m_whiteboard->freeStore(evtSlot);
1362}
1363//---------------------------------------------------------------------------
1364
1365std::unique_ptr<AthenaMtesEventLoopMgr::RangeStruct> AthenaMtesEventLoopMgr::getNextRange(yampl::ISocket* socket)
1366{
1367 static const std::string strReady("Ready for events");
1368 static const std::string strStopProcessing("No more events");
1369
1370 std::string range;
1371 if( m_inTestMode ) {
1372 static std::atomic<size_t> line_n = 0;
1373 ATH_MSG_INFO( "in TEST MODE, Range #{}", line_n+1 );
1374 range = (line_n < m_testPilotMessages.value().size()) ? m_testPilotMessages.value()[line_n++] : strStopProcessing;
1375 } else {
1376 // Signal the Pilot that we are ready for event processing
1377 void* ready_message = malloc(strReady.size());
1378 if (!ready_message) std::abort();
1379 memcpy(ready_message,strReady.data(),strReady.size());
1380 socket->send(ready_message,strReady.size());
1381 void* eventRangeMessage;
1382 std::string strPeerId;
1383 ssize_t eventRangeSize = socket->recv(eventRangeMessage,strPeerId);
1384 range = std::string((const char*)eventRangeMessage,eventRangeSize);
1385 leftString(range, '\n');
1386 }
1387
1388 std::unique_ptr<RangeStruct> result = std::make_unique<RangeStruct>();
1389 if(range.compare(strStopProcessing)==0) {
1390 ATH_MSG_INFO( "No more events from the server" );
1391 return result;
1392 }
1393 ATH_MSG_INFO( "Got Event Range from the pilot: {}", range);
1394
1395 // _____________________ Decode range string _____________________________
1396 // Expected the following format: [{KEY:VALUE[,KEY:VALUE]}]
1397 // First get rid of the leading '[{' and the trailing '}]'
1398 if(range.starts_with( "[{")) range=range.substr(2);
1399 if(range.ends_with( "}]")){
1400 const int truncate = range.size()-2;
1401 leftString(range, truncate);
1402 }
1403
1404 std::map<std::string,std::string, std::less<>> eventRangeMap;
1405 size_t startpos(0);
1406 size_t endpos = range.find(',');
1407 while(endpos!=std::string::npos) {
1408 // Get the Key-Value pair
1409 std::string keyValue(range.substr(startpos,endpos-startpos));
1410 size_t colonPos = keyValue.find(':');
1411 std::string strKey = keyValue.substr(0,colonPos);
1412 std::string strVal = keyValue.substr(colonPos+1);
1413 trimRangeStrings(strKey);
1414 trimRangeStrings(strVal);
1415 eventRangeMap[strKey]=std::move(strVal);
1416
1417 // Next iteration
1418 startpos = endpos+1;
1419 endpos = range.find(',',startpos);
1420 }
1421
1422 // Get the final Key-Value pair
1423 std::string keyValue(range.substr(startpos));
1424 size_t colonPos = keyValue.find(':');
1425 std::string strKey = keyValue.substr(0,colonPos);
1426 std::string strVal = keyValue.substr(colonPos+1);
1427 trimRangeStrings(strKey);
1428 trimRangeStrings(strVal);
1429 eventRangeMap[strKey]=std::move(strVal);
1430
1431 // _____________________ Consistency check for range string _____________________________
1432 // Three checks are performed:
1433 // 1. The existence of all required fields
1434 // 2. The consistency of field values
1435 // 3. Protection against having event ranges from different input files
1436 // NB. The last check is hopefully a temporary limitation of MTES
1437 std::string errorStr{""};
1438
1439 if(eventRangeMap.find("eventRangeID")==eventRangeMap.end()
1440 || eventRangeMap.find("startEvent")==eventRangeMap.end()
1441 || eventRangeMap.find("lastEvent")==eventRangeMap.end()
1442 || eventRangeMap.find("PFN")==eventRangeMap.end()) {
1443 // Wrong format
1444 errorStr = "ERR_ATHENAMP_PARSE \"" + range + "\": Wrong format";
1445 }
1446
1447 if(errorStr.empty()) {
1448 result->startEvent = std::atoi(eventRangeMap["startEvent"].c_str());
1449 result->lastEvent = std::atoi(eventRangeMap["lastEvent"].c_str());
1450
1451 if(eventRangeMap["eventRangeID"].empty()
1452 || eventRangeMap["PFN"].empty()
1453 || result->lastEvent < result->startEvent) {
1454 // Wrong values of range fields
1455 errorStr = "ERR_ATHENAMP_PARSE \"" + range + "\": Wrong values of range fields";
1456 }
1457 else {
1458 // Update m_pfn if necessary
1459 if(m_pfn != eventRangeMap["PFN"]) {
1460 IProperty* propertyServer = dynamic_cast<IProperty*>(m_evtSelector);
1461 if(!propertyServer) {
1462 errorStr = "ERR_ATHENAMP_PARSE \"" + range + "\": Unable to dyn-cast the event selector to IProperty";
1463 }
1464 else {
1465 std::string strInpuCol("InputCollections");
1466 std::vector<std::string> vectInpCol{eventRangeMap["PFN"],};
1467 StringArrayProperty inputFileList(std::move(strInpuCol), vectInpCol);
1468 if(propertyServer->setProperty(inputFileList).isFailure()) {
1469 errorStr = "ERR_ATHENAMP_PARSE \"" + range + "\": Unable to set input file name property to the Event Selector";
1470 }
1471 else {
1472 m_pfn = eventRangeMap["PFN"];
1473 }
1474 }
1475 }
1476 }
1477 }
1478
1479 if(errorStr.empty()) {
1480 // Event range parsing was successful
1481 ATH_MSG_DEBUG( "*** Decoded Event Range ***" );
1482 for (const auto& fieldvalue : eventRangeMap) {
1483 ATH_MSG_DEBUG( "{}:{}", fieldvalue.first, fieldvalue.second);
1484 }
1485
1486 result->eventRangeID = eventRangeMap["eventRangeID"];
1487 result->pfn = eventRangeMap["PFN"];
1488 }
1489 else {
1490 // We got here because there was an error
1491 // Report the error to the pilot and reset the result, so that the next range can be tried
1492 ATH_MSG_WARNING( errorStr );
1493 ATH_MSG_INFO( "Ignoring this event range" );
1494 if( not m_inTestMode ) {
1495 void* errorMessage = CxxUtils::xmalloc(errorStr.size());
1496 memcpy(errorMessage,errorStr.data(),errorStr.size());
1497 socket->send(errorMessage,errorStr.size());
1498 }
1499 result.reset();
1500 }
1501
1502 return result;
1503}
1504
1506{
1507 size_t i(0);
1508 // get rid of leading spaces
1509 while(i<str.size() && str[i]==' ') i++;
1510 if(i) str = str.substr(i);
1511
1512 if(str.empty()) return; // Corner case: string consists only of spaces
1513
1514 // get rid of trailing spaces
1515 i=str.size()-1;
1516 while(str[i]==' ') i--;
1517 if(i) str.resize(i+1);
1518
1519 // the string might be enclosed by either
1520 // "u\'" and "\'"
1521 // or
1522 // "\"" and "\""
1523 // Get rid of them!
1524 if(str.starts_with( "u\'")) {
1525 str = str.substr(2);
1526 if(str.rfind('\'')==str.size()-1) {
1527 str.pop_back();
1528 }
1529 }
1530 else if(str.starts_with("\"")) {
1531 str = str.substr(1);
1532 if(str.rfind('\"')==str.size()-1) {
1533 str.pop_back();
1534 }
1535 }
1536}
#define ATH_CHECK
Evaluate an expression and check for errors.
#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,...)
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.
static Double_t sc
void setProperty(columnar::PythonToolHandle &self, const std::string &key, nb::object value)
This file contains the class definition for the OutputStreamSequencerSvc class.
An AttributeList represents a logical row of attributes in a metadata table.
static const Attributes_t empty
An AttributeList represents a logical row of attributes in a metadata table.
StatusCode getEventRoot(IOpaqueAddress *&refpAddr)
Create event address using event selector.
bool m_requireInputAttributeList
require input attribute list
virtual StatusCode finalize() override
implementation of IAppMgrUI::finalize
virtual EventContext createEventContext() override
implementation of IEventProcessor::createEventContext()
virtual void resetAppReturnCode() override
Reset the application return code.
virtual StatusCode executeEvent(EventContext &&ctx) override
implementation of IEventProcessor::executeEvent(void* par)
tool_store::const_iterator tool_iterator
virtual int curEvent() const override
Return the current event count.
ServiceHandle< OutputStreamSequencerSvc > m_outSeqSvc
SmartIF< IScheduler > m_schedulerSvc
A shortcut for the scheduler.
void setClearStorePolicy(Gaudi::Details::PropertyBase &clearStorePolicy)
property update handler:set the clear-store policy value and check its value.
virtual StatusCode executeAlgorithms()
Run the algorithms for the current event.
std::unique_ptr< yampl::ISocket > m_socket
ServiceHandle< Athena::IConditionsCleanerSvc > m_conditionsCleaner
std::unique_ptr< RangeStruct > getNextRange(yampl::ISocket *socket)
virtual bool terminateLoop() override
tool_stats m_toolReject
tool returns StatusCode::FAILURE counter
UnsignedIntegerProperty m_eventPrintoutInterval
tool_stats m_toolAccept
tool returns StatusCode::SUCCESS counter
virtual StatusCode executeRun(int maxevt) override
implementation of IEventProcessor::executeRun(int maxevt)
number_type m_currentRun
current run number
AthenaMtesEventLoopMgr()=delete
tool_store m_tools
internal tool store
virtual const std::string & name() const override
unsigned int m_nev
events processed
virtual StatusCode initialize() override
implementation of IAppMgrUI::initalize
SmartIF< IAlgResourcePool > m_algResourcePool
Reference to the Algorithm resource pool.
IEvtIdModifierSvc_t m_evtIdModSvc
virtual StatusCode writeHistograms(bool force=false)
Dump out histograms as needed.
SmartIF< IHiveWhiteBoard > m_whiteboard
Reference to the Whiteboard interface.
virtual ~AthenaMtesEventLoopMgr()
Standard Destructor.
StatusCode initializeAlgorithms()
Initialize all algorithms and output streams.
SmartIF< IAlgExecStateSvc > m_aess
Reference to the Algorithm Execution State Svc.
tool_stats m_toolInvoke
tool called counter
virtual int drainScheduler(int &finishedEvents, bool report) override
Drain the scheduler from all actions that may be queued.
bool m_useSecondaryEventNumber
read event number from secondary input
virtual StatusCode nextEvent(int maxevt) override
implementation of IAppMgrUI::nextEvent. maxevt==0 returns immediately
EvtContext * m_evtContext
Gaudi event selector Context (may be used as a cursor by the evt selector).
StatusCode clearWBSlot(int evtSlot)
Clear a slot in the WB.
std::string m_whiteboardName
Name of the Whiteboard to be used.
int declareEventRootAddress(EventContext &)
Declare the root address of the event.
bool m_scheduledStop
Scheduled stop of event processing.
virtual StatusCode seek(int evt) override
Seek to a given event.
virtual StatusCode stop() override
implementation of IService::stop
std::string m_schedulerName
Name of the scheduler to be used.
StringArrayProperty m_testPilotMessages
IDataManagerSvc_t m_histoDataMgrSvc
Reference to the Histogram Data Service.
StoreGateSvc_t m_eventStore
Reference to StoreGateSvc;.
virtual int size() override
Return the size of the collection.
Gaudi::Property< std::string > m_eventRangeChannel
void modifyEventContext(EventContext &ctx, const EventID &eID, bool consume_modifier_stream, long evtModIdx)
SmartIF< IProperty > m_appMgrProperty
Property interface of ApplicationMgr.
virtual void setCurrentEventNum(int num) override
ServiceHandle< IConversionSvc > IConversionSvc_t
virtual StatusCode stopRun() override
implementation of IEventProcessor::stopRun()
void setupPreSelectTools(Gaudi::Details::PropertyBase &)
property update handler:sets up the Pre-selection tools
IIncidentSvc_t m_incidentSvc
Reference to the incident service.
void trimRangeStrings(std::string &str)
UnsignedIntegerProperty m_writeInterval
virtual void handle(const Incident &inc) override
IIncidentListenet interfaces.
IEvtSelector * m_evtSelector
Reference to the Event Selector.
void resetTimeout(Timeout &instance)
Reset timeout.
Definition Timeout.h:83
static Timeout & instance()
Get reference to Timeout singleton.
Definition Timeout.h:64
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...
Definition EventID.h:34
EventIDBase::number_type number_type
Definition EventID.h:36
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.
std::unique_ptr< RangeReport_t > RangeReport_ptr
int ir
counter of the current depth
Definition fastadd.cxx:49
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.
void * xmalloc(size_t size)
Trapping version of malloc.
Definition xmalloc.cxx:31
event_number_t eventIndex
EventInfo_v1 EventInfo
Definition of the latest event info version.
Trapping version of malloc.