ATLAS Offline Software
AthSequencer.cxx
Go to the documentation of this file.
1 
3 /*
4  Copyright (C) 2002-2024 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 
172 StatusCode AthSequencer::executeAlgorithm (Gaudi::Algorithm* theAlgorithm,
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 
247 AthSequencer::append( Gaudi::Algorithm* pAlgorithm )
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 
261 AthSequencer::remove( Gaudi::Algorithm* pAlgorithm )
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 
290 AthSequencer::append( Gaudi::Algorithm* pAlgorithm,
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  SmartIF<IAlgManager> theAlgMgr(Gaudi::svcLocator()->as<IAlgManager>());
316  IAlgorithm* tmp = nullptr;
317 
318  ATH_CHECK( theAlgMgr->createAlgorithm( type, algName, tmp ) );
319  pAlgorithm = dynamic_cast<Gaudi::Algorithm*>(tmp);
320  theAlgs->push_back( pAlgorithm );
321 
322  return StatusCode::SUCCESS;
323 }
324 
326 AthSequencer::decodeNames( Gaudi::Property<std::vector<std::string>>& theNames,
327  std::vector<Gaudi::Algorithm*>* theAlgs )
328 {
329  SmartIF<IAlgManager> theAlgMgr(Gaudi::svcLocator()->as<IAlgManager>());
330 
331  // Clear the existing list of algorithms
332  theAlgs->clear( );
333 
334  // Build the list of member algorithms from the contents of the
335  // theNames list.
336  StatusCode result = StatusCode::SUCCESS;
337  for (const std::string& name : theNames.value()) {
338 
339  // Parse the name for a syntax of the form <type>/<name>
340  Gaudi::Utils::TypeNameString tn(name);
341 
342  // Check whether the supplied name corresponds to an existing
343  // Algorithm object.
344  SmartIF<IAlgorithm>& theIAlg = theAlgMgr->algorithm(tn.name(), /*createIf*/false);
345  Gaudi::Algorithm* theAlgorithm = nullptr;
346  if ( theIAlg ) {
347  theAlgorithm = dynamic_cast<Gaudi::Algorithm*>(theIAlg.get());
348  if ( theAlgorithm ) {
349  // The specified Algorithm already exists -
350  // just append it to the membership list.
351  if ( append(theAlgorithm, theAlgs).isSuccess( ) ) {
352  ATH_MSG_DEBUG (tn.name() << " already exists - appended to member list");
353  } else {
354  ATH_MSG_WARNING (tn.name() << " already exists - append failed!!!");
355  result = StatusCode::FAILURE;
356  }
357  }
358  else {
359  ATH_MSG_WARNING (tn.name() << " is not an Algorithm - Failed dynamic cast");
360  result = StatusCode::FAILURE;
361  }
362  } else {
363  // The specified name doesn't exist -
364  // create a new object of the specified type and append it to
365  // the membership list.
366  if ( createAndAppend(tn.type(), tn.name(), theAlgorithm, theAlgs).isSuccess( ) ) {
367  ATH_MSG_DEBUG (tn.name() << " doesn't exist - created and appended to member list");
368  } else {
369  ATH_MSG_WARNING (tn.name() << " doesn't exist - creation failed!!!");
370  result = StatusCode::FAILURE;
371  }
372  }
373  } //> loop over names
374 
375  // Print membership list
376  if (msgLvl(MSG::DEBUG)) {
377  if ( result.isSuccess() && !theAlgs->empty() ) {
378 
379  msg(MSG::DEBUG) << "Member list: ";
380  bool first = true;
381  for (Gaudi::Algorithm* alg : *theAlgs) {
382  if (first)
383  first = false;
384  else
385  msg() << ", ";
386  if ( alg->name() == System::typeinfoName(typeid(*alg)))
387  msg() << alg->name();
388  else
389  msg() << System::typeinfoName(typeid(*alg)) << "/" << alg->name();
390  }
391  msg(MSG::DEBUG) << endmsg;
392  }
393  }
394  return result;
395 }
396 
398 AthSequencer::remove( const std::string& /*algname*/,
399  std::vector<Gaudi::Algorithm*>* /*theAlgs*/ )
400 {
401  ATH_MSG_ERROR ("AthSequencer::remove( ) is not supported");
402  return StatusCode::FAILURE;
403 }
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: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:54
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
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
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: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:228
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
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:326
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:536
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:187
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