25 #include <condition_variable> 30 #include "boost/algorithm/string.hpp" 31 #include "boost/optional.hpp" 32 #include "boost/thread.hpp" 33 #include "boost/tokenizer.hpp" 34 #include "tbb/task_scheduler_init.h" 43 struct DataObjIDDotRepr {
47 return os <<
'\"' << repr.parent.fullKey() <<
'\"';
51 struct DataObjIDSorter {
77 : m_algorithms( algorithms )
78 , m_evtCtx(
std::move( ctx ) )
80 , m_serviceLocator( svcLocator )
88 return MsgStream( messageSvc,
"HLTExecutionTask" );
93 bool eventfailed =
false;
101 ialg->whiteboard()->selectStore( m_evtCtx->
valid() ? m_evtCtx->
slot() : 0 ).ignore();
107 sc = ialg->sysExecute( *m_evtCtx );
114 log() <<
MSG::FATAL <<
".executeEvent(): Exception with tag=" << Exception.
tag() <<
" thrown by " 118 log() <<
MSG::FATAL <<
".executeEvent(): Standard std::exception thrown by " << ialg->name() <<
endmsg 122 log() <<
MSG::FATAL <<
".executeEvent(): UNKNOWN Exception thrown by " << ialg->name() <<
endmsg;
133 if ( !ialg->filterPassed() )
break;
147 error() <<
"Failed to initialize Service Base class." <<
endmsg;
151 m_evtDataMgrSvc = serviceLocator()->service<
IDataManagerSvc>(
"EventDataSvc" );
152 if ( !m_evtDataMgrSvc ) {
153 fatal() <<
"Error retrieving EventDataSvc interface IDataManagerSvc." <<
endmsg;
156 m_whiteboard = serviceLocator()->service<
IHiveWhiteBoard>(
"EventDataSvc" );
157 if ( !m_whiteboard ) {
158 fatal() <<
"Error retrieving EventDataSvc interface IHiveWhiteBoard." <<
endmsg;
163 if ( !appMgrProperty ) {
164 fatal() <<
"IProperty interface not found in ApplicationMgr." <<
endmsg;
170 if ( m_evtsel !=
"NONE" || m_evtsel.length() == 0 ) {
171 m_evtSelector = serviceLocator()->service<
IEvtSelector>(
"EventSelector" );
173 m_evtSelector =
nullptr;
174 warning() <<
"Unable to locate service \"EventSelector\" " <<
endmsg;
175 warning() <<
"No events will be processed from external input." <<
endmsg;
179 m_histoDataMgrSvc = serviceLocator()->service<
IDataManagerSvc>(
"HistogramDataSvc" );
180 if ( !m_histoDataMgrSvc ) {
181 fatal() <<
"Error retrieving HistogramDataSvc." <<
endmsg;
185 m_histoPersSvc = serviceLocator()->service<
IConversionSvc>(
"HistogramPersistencySvc" );
186 if ( !m_histoPersSvc ) {
187 warning() <<
"Histograms cannot not be saved - though required." <<
endmsg;
191 m_algExecStateSvc = serviceLocator()->service<
IAlgExecStateSvc>(
"AlgExecStateSvc" );
192 if ( !m_algExecStateSvc ) {
193 fatal() <<
"Error retrieving AlgExecStateSvc" <<
endmsg;
197 m_algExecStateSvc = serviceLocator()->service<
IAlgExecStateSvc>(
"AlgExecStateSvc" );
198 if ( !m_algExecStateSvc ) {
199 fatal() <<
"Error retrieving AlgExecStateSvc" <<
endmsg;
205 if ( !algResourcePool ) {
206 fatal() <<
"Error retrieving AlgoResourcePool" <<
endmsg;
212 fatal() <<
"Could not convert IAlgorithm into Algorithm: this will result in a crash." <<
endmsg;
214 m_algos.push_back( algoPtr );
222 boost::optional<std::ofstream> dot{boost::in_place_init_if, !m_dotfile.
empty(), m_dotfile.value()};
225 *dot <<
"digraph G {\n";
226 for (
auto* a : m_algos ) {
227 bool is_consumer = a->outputDataObjs().empty();
228 *dot <<
'\"' << a->name() <<
"\" [shape=box" << ( is_consumer ?
",style=filled" :
"" ) <<
"];\n";
235 for (
auto id : algoPtr->outputDataObjs() ) {
236 auto r = globalOutp.
insert(
id );
237 producers[id] = algoPtr;
239 warning() <<
"multiple algorithms declare " <<
id <<
" 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() ) {
311 ost <<
"\n * " << i.first->name();
315 fatal() <<
"The following unmet INPUT dependencies were found:" << ost.
str() <<
endmsg;
318 info() <<
"No unmet INPUT data dependencies were found" <<
endmsg;
322 info() <<
"Concurrency level information:" <<
endmsg;
323 info() <<
" o Number of events slots: " << m_whiteboard->getNumberOfStores() <<
endmsg;
324 info() <<
" o TBB thread pool size: " << m_threadPoolSize <<
endmsg;
327 auto start = m_algos.begin();
328 auto end = m_algos.end();
333 while ( current !=
end ) {
343 debug() <<
"Order of algo execution :" <<
endmsg;
353 if ( m_histoPersSvc ) {
355 sc = m_histoDataMgrSvc->traverseTree( &agent );
361 StatusCode iret = m_histoPersSvc->createRep( i, pAddr );
362 if ( iret.
isSuccess() ) i->registry()->setAddress( pAddr );
370 if ( sc.isSuccess() ) {
371 info() <<
"Histograms converted successfully according to request." <<
endmsg;
373 error() <<
"Error while saving Histograms." <<
endmsg;
376 error() <<
"Error while traversing Histogram data store" <<
endmsg;
387 int& createdEvts = *
reinterpret_cast<int*
>( createdEvts_IntPtr );
389 auto evtContext = std::make_unique<EventContext>();
390 evtContext->set( createdEvts, m_whiteboard->allocateStore( createdEvts ) );
391 m_algExecStateSvc->reset( *evtContext );
393 StatusCode sc = m_whiteboard->selectStore( evtContext->slot() );
395 fatal() <<
"Slot " << evtContext->slot() <<
" could not be selected for the WhiteBoard\n" 396 <<
"Impossible to create event context" <<
endmsg;
400 StatusCode declEvtRootSc = declareEventRootAddress();
408 debug() <<
"Event " << evtContext->evt() <<
" submitting in slot " << evtContext->slot() <<
endmsg;
411 tbb::task* task =
new ( tbb::task::allocate_root() )
413 tbb::task::enqueue( *task );
422 auto appmgr = serviceLocator()->as<
IProperty>();
435 auto appmgr = serviceLocator()->as<
IProperty>();
441 StatusCode sc = m_evtSelector->createContext( m_evtSelContext );
443 fatal() <<
"Can not create the event selector Context." <<
endmsg;
448 tbb::task_scheduler_init tbbSchedInit( m_threadPoolSize.value() + 1 );
452 bool newEvtAllowed =
false;
454 info() <<
"Starting loop on events" <<
endmsg;
455 auto start_time = Clock::now();
456 while ( maxevt < 0 || m_finishedEvt < (
unsigned int)maxevt ) {
458 if ( !( ( newEvtAllowed || createdEvts == 0 ) &&
462 ( createdEvts < maxevt || maxevt < 0 ) &&
464 m_whiteboard->freeSlots() > 0 ) ) {
467 using namespace std::chrono_literals;
468 m_createEventCond.wait_for( lock, 1
ms, [
this, newEvtAllowed, createdEvts, maxevt] {
469 return ( newEvtAllowed || 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) - " 503 StatusCode sc = m_evtSelector->next( *m_evtSelContext );
506 sc = m_evtSelector->createAddress( *m_evtSelContext, pAddr );
508 sc = m_evtSelector->next( *m_evtSelContext );
510 sc = m_evtSelector->createAddress( *m_evtSelContext, pAddr );
511 if ( !sc.
isSuccess() ) warning() <<
"Error creating IOpaqueAddress." <<
endmsg;
516 info() <<
"No more events in event selection " <<
endmsg;
519 sc = m_evtDataMgrSvc->setRoot(
"/Event", pAddr );
521 warning() <<
"Error declaring event root address." <<
endmsg;
533 fatal() <<
"*** Event " << eventContext->
evt() <<
" on slot " << eventContext->
slot() <<
" failed! ***" <<
endmsg;
535 m_algExecStateSvc->dump( ost, *eventContext );
536 info() <<
"Dumping Alg Exec State for slot " << eventContext->
slot() <<
":\n" << ost.
str() <<
endmsg;
544 eventFailed( eventContext.
get() ).ignore();
545 int si = eventContext->
slot();
553 debug() <<
"Event " << eventContext->
evt() <<
" finished (slot " << si <<
")." <<
endmsg;
555 fatal() <<
"Failed event detected on " << *eventContext <<
endmsg;
558 debug() <<
"Clearing slot " << si <<
" (event " << eventContext->
evt() <<
") of the whiteboard" <<
endmsg;
560 StatusCode sc = m_whiteboard->clearStore( si );
561 if ( !sc.
isSuccess() ) warning() <<
"Clear of Event data store failed" <<
endmsg;
562 sc = m_whiteboard->freeStore( si );
563 if ( !sc.
isSuccess() ) error() <<
"Whiteboard slot " << eventContext->
slot() <<
" could not be properly cleared";
565 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
constexpr static const auto FAILURE
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...
const std::string & name() const override
The identifying name of the algorithm object.
StatusCode finalize() override
The Event Selector Interface.
StatusCode finalize() override
implementation of IService::finalize
HistogramAgent base in charge of collecting all the refereces to DataObjects in a transient store tha...
Header file for class GaudiAlgorithm.
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
GAUDI_API ISvcLocator * svcLocator()
Abstract interface for a service that manages the Algorithm execution states.
constexpr static const auto RECOVERABLE
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...
virtual const std::string & tag() const
name tag for the exception, or exception type
IDataSelector * selectedObjects()
Return the set of selected DataObjects.
StatusCode setAppReturnCode(SmartIF< IProperty > &appmgr, int value, bool force=false)
Set the application return code.
HLTExecutionTask(std::vector< Algorithm * > &algorithms, std::unique_ptr< EventContext > ctx, ISvcLocator *svcLocator, IAlgExecStateSvc *aem, const HLTEventLoopMgr *parent)
GAUDI_API void setCurrentContext(const EventContext *ctx)
constexpr static const auto SUCCESS
virtual void updateEventStatus(const bool &b, const EventContext &ctx)=0
const HLTEventLoopMgr * m_parent
Base class from which all concrete algorithm classes should be derived.
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
const StatusCode & ignore() const
Ignore/check StatusCode.
StatusCode executeEvent(void *par) override
implementation of IEventProcessor::executeEvent(void* par)
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::vector< Algorithm * > & m_algorithms
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.