ATLAS Offline Software
AthSequencer.cxx
Go to the documentation of this file.
1 
3 /*
4  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 // AthSequencer.cxx
8 // Implementation file for class AthSequencer
9 // Author: S.Binet<binet@cern.ch>
11 
12 // AthSequencer class
13 // Implements:
14 // 1) Common functionality of IInterface
15 // 2) Default behaviour for the IAlgorithm
16 
17 #include "AthSequencer.h"
18 
19 #include "GaudiKernel/IAlgManager.h"
20 #include "GaudiKernel/ISvcLocator.h"
23 #include "CxxUtils/excepts.h"
24 
25 #include <memory.h>
26 #include "valgrind/valgrind.h"
27 
29 thread_local std::unique_ptr<Athena::AlgorithmTimer> s_abortTimer{nullptr};
30 
31 
35 AthSequencer::AthSequencer( const std::string& name,
36  ISvcLocator* pSvcLocator ):
37  ::AthCommonDataStore<AthCommonMsg<Gaudi::Sequence>> ( name, pSvcLocator ),
38  m_clidSvc("ClassIDSvc/ClassIDSvc", name),
39  m_timeoutMilliseconds(0)
40 {
41  m_names.declareUpdateHandler( &AthSequencer::membershipHandler, this );
42 }
43 
48 {}
49 
52 {
53  m_timeoutMilliseconds = static_cast<int>(m_timeout * 1e-6);
54 
55  if ( RUNNING_ON_VALGRIND ) {
56  ATH_MSG_WARNING ("### detected running inside Valgrind, disabling algorithm timeout ###");
58  }
59 
60  if (!decodeMemberNames().isSuccess()) {
61  ATH_MSG_ERROR ("Unable to configure one or more sequencer members ");
62  return StatusCode::FAILURE;
63  }
64 
65  Ath::DynamicDataHelper dynamic_data_helper;
66  StatusCode sc(StatusCode::SUCCESS);
67  // Loop over all sub-algorithms
68  for (Gaudi::Algorithm* theAlgorithm : *subAlgorithms()) {
69  if (!theAlgorithm->sysInitialize( ).isSuccess()) {
70  ATH_MSG_ERROR ("Unable to initialize Algorithm "
71  << theAlgorithm->type() << "/" << theAlgorithm->name());
72  sc= StatusCode::FAILURE;
73  }
74  else if (m_runPostInitialize) {
75  // visit all algorithms and its tools to gather their input, output handles and dynamic data consumers
76  dynamic_data_helper.gatherDataHandlesAndDynamicConsumers(this->name(),theAlgorithm);
77  }
78  }
79  if (sc.isSuccess() && m_runPostInitialize) {
80  ATH_MSG_DEBUG("Allow dynamic data consumers to update their data dependencies.");
81  if (!m_undeclaredOutputData.empty()) {
82  ATH_CHECK( m_clidSvc.retrieve() );
83  ATH_CHECK( dynamic_data_helper.addExtraDependencies(*m_clidSvc, m_undeclaredOutputData.value(), msg() ) );
84  }
85  dynamic_data_helper.updateDataNeeds(m_maxPass, msg());
86  }
87  return sc;
88 }
89 
92 {
93  StatusCode sc(StatusCode::SUCCESS);
94  // Bypass the loop if this sequencer is disabled
95  if ( isEnabled( ) ) {
96 
97  // Loop over all members calling their reinitialize functions
98  // if they are not disabled.
99  for (Gaudi::Algorithm* theAlgorithm : *subAlgorithms()) {
100  if ( theAlgorithm->isEnabled( ) ) {
101  if (theAlgorithm->sysReinitialize( ).isFailure()) {
102  ATH_MSG_ERROR ("Unable to reinitialize Algorithm "
103  << theAlgorithm->type () << "/"
104  << theAlgorithm->name());
105  sc = StatusCode::FAILURE;
106  }
107  }
108  }
109  }
110  return sc;
111 }
112 
114 AthSequencer::execute( const EventContext& ctx ) const
115 {
116  StatusCode sc = StatusCode::SUCCESS;
117  bool seqPass = !m_modeOR;
118 
119  ATH_MSG_DEBUG ("Executing " << name() << "...");
120 
121  auto& state = execState( ctx );
122 
123  // Bypass the loop if this sequencer is disabled or has already been executed
124  if ( isEnabled( ) && state.state() != AlgExecState::State::Done ) {
125 
126  // Prevent multiple executions of this sequencer for the current event
127  state.setState( AlgExecState::State::Executing );
128 
129  // Loop over all algorithms calling their execute functions if they
130  // are (a) not disabled, and (b) aren't already executed. Note that
131  // in the latter case the filter state is still examined. Terminate
132  // the loop if an algorithm indicates that it's filter didn't pass.
133  const std::vector<Gaudi::Algorithm*>* subAlgms = subAlgorithms( );
134  for (auto theAlgorithm : *subAlgms) {
135  if ( theAlgorithm->isEnabled( ) ) {
136  if ( theAlgorithm->execState(ctx).state() == AlgExecState::State::None ) {
137  sc = executeAlgorithm (theAlgorithm, ctx);
138  }
139 
140  if ( sc.isSuccess() ) {
141 
142  if ( !m_ignoreFilter ) {
143  // Take the filter passed status of this algorithm as my own status
144  const bool passed = theAlgorithm->execState( ctx ).filterPassed();
145  state.setFilterPassed( passed );
146 
147  // The behaviour when the filter fails depends on the
148  // StopOverride property.
149  // The default action is to stop processing, but this default can be
150  // overridden by setting the "StopOverride" property to false.
151  if ( m_modeOR ? passed : !passed ) {
152  seqPass = passed;
153  if ( !m_stopOverride ) break;
154  }
155  }
156  } else {
157  ATH_MSG_INFO ("execute of [" << theAlgorithm->name() << "] did NOT succeed");
158  break;
159  }
160  }
161  }
162  }
163 
164  if ( !m_ignoreFilter && !m_names.empty() ) state.setFilterPassed( seqPass );
165 
166  state.setState( AlgExecState::State::Done );
167 
168  return sc;
169 }
170 
171 
173  const EventContext& ctx) const
174 {
175  // Start timer if enabled
176  if (m_timeoutMilliseconds>0) {
177  // Create thread-specific timer if not done already
178  if (!s_abortTimer) {
179  s_abortTimer = std::make_unique<Athena::AlgorithmTimer>(0);
180  }
182  }
183 
184  // Call the sysExecute() of the method the algorithm
185  StatusCode sc = theAlgorithm->sysExecute( ctx );
186 
187  // Stop timer if enabled
188  if (m_timeoutMilliseconds>0) {
189  const unsigned int remaining = s_abortTimer->stop();
190  ATH_MSG_DEBUG ("Time left before interrupting <"
191  << theAlgorithm->name() << "> : " << remaining);
192  }
193  return sc;
194 }
195 
198 {
199  StatusCode sc(StatusCode::SUCCESS);
200  // Loop over all sub-algorithms
201  for (Gaudi::Algorithm* theAlgorithm : *subAlgorithms()) {
202  if (!theAlgorithm->sysStart( ).isSuccess()) {
203  ATH_MSG_ERROR ("Unable to start Algorithm "
204  << theAlgorithm->type () << "/"
205  << theAlgorithm->name());
206  sc = StatusCode::FAILURE;
207  }
208  }
209  return sc;
210 }
211 
214 {
215  StatusCode sc(StatusCode::SUCCESS);
216  // Loop over all sub-algorithms if they are not disabled.
217  for (Gaudi::Algorithm* theAlgorithm : *subAlgorithms()) {
218  if (theAlgorithm->sysStop( ).isFailure()) {
219  ATH_MSG_ERROR ("Unable to stop Algorithm "
220  << theAlgorithm->type () << "/"
221  << theAlgorithm->name());
222  sc = StatusCode::FAILURE;
223  }
224  }
225  return sc;
226 }
227 
228 void
229 AthSequencer::resetExecuted( const EventContext& ctx ) const
230 {
231  execState(ctx).reset();
232 
233  // Loop over all members calling their resetExecuted functions
234  // if they are not disabled.
235  for (Gaudi::Algorithm* theAlgorithm : *subAlgorithms()) {
236  theAlgorithm->execState(ctx).reset();
237  }
238 }
239 
240 bool
242 {
243  return m_stopOverride.value( );
244 }
245 
248 {
249  return append( pAlgorithm, subAlgorithms( ) );
250 }
251 
254  const std::string& name,
255  Gaudi::Algorithm*& pAlgorithm )
256 {
257  return createAndAppend( type, name, pAlgorithm, subAlgorithms( ) );
258 }
259 
262 {
263  return remove (pAlgorithm->name());
264 }
265 
267 AthSequencer::remove( const std::string& algname )
268 {
269  return remove( algname, subAlgorithms( ) );
270 }
271 
274 {
275  // Decode the membership list
276  return decodeNames( m_names, subAlgorithms() );
277 }
278 
279 void
280 AthSequencer::membershipHandler( Gaudi::Details::PropertyBase& /* theProp */ )
281 {
282  if ( isInitialized() ) decodeMemberNames().ignore();
283 }
284 
291  std::vector<Gaudi::Algorithm*>* theAlgs )
292 {
293  bool all_good = true;
294  // Check that the specified algorithm doesn't already exist
295  // in the membership list
296  for (Gaudi::Algorithm* theAlgorithm : *theAlgs) {
297  if ( theAlgorithm == pAlgorithm ) {
298  all_good = false;
299  break;
300  }
301  }
302  if ( all_good ) {
303  theAlgs->push_back( pAlgorithm );
304  pAlgorithm->addRef();
305  }
306  return all_good ? StatusCode::SUCCESS : StatusCode::FAILURE;
307 }
308 
309 StatusCode
311  const std::string& algName,
312  Gaudi::Algorithm*& pAlgorithm,
313  std::vector<Gaudi::Algorithm*>* theAlgs )
314 {
315  StatusCode result = StatusCode::FAILURE;
316  IAlgManager* theAlgMgr;
317  //result = service( "ApplicationMgr", theAlgMgr );
318  result = serviceLocator()
319  ->getService( "ApplicationMgr",
320  IAlgManager::interfaceID(),
321  *pp_cast<IInterface>(&theAlgMgr) );
322  if ( result.isSuccess( ) ) {
323  IAlgorithm* tmp;
324  result = theAlgMgr->createAlgorithm( type, algName, tmp );
325  if ( result.isSuccess( ) ) {
326  try{
327  pAlgorithm = dynamic_cast<Gaudi::Algorithm*>(tmp);
328  theAlgs->push_back( pAlgorithm );
329  } catch(...){
330  ATH_MSG_ERROR ("Unable to create Algorithm " << algName);
331  result = StatusCode::FAILURE;
332  }
333  }
334  }
335  theAlgMgr->release();
336  return result;
337 }
338 
340 AthSequencer::decodeNames( Gaudi::Property<std::vector<std::string>>& theNames,
341  std::vector<Gaudi::Algorithm*>* theAlgs )
342 {
344  IAlgManager* theAlgMgr;
345  //result = service( "ApplicationMgr", theAlgMgr );
346  result = serviceLocator()->getService( "ApplicationMgr",
347  IAlgManager::interfaceID(),
348  *pp_cast<IInterface>(&theAlgMgr) );
349 
350  if ( result.isSuccess( ) ) {
351 
352  // Clear the existing list of algorithms
353  theAlgs->clear( );
354 
355  // Build the list of member algorithms from the contents of the
356  // theNames list.
357  const std::vector<std::string>& theNameVector = theNames.value( );
358  for (const std::string& name : theNameVector) {
359 
360  // Parse the name for a syntax of the form:
361  //
362  // <type>/<name>
363  //
364  // Where <name> is the algorithm instance name, and <type> is the
365  // algorithm class type (being a subclass of Algorithm).
366  std::string theName = name;
367  std::string theType = name;
368  int slash = name.find_first_of( "/" );
369  if ( slash > 0 ) {
370  theType = name.substr( 0, slash );
371  theName = name.substr( slash+1 );
372  }
373 
374  // Check whether the suppied name corresponds to an existing
375  // Algorithm object.
376  IAlgorithm* theIAlg;
377  Gaudi::Algorithm* theAlgorithm = nullptr;
378  StatusCode status = theAlgMgr->getAlgorithm( theName, theIAlg );
379  if ( status.isSuccess( ) ) {
380  theAlgorithm = dynamic_cast<Gaudi::Algorithm*>(theIAlg);
381  if (!theAlgorithm) {
383  (theName << " is not an Algorithm - Failed dynamic cast");
384  status = StatusCode::FAILURE;
385  }
386  }
387  if ( status.isSuccess( ) && theAlgorithm != nullptr ) {
388 
389  // The specified Algorithm already exists -
390  // just append it to the membership list.
391  status = append( theAlgorithm, theAlgs );
392  if ( status.isSuccess( ) ) {
394  (theName << " already exists - appended to member list");
395  } else {
397  (theName << " already exists - append failed!!!");
398  result = StatusCode::FAILURE;
399  }
400  } else {
401 
402  // The specified name doesn't exist -
403  // create a new object of the specified type and append it to
404  // the membership list.
405  status = createAndAppend( theType, theName, theAlgorithm, theAlgs );
406  if ( status.isSuccess( ) ) {
408  (theName << " doesn't exist - created and appended to member list");
409  } else {
411  (theName << " doesn't exist - creation failed!!!");
412  result = StatusCode::FAILURE;
413  }
414  }
415  } //> loop over names
416 
417  }
418  // Print membership list
419  if (msgLvl(MSG::DEBUG)) {
420  if ( result.isSuccess() && !theAlgs->empty() ) {
421 
422  msg(MSG::DEBUG) << "Member list: ";
423  bool first = true;
424  for (Gaudi::Algorithm* alg : *theAlgs) {
425  if (first)
426  first = false;
427  else
428  msg() << ", ";
429  if ( alg->name() == System::typeinfoName(typeid(*alg)))
430  msg() << alg->name();
431  else
432  msg() << System::typeinfoName(typeid(*alg)) << "/" << alg->name();
433  }
434  msg(MSG::DEBUG) << endmsg;
435  }
436  }
437  theAlgMgr->release();
438  return result;
439 }
440 
442 AthSequencer::remove( const std::string& algname,
443  std::vector<Gaudi::Algorithm*>* theAlgs )
444 {
445  StatusCode result = StatusCode::FAILURE;
446 
447  // Test that the algorithm exists in the member list
448  for (Gaudi::Algorithm* theAlgorithm : *theAlgs) {
449  if ( theAlgorithm->name( ) == algname ) {
450 
451  // Algorithm with specified name exists in the algorithm list - remove it
452  // THIS ISN'T IMPLEMENTED YET!!!!
453  ATH_MSG_INFO ("AthSequencer::remove( ) isn't implemented yet!!!!!");
454  result = StatusCode::SUCCESS;
455  break;
456  }
457  }
458  return result;
459 }
python.samplers.Sequence
Sequence
Alias:
Definition: samplers.py:237
AthSequencer::append
StatusCode append(Gaudi::Algorithm *pAlgorithm)
Append an algorithm to the sequencer.
Definition: AthSequencer.cxx:247
AthSequencer::~AthSequencer
virtual ~AthSequencer()
Destructor.
Definition: AthSequencer.cxx:47
AthSequencer::AthSequencer
AthSequencer(const std::string &name, ISvcLocator *svcloc)
Constructor(s)
Definition: AthSequencer.cxx:35
getMenu.algname
algname
Definition: getMenu.py:53
AthSequencer::m_clidSvc
ServiceHandle< IClassIDSvc > m_clidSvc
Definition: AthSequencer.h:204
SGout2dot.alg
alg
Definition: SGout2dot.py:243
get_generator_info.result
result
Definition: get_generator_info.py:21
TrigCompositeUtils::passed
bool passed(DecisionID id, const DecisionIDContainer &idSet)
checks if required decision ID is in the set of IDs in the container
Definition: TrigCompositeUtilsRoot.cxx:117
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
Ath::DynamicDataHelper
Helper class to gather all declared data IDs and propagate them to components which declare data depe...
Definition: DynamicDataHelper.h:25
AthSequencer::decodeMemberNames
StatusCode decodeMemberNames()
Decode Member Name list.
Definition: AthSequencer.cxx:273
xAOD::JetAlgorithmType::algName
const std::string & algName(ID id)
Converts a JetAlgorithmType::ID into a string.
Definition: JetContainerInfo.cxx:67
python.FakeAthena.Algorithm
def Algorithm(name)
Definition: FakeAthena.py:41
AthCommonMsg< Gaudi::Sequence >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
excepts.h
Declarations of feenableexcept()/fedisableexcept() functions for MacOSX.
AthSequencer::m_maxPass
const unsigned int m_maxPass
Definition: AthSequencer.h:207
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
AthSequencer::initialize
virtual StatusCode initialize() override
Initialization of a sequencer.
Definition: AthSequencer.cxx:51
AthSequencer::m_modeOR
Gaudi::Property< bool > m_modeOR
Definition: AthSequencer.h:181
AthSequencer::m_runPostInitialize
Gaudi::Property< bool > m_runPostInitialize
Definition: AthSequencer.h:200
CaloCellPos2Ntuple.None
None
Definition: CaloCellPos2Ntuple.py:23
AthSequencer::m_undeclaredOutputData
Gaudi::Property< std::vector< std::string > > m_undeclaredOutputData
Definition: AthSequencer.h:197
AlgorithmTimer.h
Efficient realtime timers.
AthCommonDataStore
Definition: AthCommonDataStore.h:52
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
s_abortTimer
thread_local std::unique_ptr< Athena::AlgorithmTimer > s_abortTimer
timer will abort job once timeout for any algorithm or sequence is reached
Definition: AthSequencer.cxx:29
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AthSequencer::m_ignoreFilter
Gaudi::Property< bool > m_ignoreFilter
Definition: AthSequencer.h:184
AthSequencer::resetExecuted
virtual void resetExecuted(const EventContext &ctx) const
Reset the AthSequencer executed state for the current event.
Definition: AthSequencer.cxx:229
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
AthSequencer::execute
virtual StatusCode execute(const EventContext &ctx) const override
The actions to be performed by the sequencer on an event.
Definition: AthSequencer.cxx:114
AthSequencer::membershipHandler
void membershipHandler(Gaudi::Details::PropertyBase &theProp)
"Members" property handler
Definition: AthSequencer.cxx:280
AthSequencer::isStopOverride
virtual bool isStopOverride() const
Has the StopOverride mode been set?
Definition: AthSequencer.cxx:241
Ath::DynamicDataHelper::gatherDataHandlesAndDynamicConsumers
void gatherDataHandlesAndDynamicConsumers(const std::string &parent_name, Gaudi::Algorithm *theAlgorithm)
Gather the input and output data declared by the given algorithm, its child algorithms and their tool...
Definition: DynamicDataHelper.cxx:65
AthSequencer::remove
StatusCode remove(Gaudi::Algorithm *pAlgorithm)
Remove the specified algorithm from the sequencer.
Definition: AthSequencer.cxx:261
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
AthSequencer::m_names
Gaudi::Property< std::vector< std::string > > m_names
Definition: AthSequencer.h:178
AthSequencer::start
virtual StatusCode start() override
Start (from INITIALIZED to RUNNING).
Definition: AthSequencer.cxx:197
AthSequencer::executeAlgorithm
StatusCode executeAlgorithm(Gaudi::Algorithm *theAlgorithm, const EventContext &ctx) const
Run one algorithm.
Definition: AthSequencer.cxx:172
AthSequencer::createAndAppend
StatusCode createAndAppend(const std::string &type, const std::string &name, Gaudi::Algorithm *&pAlgorithm)
Create a algorithm and append it to the sequencer.
Definition: AthSequencer.cxx:253
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
AthCommonMsg
Definition: AthCommonMsg.h:19
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
AthSequencer::decodeNames
StatusCode decodeNames(Gaudi::Property< std::vector< std::string >> &theNames, std::vector< Gaudi::Algorithm * > *theAlgs)
Decode algorithm names, creating or appending algorithms as appropriate.
Definition: AthSequencer.cxx:340
AthSequencer::m_timeoutMilliseconds
unsigned int m_timeoutMilliseconds
timeout converted to ms
Definition: AthSequencer.h:206
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
DeMoScan.first
bool first
Definition: DeMoScan.py:534
DEBUG
#define DEBUG
Definition: page_access.h:11
AthCommonMsg< Gaudi::Sequence >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
AthSequencer::reinitialize
virtual StatusCode reinitialize() override
AthSequencer Reinitialization.
Definition: AthSequencer.cxx:91
Gaudi
=============================================================================
Definition: CaloGPUClusterAndCellDataMonitorOptions.h:273
merge.status
status
Definition: merge.py:17
Ath::DynamicDataHelper::updateDataNeeds
void updateDataNeeds(unsigned int max_pass, MsgStream &out)
Update the data dependencies of all components which dynamically declare tehm.
Definition: DynamicDataHelper.cxx:100
DynamicDataHelper.h
AthSequencer::m_stopOverride
Gaudi::Property< bool > m_stopOverride
Definition: AthSequencer.h:187
python.web.remaining
remaining
Definition: web.py:132
Ath::DynamicDataHelper::addExtraDependencies
StatusCode addExtraDependencies(IClassIDSvc &clid_svc, std::vector< std::string > &undeclared_output_data, MsgStream &out)
Add extra output data which is not declared by any of the gathered components.
Definition: DynamicDataHelper.cxx:26
AthSequencer.h
AthSequencer::m_timeout
Gaudi::Property< double > m_timeout
Definition: AthSequencer.h:193
AthSequencer::stop
virtual StatusCode stop() override
Stop (from RUNNING to INITIALIZED).
Definition: AthSequencer.cxx:213