26 #include <condition_variable> 31 #include "boost/algorithm/string.hpp" 32 #include "boost/optional.hpp" 33 #include "boost/thread.hpp" 34 #include "boost/tokenizer.hpp" 35 #include "tbb/task_scheduler_init.h" 43 struct DataObjIDDotRepr {
46 return os <<
'\"' << repr.parent.fullKey() <<
'\"';
50 struct DataObjIDSorter {
75 : m_algorithms( algorithms )
76 , m_evtCtx(
std::move( ctx ) )
78 , m_serviceLocator( svcLocator )
79 , m_parent( parent ) {}
83 return MsgStream( messageSvc,
"HLTExecutionTask" );
87 bool eventfailed =
false;
95 ialg->whiteboard()->selectStore( m_evtCtx->
valid() ? m_evtCtx->
slot() : 0 ).ignore();
101 sc = ialg->sysExecute( *m_evtCtx );
108 log() <<
MSG::FATAL <<
".executeEvent(): Exception with tag=" << Exception.
tag() <<
" thrown by " 112 log() <<
MSG::FATAL <<
".executeEvent(): Standard std::exception thrown by " << ialg->name() <<
endmsg 116 log() <<
MSG::FATAL <<
".executeEvent(): UNKNOWN Exception thrown by " << ialg->name() <<
endmsg;
127 if ( !ialg->execState( *m_evtCtx ).filterPassed() )
break;
140 error() <<
"Failed to initialize Service Base class." <<
endmsg;
144 m_evtDataMgrSvc = serviceLocator()->service<
IDataManagerSvc>(
"EventDataSvc" );
145 if ( !m_evtDataMgrSvc ) {
146 fatal() <<
"Error retrieving EventDataSvc interface IDataManagerSvc." <<
endmsg;
149 m_whiteboard = serviceLocator()->service<
IHiveWhiteBoard>(
"EventDataSvc" );
150 if ( !m_whiteboard ) {
151 fatal() <<
"Error retrieving EventDataSvc interface IHiveWhiteBoard." <<
endmsg;
156 if ( !appMgrProperty ) {
157 fatal() <<
"IProperty interface not found in ApplicationMgr." <<
endmsg;
163 if ( m_evtsel !=
"NONE" || m_evtsel.length() == 0 ) {
164 m_evtSelector = serviceLocator()->service<
IEvtSelector>(
"EventSelector" );
166 m_evtSelector =
nullptr;
167 warning() <<
"Unable to locate service \"EventSelector\" " <<
endmsg;
168 warning() <<
"No events will be processed from external input." <<
endmsg;
172 m_histoDataMgrSvc = serviceLocator()->service<
IDataManagerSvc>(
"HistogramDataSvc" );
173 if ( !m_histoDataMgrSvc ) {
174 fatal() <<
"Error retrieving HistogramDataSvc." <<
endmsg;
178 m_histoPersSvc = serviceLocator()->service<
IConversionSvc>(
"HistogramPersistencySvc" );
179 if ( !m_histoPersSvc ) {
180 warning() <<
"Histograms cannot not be saved - though required." <<
endmsg;
184 m_algExecStateSvc = serviceLocator()->service<
IAlgExecStateSvc>(
"AlgExecStateSvc" );
185 if ( !m_algExecStateSvc ) {
186 fatal() <<
"Error retrieving AlgExecStateSvc" <<
endmsg;
190 if ( !m_topAlgs.empty() ) {
191 auto databroker = serviceLocator()->service<
IDataBroker>(
"HiveDataBrokerSvc" );
195 for (
const auto& alg : m_topAlgs.value() ) {
204 if ( !algResourcePool ) {
205 fatal() <<
"Error retrieving AlgoResourcePool" <<
endmsg;
211 fatal() <<
"Could not convert IAlgorithm into Algorithm: this will result in a crash." <<
endmsg;
213 m_algos.push_back( algoPtr );
221 boost::optional<std::ofstream> dot{boost::in_place_init_if, !m_dotfile.
empty(), m_dotfile.value()};
224 *dot <<
"digraph G {\n";
225 for (
auto* a : m_algos ) {
226 bool is_consumer = a->outputDataObjs().empty();
227 *dot <<
'\"' << a->name() <<
"\" [shape=box" << ( is_consumer ?
",style=filled" :
"" ) <<
"];\n";
234 for (
auto id : algoPtr->outputDataObjs() ) {
235 auto r = globalOutp.
insert(
id );
236 producers[id] = algoPtr;
238 warning() <<
"multiple algorithms declare " <<
id 239 <<
" as output! could be a single instance in multiple paths " 240 "though, or control flow may guarantee only one runs...!" 248 algosDependencies.
reserve( m_algos.size() );
250 info() <<
"Data Dependencies for Algorithms:";
253 info() <<
"\n " << algoPtr->name();
256 if ( !algoPtr->inputDataObjs().empty() || !algoPtr->outputDataObjs().empty() ) {
257 for (
const DataObjID* idp : sortedDataObjIDColl( algoPtr->inputDataObjs() ) ) {
259 info() <<
"\n o INPUT " << id;
260 if (
id.key().find(
":" ) != std::string::npos ) {
261 info() <<
" contains alternatives which require resolution...\n";
262 auto tokens = boost::tokenizer<boost::char_separator<char>>{
id.
key(), boost::char_separator<char>{
":"}};
266 if ( itok != tokens.end() ) {
267 info() <<
"found matching output for " << *itok <<
" -- updating scheduler info\n";
268 id.updateKey( *itok );
270 error() <<
"failed to find alternate in global output list" 271 <<
" for id: " <<
id <<
" in Alg " << algoPtr->name() <<
endmsg;
274 algoDependencies.
insert(
id );
275 if ( dot ) *dot << DataObjIDDotRepr{
id} <<
" -> \"" << algoPtr->name() <<
"\";\n";
278 for (
const DataObjID*
id : sortedDataObjIDColl( algoPtr->outputDataObjs() ) ) {
279 info() <<
"\n o OUTPUT " << *id;
280 if ( id->key().find(
":" ) != std::string::npos ) {
281 error() <<
" in Alg " << algoPtr->name() <<
" alternatives are NOT allowed for outputs! id: " << *
id 284 if ( dot ) *dot <<
'\"' << algoPtr->name() <<
"\" -> " << DataObjIDDotRepr{*
id} <<
";\n";
290 algo2Deps[algoPtr] = &algosDependencies.
back();
293 for (
const auto& t : globalOutp ) {
294 if ( globalInp.
find( t ) == globalInp.
end() ) *dot << DataObjIDDotRepr{t} <<
" [style=filled];\n";
302 for (
auto o : globalInp ) {
303 if ( globalOutp.
find( o ) == globalOutp.
end() ) unmetDep.
insert( o );
305 if ( unmetDep.
size() > 0 ) {
307 for (
const DataObjID* o : sortedDataObjIDColl( unmetDep ) ) {
308 ost <<
"\n o " << *o <<
" required by Algorithm: ";
309 for (
const auto& i : algo2Deps ) {
310 if ( i.second->find( *o ) != i.second->end() ) { ost <<
"\n * " << i.first->name(); }
313 fatal() <<
"The following unmet INPUT dependencies were found:" << ost.
str() <<
endmsg;
316 info() <<
"No unmet INPUT data dependencies were found" <<
endmsg;
320 auto start = m_algos.begin();
321 auto end = m_algos.end();
326 while ( current !=
end ) {
337 info() <<
"Concurrency level information:" <<
endmsg;
338 info() <<
" o Number of events slots: " << m_whiteboard->getNumberOfStores() <<
endmsg;
339 info() <<
" o TBB thread pool size: " << m_threadPoolSize <<
endmsg;
342 debug() <<
"Order of algo execution :" <<
endmsg;
351 if ( m_histoPersSvc ) {
353 sc = m_histoDataMgrSvc->traverseTree( &agent );
359 StatusCode iret = m_histoPersSvc->createRep( i, pAddr );
360 if ( iret.
isSuccess() ) i->registry()->setAddress( pAddr );
368 if ( sc.isSuccess() ) {
369 info() <<
"Histograms converted successfully according to request." <<
endmsg;
371 error() <<
"Error while saving Histograms." <<
endmsg;
374 error() <<
"Error while traversing Histogram data store" <<
endmsg;
384 int& createdEvts = *
reinterpret_cast<int*
>( createdEvts_IntPtr );
386 auto evtContext = std::make_unique<EventContext>();
387 evtContext->set( createdEvts, m_whiteboard->allocateStore( createdEvts ) );
388 m_algExecStateSvc->reset( *evtContext );
390 StatusCode sc = m_whiteboard->selectStore( evtContext->slot() );
392 fatal() <<
"Slot " << evtContext->slot() <<
" could not be selected for the WhiteBoard\n" 393 <<
"Impossible to create event context" <<
endmsg;
397 StatusCode declEvtRootSc = declareEventRootAddress();
405 debug() <<
"Event " << evtContext->evt() <<
" submitting in slot " << evtContext->slot() <<
endmsg;
408 tbb::task* task =
new ( tbb::task::allocate_root() )
410 tbb::task::enqueue( *task );
413 debug() <<
"All algorithms were submitted on event " << evtContext->evt() <<
" in slot " << evtContext->slot()
422 auto appmgr = serviceLocator()->as<
IProperty>();
434 auto appmgr = serviceLocator()->as<
IProperty>();
440 StatusCode sc = m_evtSelector->createContext( m_evtSelContext );
442 fatal() <<
"Can not create the event selector Context." <<
endmsg;
447 tbb::task_scheduler_init tbbSchedInit( m_threadPoolSize.value() + 1 );
451 bool newEvtAllowed =
false;
453 info() <<
"Starting loop on events" <<
endmsg;
454 auto start_time = Clock::now();
455 while ( maxevt < 0 || m_finishedEvt < (
unsigned int)maxevt ) {
457 if ( !( ( newEvtAllowed || createdEvts == 0 ) &&
461 ( createdEvts < maxevt || maxevt < 0 ) &&
463 m_whiteboard->freeSlots() > 0 ) ) {
466 using namespace std::chrono_literals;
467 m_createEventCond.wait_for( lock, 1
ms, [
this, newEvtAllowed, createdEvts, maxevt] {
468 return ( newEvtAllowed ||
469 createdEvts == 0 ) &&
473 ( createdEvts < maxevt || maxevt < 0 ) &&
475 this->m_whiteboard->freeSlots() > 0;
479 if ( 1 == createdEvts )
480 start_time = Clock::now();
484 sc = executeEvent( &createdEvts );
486 newEvtAllowed =
true;
488 auto end_time = Clock::now();
490 delete m_evtSelContext;
491 m_evtSelContext =
nullptr;
493 constexpr
double oneOver1024 = 1. / 1024.;
494 info() <<
"---> Loop Finished (skipping 1st evt) - " 502 StatusCode sc = m_evtSelector->next( *m_evtSelContext );
505 sc = m_evtSelector->createAddress( *m_evtSelContext, pAddr );
507 sc = m_evtSelector->next( *m_evtSelContext );
509 sc = m_evtSelector->createAddress( *m_evtSelContext, pAddr );
510 if ( !sc.
isSuccess() ) warning() <<
"Error creating IOpaqueAddress." <<
endmsg;
515 info() <<
"No more events in event selection " <<
endmsg;
518 sc = m_evtDataMgrSvc->setRoot(
"/Event", pAddr );
519 if ( !sc.
isSuccess() ) { warning() <<
"Error declaring event root address." <<
endmsg; }
529 fatal() <<
"*** Event " << eventContext->
evt() <<
" on slot " << eventContext->
slot() <<
" failed! ***" <<
endmsg;
531 m_algExecStateSvc->dump( ost, *eventContext );
532 info() <<
"Dumping Alg Exec State for slot " << eventContext->
slot() <<
":\n" << ost.
str() <<
endmsg;
539 eventFailed( eventContext.
get() ).ignore();
540 int si = eventContext->
slot();
548 debug() <<
"Event " << eventContext->
evt() <<
" finished (slot " << si <<
")." <<
endmsg;
550 fatal() <<
"Failed event detected on " << *eventContext <<
endmsg;
553 debug() <<
"Clearing slot " << si <<
" (event " << eventContext->
evt() <<
") of the whiteboard" <<
endmsg;
555 StatusCode sc = m_whiteboard->clearStore( si );
556 if ( !sc.
isSuccess() ) warning() <<
"Clear of Event data store failed" <<
endmsg;
557 sc = m_whiteboard->freeStore( si );
558 if ( !sc.
isSuccess() ) error() <<
"Whiteboard slot " << eventContext->
slot() <<
" could not be properly cleared";
560 m_createEventCond.notify_all();
IAlgExecStateSvc * m_aess
StatusCode setProperty(IProperty *component, const std::string &name, const TYPE &value, const std::string &doc)
simple function to set the property of the given object from the value
Definition of the MsgStream class used to transmit messages.
StatusCode initialize() override
Define general base for Gaudi exception.
Helper class to set the application return code in case of early exit (e.g.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
StatusCode finalize() override
The Event Selector Interface.
StatusCode finalize() override
implementation of IService::finalize
HistogramAgent base in charge of collecting all the references to DataObjects in a transient store th...
Header file for class GaudiAlgorithm.
constexpr static const auto RECOVERABLE
Basic event loop and scheduler for fast HLT reconstruction.
constexpr static const auto SUCCESS
T duration_cast(T...args)
virtual StatusCode getProperty(Gaudi::Details::PropertyBase *p) const =0
Get the property by property.
virtual std::list< IAlgorithm * > getFlatAlgList()=0
Get the flat list of algorithms.
This class represents an entry point to all the event specific data.
constexpr int ScheduledStop
The IAlgResourcePool is the interface for managing algorithm instances, in particular if clones of th...
#define DECLARE_COMPONENT(type)
constexpr int UnhandledException
tbb::task * execute() override
HLTExecutionTask(std::vector< Gaudi::Algorithm * > &algorithms, std::unique_ptr< EventContext > ctx, ISvcLocator *svcLocator, IAlgExecStateSvc *aem, const HLTEventLoopMgr *parent)
std::vector< Gaudi::Algorithm * > & m_algorithms
GAUDI_API ISvcLocator * svcLocator()
Abstract interface for a service that manages the Algorithm execution states.
This class is used for returning status codes from appropriate routines.
virtual const AlgExecState & algExecState(const Gaudi::StringKey &algName, const EventContext &ctx) const =0
const std::string & key() const
The IRegistry represents the entry door to the environment any data object residing in a transient da...
const IDataSelector & selectedObjects() const
Return the set of selected DataObjects.
virtual const std::string & tag() const
name tag for the exception, or exception type
StatusCode setAppReturnCode(SmartIF< IProperty > &appmgr, int value, bool force=false)
Set the application return code.
GAUDI_API void setCurrentContext(const EventContext *ctx)
virtual void updateEventStatus(const bool &b, const EventContext &ctx)=0
const HLTEventLoopMgr * m_parent
Alias for backward compatibility.
SmartIF< ISvcLocator > m_serviceLocator
void promoteToExecuted(std::unique_ptr< EventContext > eventContext) const
GAUDI_API long mappedMemory(MemoryUnit unit=kByte, InfoType fetch=Memory, long pid=-1)
Basic Process Information: priority boost.
StatusCode nextEvent(int maxevt) override
implementation of IEventProcessor::nextEvent
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
StatusCode initialize() override
implementation of IService::initialize
T back_inserter(T...args)
const StatusCode & ignore() const
Ignore/check StatusCode.
Base class from which all concrete algorithm classes should be derived.
constexpr static const auto FAILURE
StatusCode executeEvent(void *par) override
implementation of IEventProcessor::executeEvent(void* par)
virtual std::vector< Gaudi::Algorithm * > algorithmsRequiredFor(const DataObjIDColl &requested, const std::vector< std::string > &stoppers={}) const =0
Get the (ordered!) list of algorithms required to provide a given DataObjIDColl.
GAUDI_API void setCurrentContextEvt(long int evtN)
StatusCode stopRun() override
implementation of IEventProcessor::stopRun()
AttribStringParser::Iterator begin(const AttribStringParser &parser)
Opaque address interface definition.
StatusCode declareEventRootAddress()
Declare the root address of the event.
The IProperty is the basic interface for all components which have properties that can be set or get...
std::string fullKey() const
StatusCode eventFailed(EventContext *eventContext) const
Method to check if an event failed and take appropriate actions.
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
std::unique_ptr< EventContext > m_evtCtx
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
std::ostream & operator<<(std::ostream &str, const GaudiAlg::ID &id)
Operator overloading for ostream.