ATLAS Offline Software
AthSequencer.cxx
Go to the documentation of this file.
1 
3 /*
4  Copyright (C) 2002-2025 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  if ( m_invert ) {
146  state.setFilterPassed( !passed );
147  } else {
148  state.setFilterPassed( passed );
149  }
150 
151  // The behaviour when the filter fails depends on the
152  // StopOverride property.
153  // The default action is to stop processing, but this default can be
154  // overridden by setting the "StopOverride" property to false.
155  if ( m_modeOR ? passed : !passed ) {
156  seqPass = passed;
157  if ( !m_stopOverride ) break;
158  }
159  }
160  } else {
161  ATH_MSG_INFO ("execute of [" << theAlgorithm->name() << "] did NOT succeed");
162  break;
163  }
164  }
165  }
166  }
167 
168  if ( !m_ignoreFilter && !m_names.empty() ) {
169  if ( m_invert ) {
170  state.setFilterPassed( !seqPass );
171  } else {
172  state.setFilterPassed( seqPass );
173  }
174  }
175 
176  state.setState( AlgExecState::State::Done );
177 
178  return sc;
179 }
180 
181 
182 StatusCode AthSequencer::executeAlgorithm (Gaudi::Algorithm* theAlgorithm,
183  const EventContext& ctx) const
184 {
185  // Start timer if enabled
186  if (m_timeoutMilliseconds>0) {
187  // Create thread-specific timer if not done already
188  if (!s_abortTimer) {
189  s_abortTimer = std::make_unique<Athena::AlgorithmTimer>(0);
190  }
192  }
193 
194  // Call the sysExecute() of the method the algorithm
195  StatusCode sc = theAlgorithm->sysExecute( ctx );
196 
197  // Stop timer if enabled
198  if (m_timeoutMilliseconds>0) {
199  const unsigned int remaining = s_abortTimer->stop();
200  ATH_MSG_DEBUG ("Time left before interrupting <"
201  << theAlgorithm->name() << "> : " << remaining);
202  }
203  return sc;
204 }
205 
208 {
209  StatusCode sc(StatusCode::SUCCESS);
210  // Loop over all sub-algorithms
211  for (Gaudi::Algorithm* theAlgorithm : *subAlgorithms()) {
212  if (!theAlgorithm->sysStart( ).isSuccess()) {
213  ATH_MSG_ERROR ("Unable to start Algorithm "
214  << theAlgorithm->type () << "/"
215  << theAlgorithm->name());
216  sc = StatusCode::FAILURE;
217  }
218  }
219  return sc;
220 }
221 
224 {
225  StatusCode sc(StatusCode::SUCCESS);
226  // Loop over all sub-algorithms if they are not disabled.
227  for (Gaudi::Algorithm* theAlgorithm : *subAlgorithms()) {
228  if (theAlgorithm->sysStop( ).isFailure()) {
229  ATH_MSG_ERROR ("Unable to stop Algorithm "
230  << theAlgorithm->type () << "/"
231  << theAlgorithm->name());
232  sc = StatusCode::FAILURE;
233  }
234  }
235  return sc;
236 }
237 
238 void
239 AthSequencer::resetExecuted( const EventContext& ctx ) const
240 {
241  execState(ctx).reset();
242 
243  // Loop over all members calling their resetExecuted functions
244  // if they are not disabled.
245  for (Gaudi::Algorithm* theAlgorithm : *subAlgorithms()) {
246  theAlgorithm->execState(ctx).reset();
247  }
248 }
249 
250 bool
252 {
253  return m_stopOverride.value( );
254 }
255 
257 AthSequencer::append( Gaudi::Algorithm* pAlgorithm )
258 {
259  return append( pAlgorithm, subAlgorithms( ) );
260 }
261 
264  const std::string& name,
265  Gaudi::Algorithm*& pAlgorithm )
266 {
267  return createAndAppend( type, name, pAlgorithm, subAlgorithms( ) );
268 }
269 
271 AthSequencer::remove( Gaudi::Algorithm* pAlgorithm )
272 {
273  return remove (pAlgorithm->name());
274 }
275 
277 AthSequencer::remove( const std::string& algname )
278 {
279  return remove( algname, subAlgorithms( ) );
280 }
281 
284 {
285  // Decode the membership list
286  return decodeNames( m_names, subAlgorithms() );
287 }
288 
289 void
290 AthSequencer::membershipHandler( Gaudi::Details::PropertyBase& /* theProp */ )
291 {
292  if ( isInitialized() ) decodeMemberNames().ignore();
293 }
294 
300 AthSequencer::append( Gaudi::Algorithm* pAlgorithm,
301  std::vector<Gaudi::Algorithm*>* theAlgs )
302 {
303  bool all_good = true;
304  // Check that the specified algorithm doesn't already exist
305  // in the membership list
306  for (Gaudi::Algorithm* theAlgorithm : *theAlgs) {
307  if ( theAlgorithm == pAlgorithm ) {
308  all_good = false;
309  break;
310  }
311  }
312  if ( all_good ) {
313  theAlgs->push_back( pAlgorithm );
314  pAlgorithm->addRef();
315  }
316  return all_good ? StatusCode::SUCCESS : StatusCode::FAILURE;
317 }
318 
319 StatusCode
321  const std::string& algName,
322  Gaudi::Algorithm*& pAlgorithm,
323  std::vector<Gaudi::Algorithm*>* theAlgs )
324 {
325  SmartIF<IAlgManager> theAlgMgr(Gaudi::svcLocator()->as<IAlgManager>());
326  IAlgorithm* tmp = nullptr;
327 
328  ATH_CHECK( theAlgMgr->createAlgorithm( type, algName, tmp ) );
329  pAlgorithm = dynamic_cast<Gaudi::Algorithm*>(tmp);
330  theAlgs->push_back( pAlgorithm );
331 
332  return StatusCode::SUCCESS;
333 }
334 
336 AthSequencer::decodeNames( Gaudi::Property<std::vector<std::string>>& theNames,
337  std::vector<Gaudi::Algorithm*>* theAlgs )
338 {
339  SmartIF<IAlgManager> theAlgMgr(Gaudi::svcLocator()->as<IAlgManager>());
340 
341  // Clear the existing list of algorithms
342  theAlgs->clear( );
343 
344  // Build the list of member algorithms from the contents of the
345  // theNames list.
346  StatusCode result = StatusCode::SUCCESS;
347  for (const std::string& name : theNames.value()) {
348 
349  // Parse the name for a syntax of the form <type>/<name>
350  Gaudi::Utils::TypeNameString tn(name);
351 
352  // Check whether the supplied name corresponds to an existing
353  // Algorithm object.
354  SmartIF<IAlgorithm>& theIAlg = theAlgMgr->algorithm(tn.name(), /*createIf*/false);
355  Gaudi::Algorithm* theAlgorithm = nullptr;
356  if ( theIAlg ) {
357  theAlgorithm = dynamic_cast<Gaudi::Algorithm*>(theIAlg.get());
358  if ( theAlgorithm ) {
359  // The specified Algorithm already exists -
360  // just append it to the membership list.
361  if ( append(theAlgorithm, theAlgs).isSuccess( ) ) {
362  ATH_MSG_DEBUG (tn.name() << " already exists - appended to member list");
363  } else {
364  ATH_MSG_WARNING (tn.name() << " already exists - append failed!!!");
365  result = StatusCode::FAILURE;
366  }
367  }
368  else {
369  ATH_MSG_WARNING (tn.name() << " is not an Algorithm - Failed dynamic cast");
370  result = StatusCode::FAILURE;
371  }
372  } else {
373  // The specified name doesn't exist -
374  // create a new object of the specified type and append it to
375  // the membership list.
376  if ( createAndAppend(tn.type(), tn.name(), theAlgorithm, theAlgs).isSuccess( ) ) {
377  ATH_MSG_DEBUG (tn.name() << " doesn't exist - created and appended to member list");
378  } else {
379  ATH_MSG_WARNING (tn.name() << " doesn't exist - creation failed!!!");
380  result = StatusCode::FAILURE;
381  }
382  }
383  } //> loop over names
384 
385  // Print membership list
386  if (msgLvl(MSG::DEBUG)) {
387  if ( result.isSuccess() && !theAlgs->empty() ) {
388 
389  msg(MSG::DEBUG) << "Member list: ";
390  bool first = true;
391  for (Gaudi::Algorithm* alg : *theAlgs) {
392  if (first)
393  first = false;
394  else
395  msg() << ", ";
396  if ( alg->name() == System::typeinfoName(typeid(*alg)))
397  msg() << alg->name();
398  else
399  msg() << System::typeinfoName(typeid(*alg)) << "/" << alg->name();
400  }
401  msg(MSG::DEBUG) << endmsg;
402  }
403  }
404  return result;
405 }
406 
408 AthSequencer::remove( const std::string& /*algname*/,
409  std::vector<Gaudi::Algorithm*>* /*theAlgs*/ )
410 {
411  ATH_MSG_ERROR ("AthSequencer::remove( ) is not supported");
412  return StatusCode::FAILURE;
413 }
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
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:257
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:54
AthSequencer::m_clidSvc
ServiceHandle< IClassIDSvc > m_clidSvc
Definition: AthSequencer.h:207
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:118
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:283
xAOD::JetAlgorithmType::algName
const std::string & algName(ID id)
Converts a JetAlgorithmType::ID into a string.
Definition: JetContainerInfo.cxx:67
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_invert
Gaudi::Property< bool > m_invert
Definition: AthSequencer.h:187
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
AthSequencer::m_maxPass
const unsigned int m_maxPass
Definition: AthSequencer.h:210
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:203
CaloCellPos2Ntuple.None
None
Definition: CaloCellPos2Ntuple.py:23
AthSequencer::m_undeclaredOutputData
Gaudi::Property< std::vector< std::string > > m_undeclaredOutputData
Definition: AthSequencer.h:200
AlgorithmTimer.h
Efficient realtime timers.
AthCommonDataStore
Definition: AthCommonDataStore.h:52
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Athena::typeinfoName
std::string typeinfoName(const std::type_info &ti)
Convert a type_info to a demangled string.
Definition: AthenaKernel/src/ClassName.cxx:23
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:239
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:290
AthSequencer::isStopOverride
virtual bool isStopOverride() const
Has the StopOverride mode been set?
Definition: AthSequencer.cxx:251
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:271
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
AthSequencer::m_names
Gaudi::Property< std::vector< std::string > > m_names
Definition: AthSequencer.h:178
RegSelToolConfig.alg
alg
Definition: RegSelToolConfig.py:332
AthSequencer::start
virtual StatusCode start() override
Start (from INITIALIZED to RUNNING).
Definition: AthSequencer.cxx:207
AthSequencer::executeAlgorithm
StatusCode executeAlgorithm(Gaudi::Algorithm *theAlgorithm, const EventContext &ctx) const
Run one algorithm.
Definition: AthSequencer.cxx:182
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:263
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:336
AthSequencer::m_timeoutMilliseconds
unsigned int m_timeoutMilliseconds
timeout converted to ms
Definition: AthSequencer.h:209
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
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:190
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:196
AthSequencer::stop
virtual StatusCode stop() override
Stop (from RUNNING to INITIALIZED).
Definition: AthSequencer.cxx:223