Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v36r16 (ea80daf8)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Sequencer.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 // Sequencer class
12 // Implements:
13 // 1) Common functionality of IInterface
14 // 2) Default behavior for the IAlgorithm
15 #include "GaudiAlg/Sequencer.h"
16 
17 #include "GaudiKernel/Chrono.h"
21 #include "GaudiKernel/Stat.h"
23 
24 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
25 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
26 
28  auto is_good = decodeMemberNames();
29  if ( !is_good ) {
30  error() << "Unable to configure one or more sequencer members " << endmsg;
31  return is_good;
32  }
33 
34  is_good = decodeBranchMemberNames();
35  if ( !is_good ) {
36  error() << "Unable to configure one or more branch members " << endmsg;
37  return is_good;
38  }
39 
40  // We have to "decode" members before calling base class initialize
41  is_good = Sequence::initialize();
42  if ( !is_good ) return is_good;
43 
44  // Loop over all branches
45  // (Sequence does not know about branches)
46  for ( auto& alg : branchAlgorithms() ) {
47  is_good = alg->sysInitialize();
48  if ( is_good.isFailure() ) {
49  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
50  return is_good;
51  }
52  }
53 
54  return is_good;
55 }
56 
58  // Bypass the loop if this sequencer is disabled
59  if ( isEnabled() ) {
60  // Loop over all branch members calling their reinitialize functions
61  // if they are not disabled.
62  for ( auto& alg : branchAlgorithms() ) {
63  if ( alg->isEnabled() ) { alg->reinitialize().ignore(); }
64  }
65  return Sequence::reinitialize();
66  }
67  return StatusCode::SUCCESS;
68 }
69 
72  ON_DEBUG debug() << name() << " Sequencer::execute()" << endmsg;
73 
74  auto& state = execState( ctx );
75 
76  // Bypass the loop if this sequencer is disabled or has already been executed
77  if ( isEnabled() && !( execState( ctx ).state() == AlgExecState::State::Done ) ) {
78  Gaudi::Algorithm* lastAlgorithm;
79  result = execute( ctx, *subAlgorithms(), m_isInverted, lastAlgorithm );
80  if ( result.isSuccess() ) {
81  const bool passed = state.filterPassed();
82  if ( !passed && !isStopOverride() ) {
83 
84  // Filter failed and stop override not set. Execute the
85  // branch if there is one associated with the filter
86  // algorithm that failed. Note that the first member on
87  // the branch is the failing algorithm and so should
88  // be skipped.
89  const auto& theAlgs = branchAlgorithms();
90  if ( !theAlgs.empty() ) {
91  Gaudi::Algorithm* branchAlgorithm = theAlgs[0];
92  if ( lastAlgorithm == branchAlgorithm ) {
93 
94  // Branch specified - Loop over branch members
95  result = execute( ctx, branchAlgorithms(), m_isBranchInverted, lastAlgorithm, 1 );
96  if ( result.isSuccess() ) {
97 
98  // The final filter passed state will be set true if either
99  // of the main or branches passed, otherwise false.
100 
101  // Save the branch filter passed state.
102  setBranchFilterPassed( ctx, state.filterPassed() );
103  }
104  }
105  }
106  }
107  }
108 
109  // Prevent multiple executions of this sequencer for the current event
110  state.setState( AlgExecState::State::Done );
111  }
112  return result;
113 }
114 
116  // Loop over all branch members calling their finalize functions
117  // if they are not disabled. Note that the Sequence::finalize
118  // function already does this for the main members.
119  for ( auto& alg : branchAlgorithms() ) {
120  if ( alg->sysFinalize().isFailure() ) { error() << "Unable to finalize Algorithm " << alg->name() << endmsg; }
121  }
122  return Sequence::finalize();
123 }
124 
126  auto is_good = Sequence::start();
127  if ( !is_good ) return is_good;
128 
129  // Loop over all branches
130  for ( auto& alg : branchAlgorithms() ) {
131  is_good = alg->sysStart();
132  if ( !is_good ) {
133  error() << "Unable to start Algorithm " << alg->name() << endmsg;
134  return is_good;
135  }
136  }
137 
138  return is_good;
139 }
140 
142  // Loop over all branch members calling their finalize functions
143  // if they are not disabled.
144  for ( auto& alg : branchAlgorithms() ) {
145  if ( alg->sysStop().isFailure() ) { error() << "Unable to stop Algorithm " << alg->name() << endmsg; }
146  }
147  return Sequence::stop();
148 }
149 
151  auto lock = std::scoped_lock{ m_branchFilterMutex };
152  return m_branchFilterPassed[ctx.slot()];
153 }
154 
156  auto lock = std::scoped_lock{ m_branchFilterMutex };
157  m_branchFilterPassed[ctx.slot()] = state;
158 }
159 
161 
162 StatusCode Sequencer::append( Gaudi::Algorithm* pAlgorithm ) { return append( pAlgorithm, *subAlgorithms() ); }
163 
165  return append( pAlgorithm, branchAlgorithms() );
166 }
167 
169  Gaudi::Algorithm*& pAlgorithm ) {
170  return createAndAppend( type, name, pAlgorithm, *subAlgorithms() );
171 }
172 
174  Gaudi::Algorithm*& pAlgorithm ) {
175  return createAndAppend( type, name, pAlgorithm, branchAlgorithms() );
176 }
177 
178 StatusCode Sequencer::remove( Gaudi::Algorithm* pAlgorithm ) { return remove( pAlgorithm->name() ); }
179 
180 StatusCode Sequencer::remove( const std::string& algname ) { return remove( algname, *subAlgorithms() ); }
181 
183  return removeFromBranch( pAlgorithm->name() );
184 }
185 
186 StatusCode Sequencer::removeFromBranch( const std::string& algname ) { return remove( algname, branchAlgorithms() ); }
187 
189 
191 
193  // Decode the membership list
195 }
196 
198  // Decode the branch membership list
200 }
201 
207  // Check that the specified algorithm doesn't already exist in the membership list
208  if ( std::find( std::begin( theAlgs ), std::end( theAlgs ), pAlgorithm ) != std::end( theAlgs ) ) {
209  return StatusCode::FAILURE;
210  }
211  theAlgs.push_back( pAlgorithm );
212  pAlgorithm->addRef();
213  return StatusCode::SUCCESS;
214 }
215 
217  Gaudi::Algorithm*& pAlgorithm, std::vector<Gaudi::Algorithm*>& theAlgs ) {
218  auto theAlgMgr = serviceLocator()->service<IAlgManager>( "ApplicationMgr" );
219  if ( !theAlgMgr ) return StatusCode::FAILURE;
220 
221  IAlgorithm* tmp;
222  StatusCode result = theAlgMgr->createAlgorithm( type, algName, tmp );
223  if ( result.isSuccess() ) {
224  try {
225  pAlgorithm = dynamic_cast<Gaudi::Algorithm*>( tmp );
226  theAlgs.push_back( pAlgorithm );
227  } catch ( ... ) {
228  error() << "Unable to create Algorithm " << algName << endmsg;
229  result = StatusCode::FAILURE;
230  }
231  }
232 
233  return result;
234 }
235 
237  std::vector<Gaudi::Algorithm*>& theAlgs, std::vector<bool>& theLogic ) {
238  StatusCode result;
239  auto theAlgMgr = serviceLocator()->service<IAlgManager>( "ApplicationMgr" );
240  if ( theAlgMgr ) {
241  // Clear the existing list of algorithms
242  theAlgs.clear();
243 
244  // Build the list of member algorithms from the contents of the
245  // theNames list.
246  for ( const auto& n : theNames.value() ) {
247 
248  // Parse the name for a syntax of the form:
249  //
250  // <type>/<name>
251  //
252  // Where <name> is the algorithm instance name, and <type> is the
253  // algorithm class type (being a subclass of Algorithm).
255  std::string theName = typeName.name();
256  std::string theType = typeName.type();
257 
258  // Parse the name for a syntax of the form:
259  //
260  // <name>:invert
261  //
262  // Where <name> is the algorithm instance name and ":invert"
263  // indicates that the filter passed logic is inverted.
264  bool isInverted = false;
265  std::string::size_type invert = theName.find_first_of( ":" );
266  // Skip all occurrences of "::" (allow namespaces)
267  while ( std::string::npos != invert && invert < ( theName.size() - 1 ) && theName[invert + 1] == ':' )
268  invert = theName.find_first_of( ":", invert + 2 );
269  if ( std::string::npos != invert ) {
270  if ( theName == theType ) {
271  // This means that we got something like "Type:invert",
272  // so we have to strip the ":invert" from the type too.
273  theType = theType.substr( 0, invert );
274  }
275  theName = theName.substr( 0, invert );
276  isInverted = true;
277  }
278  // Check whether the supplied name corresponds to an existing
279  // Algorithm object.
280  SmartIF<IAlgorithm>& theIAlg = theAlgMgr->algorithm( theName, false );
281  Gaudi::Algorithm* theAlgorithm = nullptr;
283  if ( theIAlg ) {
284  try {
285  theAlgorithm = dynamic_cast<Gaudi::Algorithm*>( theIAlg.get() );
286  } catch ( ... ) {
287  warning() << theName << " is not an Algorithm - Failed dynamic cast" << endmsg;
288  theAlgorithm = nullptr; // release
289  }
290  }
291  if ( theAlgorithm ) {
292 
293  // The specified Algorithm already exists - just append it to the membership list.
294  status = append( theAlgorithm, theAlgs );
295  if ( status.isSuccess() ) {
296  ON_DEBUG debug() << theName << " already exists - appended to member list" << endmsg;
297  } else {
298  warning() << theName << " already exists - append failed!!!" << endmsg;
299  result = StatusCode::FAILURE;
300  }
301  } else {
302 
303  // The specified name doesn't exist - create a new object of the specified type
304  // and append it to the membership list.
305  status = createAndAppend( theType, theName, theAlgorithm, theAlgs );
306  if ( status.isSuccess() ) {
307  ON_DEBUG debug() << theName << " doesn't exist - created and appended to member list" << endmsg;
308  } else {
309  warning() << theName << " doesn't exist - creation failed!!!" << endmsg;
310  result = StatusCode::FAILURE;
311  }
312  }
313  if ( status.isSuccess() ) theLogic.push_back( isInverted );
314  }
315  }
316  // Print membership list
317  if ( result.isSuccess() && theAlgs.size() != 0 ) {
318  info() << "Member list: ";
319  auto ai = theAlgs.begin();
320  auto li = theLogic.begin();
321  for ( ; ai != theAlgs.end(); ++ai, ++li ) {
322 
323  if ( ai != theAlgs.begin() ) info() << ", ";
324  auto alg = *ai;
325  if ( alg->name() == System::typeinfoName( typeid( *alg ) ) )
326  info() << alg->name();
327  else
328  info() << System::typeinfoName( typeid( *alg ) ) << "/" << alg->name();
329 
330  if ( *li ) info() << ":invert";
331  }
332  info() << endmsg;
333  }
334  return result;
335 }
336 
338  const std::vector<bool>& theLogic, Gaudi::Algorithm*& lastAlgorithm,
339  std::size_t first ) const {
341 
342  auto& state = execState( ctx );
343 
344  // Reset the branch filter passed flag
345  setBranchFilterPassed( ctx, false );
346 
347  // Loop over all algorithms calling their execute functions if they
348  // are (a) not disabled, and (b) aren't already executed. Note that
349  // in the latter case the filter state is still examined. Terminate
350  // the loop if an algorithm indicates that it's filter didn't pass.
351  auto size = theAlgs.size();
352  for ( auto i = first; i < size; i++ ) {
353  lastAlgorithm = theAlgs[i];
354  result = executeMember( lastAlgorithm, ctx );
355  if ( result.isSuccess() ) {
356 
357  // Take the filter passed status of this algorithm as my own status.
358  // Note that we take into account inverted logic.
359  bool passed = lastAlgorithm->execState( ctx ).filterPassed();
360  bool isInverted = theLogic[i];
361  if ( isInverted ) passed = !passed;
362  state.setFilterPassed( passed );
363 
364  // The behaviour when the filter fails depends on the StopOverride property.
365  // The default action is to stop processing, but this default can be
366  // overridden by setting the "StopOverride" property to true.
367  if ( !isStopOverride() ) {
368  if ( !passed ) break;
369  }
370  } else {
371  break;
372  }
373  }
374  return result;
375 }
376 
377 StatusCode Sequencer::executeMember( Gaudi::Algorithm* theAlgorithm, const EventContext& context ) const {
379  if ( theAlgorithm->isEnabled() ) {
380  if ( theAlgorithm->execState( context ).state() != AlgExecState::State::Done ) {
381  result = theAlgorithm->sysExecute( context );
382  }
383  }
384  return result;
385 }
386 
389 
390  // Test that the algorithm exists in the member list
391  for ( auto& alg : theAlgs ) {
392  if ( alg->name() == algname ) {
393 
394  // Algorithm with specified name exists in the algorithm list - remove it
395  // THIS ISN'T IMPLEMENTED YET!!!!
396  info() << "Sequencer::remove( ) isn't implemented yet!!!!!" << endmsg;
397  result = StatusCode::SUCCESS;
398  break;
399  }
400  }
401  return result;
402 }
403 
405  auto& theAlgs = *subAlgorithms();
406  if ( theAlgs.empty() ) return os << "CFTrue";
407 
408  os << "seq(";
409  const auto algs_count = theAlgs.size();
410  const auto op = isStopOverride() ? " >> " : " & ";
411  size_t i = 0;
412  while ( i < algs_count ) {
413  if ( i ) os << op;
414  if ( m_isInverted[i] ) os << "~";
415  theAlgs[i]->toControlFlowExpression( os );
416  ++i;
417  }
418  return os << ")";
419 }
Sequencer::start
StatusCode start() override
Sequencer finalization.
Definition: Sequencer.cpp:125
Sequencer::removeFromBranch
StatusCode removeFromBranch(Gaudi::Algorithm *pAlgorithm)
Definition: Sequencer.cpp:182
Sequencer::executeMember
StatusCode executeMember(Gaudi::Algorithm *theAlgorithm, const EventContext &context) const
Execute member algorithm.
Definition: Sequencer.cpp:377
Sequencer::reinitialize
StatusCode reinitialize() override
Sequencer Reinitialization.
Definition: Sequencer.cpp:57
Gaudi::Algorithm::sysExecute
StatusCode sysExecute(const EventContext &ctx) override
The actions to be performed by the algorithm on an event.
Definition: Algorithm.cpp:327
IAlgManager.h
std::string
STL class.
details::size
constexpr auto size(const T &, Args &&...) noexcept
Definition: AnyDataWrapper.h:22
AlgExecState::state
State state() const
Definition: IAlgExecStateSvc.h:42
Gaudi::Algorithm::name
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:528
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:314
GaudiException.h
Gaudi::Algorithm::type
const std::string & type() const override
The type of the algorithm object.
Definition: Algorithm.h:165
std::vector< Gaudi::Algorithm * >
std::find
T find(T... args)
std::string::size
T size(T... args)
Sequencer::m_branchAlgs
std::vector< Gaudi::Algorithm * > m_branchAlgs
Definition: Sequencer.h:235
Sequencer::branchFilterPassed
bool branchFilterPassed(const EventContext &ctx) const
additional interface methods
Definition: Sequencer.cpp:150
Gaudi::Algorithm::serviceLocator
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Algorithm.cpp:572
ON_DEBUG
#define ON_DEBUG
Definition: Sequencer.cpp:24
Sequencer::append
StatusCode append(Gaudi::Algorithm *pAlgorithm)
Append an algorithm to the sequencer.
Definition: Sequencer.cpp:162
Sequencer::m_branchFilterMutex
std::mutex m_branchFilterMutex
Definition: Sequencer.h:238
System::typeinfoName
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:313
IOTest.start
start
Definition: IOTest.py:108
Sequencer::createAndAppendToBranch
StatusCode createAndAppendToBranch(const std::string &type, const std::string &name, Gaudi::Algorithm *&pAlgorithm)
Create a algorithm and append it to the sequencer branch.
Definition: Sequencer.cpp:173
std::vector::clear
T clear(T... args)
Sequencer::m_branchNames
Gaudi::Property< std::vector< std::string > > m_branchNames
Definition: Sequencer.h:224
Sequencer::m_isInverted
std::vector< bool > m_isInverted
Definition: Sequencer.h:234
basic.alg
alg
Definition: basic.py:15
std::vector::push_back
T push_back(T... args)
IAlgManager
Definition: IAlgManager.h:37
Gaudi::Algorithm::isEnabled
bool isEnabled() const override
Is this algorithm enabled or disabled?
Definition: Algorithm.cpp:538
Gaudi::Utils::TypeNameString
Helper class to parse a string of format "type/name".
Definition: TypeNameString.h:20
Sequencer::execute
StatusCode execute(const EventContext &ctx) const override
The actions to be performed by the sequencer on an event.
Definition: Sequencer.cpp:70
TimingHistograms.name
name
Definition: TimingHistograms.py:25
GaudiPython.Pythonizations.ctx
ctx
Definition: Pythonizations.py:588
StatusCode
Definition: StatusCode.h:65
IAlgorithm
Definition: IAlgorithm.h:38
std::ostream
STL class.
Sequencer::appendToBranch
StatusCode appendToBranch(Gaudi::Algorithm *pAlgorithm)
Append an algorithm to the sequencer branch.
Definition: Sequencer.cpp:164
Gaudi::Algorithm::execState
AlgExecState & execState(const EventContext &ctx) const override
reference to AlgExecState of Alg
Definition: Algorithm.cpp:540
Gaudi::Algorithm
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:90
Gaudi::Property::value
const ValueType & value() const
Definition: Property.h:239
Sequencer::remove
StatusCode remove(Gaudi::Algorithm *pAlgorithm)
Remove the specified algorithm from the sequencer.
Definition: Sequencer.cpp:178
SmartIF< IAlgorithm >
Sequencer::m_names
Gaudi::Property< std::vector< std::string > > m_names
Definition: Sequencer.h:217
Sequencer::m_branchFilterPassed
std::map< EventContext::ContextID_t, bool > m_branchFilterPassed
Definition: Sequencer.h:239
Sequencer::createAndAppend
StatusCode createAndAppend(const std::string &type, const std::string &name, Gaudi::Algorithm *&pAlgorithm)
Create a algorithm and append it to the sequencer.
Definition: Sequencer.cpp:168
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
GaudiPluginService.cpluginsvc.n
n
Definition: cpluginsvc.py:235
Sequencer::m_stopOverride
Gaudi::Property< bool > m_stopOverride
Definition: Sequencer.h:232
Stat.h
Sequencer::finalize
StatusCode finalize() override
Sequencer finalization.
Definition: Sequencer.cpp:115
std::string::substr
T substr(T... args)
Sequencer::isStopOverride
virtual bool isStopOverride() const
Has the StopOverride mode been set?
Definition: Sequencer.cpp:160
Sequencer::decodeMemberNames
StatusCode decodeMemberNames()
Decode Member Name list.
Definition: Sequencer.cpp:192
gaudirun.type
type
Definition: gaudirun.py:162
ThreadLocalContext.h
Sequencer::decodeNames
StatusCode decodeNames(Gaudi::Property< std::vector< std::string >> &theNames, std::vector< Gaudi::Algorithm * > &theAlgs, std::vector< bool > &theLogic)
Decode algorithm names, creating or appending algorithms as appropriate.
Definition: Sequencer.cpp:236
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
SmartIF::get
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:86
GaudiDict::typeName
std::string typeName(const std::type_info &typ)
Definition: Dictionary.cpp:31
Sequencer::decodeBranchMemberNames
StatusCode decodeBranchMemberNames()
Decode branch member name list.
Definition: Sequencer.cpp:197
std::begin
T begin(T... args)
Chrono.h
EventContext
Definition: EventContext.h:34
Sequencer::stop
StatusCode stop() override
Sequencer finalization.
Definition: Sequencer.cpp:141
Sequencer::toControlFlowExpression
std::ostream & toControlFlowExpression(std::ostream &os) const override
Produce string represention of the control flow expression.
Definition: Sequencer.cpp:404
Gaudi::Sequence::subAlgorithms
const std::vector< Algorithm * > * subAlgorithms() const
List of sub-algorithms. Returns a pointer to a vector of (sub) Algorithms.
Definition: Sequence.cpp:103
AlgExecState::filterPassed
bool filterPassed() const
Definition: IAlgExecStateSvc.h:41
Sequencer::setBranchFilterPassed
void setBranchFilterPassed(const EventContext &ctx, bool state) const
Set the branch filter passed flag for the last event.
Definition: Sequencer.cpp:155
Sequencer::branchAlgorithms
const std::vector< Gaudi::Algorithm * > & branchAlgorithms() const
List of branch algorithms.
Definition: Sequencer.cpp:188
std::string::find_first_of
T find_first_of(T... args)
std::size_t
std::end
T end(T... args)
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
Sequencer::m_isBranchInverted
std::vector< bool > m_isBranchInverted
Definition: Sequencer.h:236
ISvcLocator.h
compareRootHistos.state
state
Definition: compareRootHistos.py:498
Gaudi::Property
Implementation of property with value of concrete type.
Definition: Property.h:39
Sequencer::initialize
StatusCode initialize() override
Initialization of a sequencer.
Definition: Sequencer.cpp:27
Sequencer.h