The Gaudi Framework  v30r4 (9b837755)
Sequencer.cpp
Go to the documentation of this file.
1 // Sequencer class
2 // Implements:
3 // 1) Common functionality of IInterface
4 // 2) Default behavior for the IAlgorithm
5 
6 #include "GaudiAlg/Sequencer.h"
7 
8 #include "GaudiKernel/Chrono.h"
12 #include "GaudiKernel/Stat.h"
13 
14 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
15 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
16 
18 {
20 
21  result = decodeMemberNames();
22  if ( result.isFailure() ) {
23  error() << "Unable to configure one or more sequencer members " << endmsg;
24  return result;
25  }
26  result = decodeBranchMemberNames();
27  if ( result.isFailure() ) {
28  error() << "Unable to configure one or more branch members " << endmsg;
29  return result;
30  }
31 
32  // Loop over all sub-algorithms
33  for ( auto& alg : *subAlgorithms() ) {
34  result = alg->sysInitialize();
35  if ( result.isFailure() ) {
36  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
37  return result;
38  }
39  }
40 
41  // Loop over all branches
42  for ( auto& alg : branchAlgorithms() ) {
43  result = alg->sysInitialize();
44  if ( result.isFailure() ) {
45  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
46  return result;
47  }
48  }
49 
50  return result;
51 }
52 
54 {
55  // Bypass the loop if this sequencer is disabled
56  if ( isEnabled() ) {
57 
58  // Loop over all members calling their reinitialize functions
59  // if they are not disabled.
60  for ( auto& alg : *subAlgorithms() ) {
61  if ( alg->isEnabled() ) alg->reinitialize().ignore();
62  }
63  // Loop over all branch members calling their reinitialize functions
64  // if they are not disabled.
65  for ( auto& alg : branchAlgorithms() ) {
66  if ( alg->isEnabled() ) {
67  alg->reinitialize().ignore();
68  }
69  }
70  }
71  return StatusCode::SUCCESS;
72 }
73 
75 {
77  ON_DEBUG debug() << name() << " Sequencer::execute( )" << endmsg;
78 
79  // Bypass the loop if this sequencer is disabled or has already been executed
80  if ( isEnabled() && !isExecuted() ) {
81  Algorithm* lastAlgorithm;
82  result = execute( *subAlgorithms(), m_isInverted, lastAlgorithm );
83  if ( result.isSuccess() ) {
84  bool passed = filterPassed();
85  if ( !passed && !isStopOverride() ) {
86 
87  // Filter failed and stop override not set. Execute the
88  // branch if there is one associated with the filter
89  // algorithm that failed. Note that the first member on
90  // the branch is the failing algorithm and so should
91  // be skipped.
92  const auto& theAlgs = branchAlgorithms();
93  if ( !theAlgs.empty() ) {
94  Algorithm* branchAlgorithm = theAlgs[0];
95  if ( lastAlgorithm == branchAlgorithm ) {
96 
97  // Branch specified - Loop over branch members
98  result = execute( branchAlgorithms(), m_isBranchInverted, lastAlgorithm, 1 );
99  if ( result.isSuccess() ) {
100 
101  // The final filter passed state will be set true if either
102  // of the main or branches passed, otherwise false.
103 
104  // Save the branch filter passed state.
106  }
107  }
108  }
109  }
110  }
111 
112  // Prevent multiple executions of this sequencer for the current event
113  setExecuted( true );
114  }
115  return result;
116 }
117 
119 {
120  // Loop over all branch members calling their finalize functions
121  // if they are not disabled. Note that the Algorithm::sysFinalize
122  // function already does this for the main members.
123  for ( auto& alg : branchAlgorithms() ) {
124  if ( alg->sysFinalize().isFailure() ) {
125  error() << "Unable to finalize Algorithm " << alg->name() << endmsg;
126  }
127  }
128  return StatusCode::SUCCESS;
129 }
130 
132 {
134 
135  // Loop over all sub-algorithms
136  for ( auto& alg : *subAlgorithms() ) {
137  result = alg->sysStart();
138  if ( result.isFailure() ) {
139  error() << "Unable to start Algorithm " << alg->name() << endmsg;
140  return result;
141  }
142  }
143 
144  // Loop over all branches
145  for ( auto& alg : branchAlgorithms() ) {
146  result = alg->sysStart();
147  if ( result.isFailure() ) {
148  error() << "Unable to start Algorithm " << alg->name() << endmsg;
149  return result;
150  }
151  }
152 
153  return result;
154 }
155 
157 {
158  // Loop over all branch members calling their finalize functions
159  // if they are not disabled.
160 
161  for ( auto& alg : *subAlgorithms() ) {
162  if ( alg->sysStop().isFailure() ) {
163  error() << "Unable to stop Algorithm " << alg->name() << endmsg;
164  }
165  }
166 
167  for ( auto& alg : branchAlgorithms() ) {
168  if ( alg->sysStop().isFailure() ) {
169  error() << "Unable to stop Algorithm " << alg->name() << endmsg;
170  }
171  }
172  return StatusCode::SUCCESS;
173 }
174 
176 {
178 
179  // Loop over all members calling their resetExecuted functions
180  // if they are not disabled.
181  for ( auto& alg : *subAlgorithms() ) alg->resetExecuted();
182 
183  // Loop over all branch members calling their resetExecuted functions
184  // if they are not disabled.
185  for ( auto& alg : branchAlgorithms() ) alg->resetExecuted();
186 
187  // Reset the branch filter passed flag
188  m_branchFilterPassed = false;
189 }
190 
192 
194 {
196  return StatusCode::SUCCESS;
197 }
198 
199 bool Sequencer::isStopOverride() const { return m_stopOverride.value(); }
200 
201 StatusCode Sequencer::append( Algorithm* pAlgorithm ) { return append( pAlgorithm, *subAlgorithms() ); }
202 
203 StatusCode Sequencer::appendToBranch( Algorithm* pAlgorithm ) { return append( pAlgorithm, branchAlgorithms() ); }
204 
206 {
207  return createAndAppend( type, name, pAlgorithm, *subAlgorithms() );
208 }
209 
211  Algorithm*& pAlgorithm )
212 {
213  return createAndAppend( type, name, pAlgorithm, branchAlgorithms() );
214 }
215 
216 StatusCode Sequencer::remove( Algorithm* pAlgorithm ) { return remove( pAlgorithm->name() ); }
217 
218 StatusCode Sequencer::remove( const std::string& algname ) { return remove( algname, *subAlgorithms() ); }
219 
220 StatusCode Sequencer::removeFromBranch( Algorithm* pAlgorithm ) { return removeFromBranch( pAlgorithm->name() ); }
221 
222 StatusCode Sequencer::removeFromBranch( const std::string& algname ) { return remove( algname, branchAlgorithms() ); }
223 
225 
227 
229 {
230  // Decode the membership list
232 }
233 
235 {
236  // Decode the branch membership list
238 }
239 
245 {
246  // Check that the specified algorithm doesn't already exist in the membership list
247  if ( std::find( std::begin( theAlgs ), std::end( theAlgs ), pAlgorithm ) != std::end( theAlgs ) ) {
248  return StatusCode::FAILURE;
249  }
250  theAlgs.push_back( pAlgorithm );
251  pAlgorithm->addRef();
252  return StatusCode::SUCCESS;
253 }
254 
256  std::vector<Algorithm*>& theAlgs )
257 {
258  auto theAlgMgr = serviceLocator()->service<IAlgManager>( "ApplicationMgr" );
259  if ( !theAlgMgr ) return StatusCode::FAILURE;
260 
261  IAlgorithm* tmp;
262  StatusCode result = theAlgMgr->createAlgorithm( type, algName, tmp );
263  if ( result.isSuccess() ) {
264  try {
265  pAlgorithm = dynamic_cast<Algorithm*>( tmp );
266  theAlgs.push_back( pAlgorithm );
267  } catch ( ... ) {
268  error() << "Unable to create Algorithm " << algName << endmsg;
269  result = StatusCode::FAILURE;
270  }
271  }
272 
273  return result;
274 }
275 
277  std::vector<Algorithm*>& theAlgs, std::vector<bool>& theLogic )
278 {
279  StatusCode result;
280  auto theAlgMgr = serviceLocator()->service<IAlgManager>( "ApplicationMgr" );
281  if ( theAlgMgr ) {
282  // Clear the existing list of algorithms
283  theAlgs.clear();
284 
285  // Build the list of member algorithms from the contents of the
286  // theNames list.
287  for ( const auto& n : theNames.value() ) {
288 
289  // Parse the name for a syntax of the form:
290  //
291  // <type>/<name>
292  //
293  // Where <name> is the algorithm instance name, and <type> is the
294  // algorithm class type (being a subclass of Algorithm).
296  std::string theName = typeName.name();
297  std::string theType = typeName.type();
298 
299  // Parse the name for a syntax of the form:
300  //
301  // <name>:invert
302  //
303  // Where <name> is the algorithm instance name and ":invert"
304  // indicates that the filter passed logic is inverted.
305  bool isInverted = false;
306  std::string::size_type invert = theName.find_first_of( ":" );
307  // Skip all occurrences of "::" (allow namespaces)
308  while ( std::string::npos != invert && invert < ( theName.size() - 1 ) && theName[invert + 1] == ':' )
309  invert = theName.find_first_of( ":", invert + 2 );
310  if ( std::string::npos != invert ) {
311  if ( theName == theType ) {
312  // This means that we got something like "Type:invert",
313  // so we have to strip the ":invert" from the type too.
314  theType = theType.substr( 0, invert );
315  }
316  theName = theName.substr( 0, invert );
317  isInverted = true;
318  }
319  // Check whether the supplied name corresponds to an existing
320  // Algorithm object.
321  SmartIF<IAlgorithm>& theIAlg = theAlgMgr->algorithm( theName, false );
322  Algorithm* theAlgorithm = nullptr;
324  if ( theIAlg ) {
325  try {
326  theAlgorithm = dynamic_cast<Algorithm*>( theIAlg.get() );
327  } catch ( ... ) {
328  warning() << theName << " is not an Algorithm - Failed dynamic cast" << endmsg;
329  theAlgorithm = nullptr; // release
330  }
331  }
332  if ( theAlgorithm ) {
333 
334  // The specified Algorithm already exists - just append it to the membership list.
335  status = append( theAlgorithm, theAlgs );
336  if ( status.isSuccess() ) {
337  ON_DEBUG debug() << theName << " already exists - appended to member list" << endmsg;
338  } else {
339  warning() << theName << " already exists - append failed!!!" << endmsg;
340  result = StatusCode::FAILURE;
341  }
342  } else {
343 
344  // The specified name doesn't exist - create a new object of the specified type
345  // and append it to the membership list.
346  status = createAndAppend( theType, theName, theAlgorithm, theAlgs );
347  if ( status.isSuccess() ) {
348  ON_DEBUG debug() << theName << " doesn't exist - created and appended to member list" << endmsg;
349  } else {
350  warning() << theName << " doesn't exist - creation failed!!!" << endmsg;
351  result = StatusCode::FAILURE;
352  }
353  }
354  if ( status.isSuccess() ) theLogic.push_back( isInverted );
355  }
356  }
357  // Print membership list
358  if ( result.isSuccess() && theAlgs.size() != 0 ) {
359  info() << "Member list: ";
360  auto ai = theAlgs.begin();
361  auto li = theLogic.begin();
362  for ( ; ai != theAlgs.end(); ++ai, ++li ) {
363 
364  if ( ai != theAlgs.begin() ) info() << ", ";
365  auto alg = *ai;
366  if ( alg->name() == System::typeinfoName( typeid( *alg ) ) )
367  info() << alg->name();
368  else
369  info() << System::typeinfoName( typeid( *alg ) ) << "/" << alg->name();
370 
371  if ( *li ) info() << ":invert";
372  }
373  info() << endmsg;
374  }
375  return result;
376 }
377 
379  Algorithm*& lastAlgorithm, unsigned int first )
380 {
382 
383  // Loop over all algorithms calling their execute functions if they
384  // are (a) not disabled, and (b) aren't already executed. Note that
385  // in the latter case the filter state is still examined. Terminate
386  // the loop if an algorithm indicates that it's filter didn't pass.
387  unsigned int size = theAlgs.size();
388  for ( unsigned int i = first; i < size; i++ ) {
389  lastAlgorithm = theAlgs[i];
390  result = executeMember( lastAlgorithm );
391  if ( result.isSuccess() ) {
392 
393  // Take the filter passed status of this algorithm as my own status.
394  // Note that we take into account inverted logic.
395  bool passed = lastAlgorithm->filterPassed();
396  bool isInverted = theLogic[i];
397  if ( isInverted ) passed = !passed;
398  setFilterPassed( passed );
399 
400  // The behaviour when the filter fails depends on the StopOverride property.
401  // The default action is to stop processing, but this default can be
402  // overridden by setting the "StopOverride" property to true.
403  if ( !isStopOverride() ) {
404  if ( !passed ) break;
405  }
406  } else {
407  break;
408  }
409  }
410  return result;
411 }
412 
414 {
416  if ( theAlgorithm->isEnabled() ) {
417  if ( !theAlgorithm->isExecuted() ) {
418  result = theAlgorithm->sysExecute( getContext() );
419  }
420  }
421  return result;
422 }
423 
425 {
427 
428  // Test that the algorithm exists in the member list
429  for ( auto& alg : theAlgs ) {
430  if ( alg->name() == algname ) {
431 
432  // Algorithm with specified name exists in the algorithm list - remove it
433  // THIS ISN'T IMPLEMENTED YET!!!!
434  info() << "Sequencer::remove( ) isn't implemented yet!!!!!" << endmsg;
435  result = StatusCode::SUCCESS;
436  break;
437  }
438  }
439  return result;
440 }
441 
443 {
444  auto& theAlgs = *subAlgorithms();
445  if ( theAlgs.empty() ) return os << "CFTrue";
446 
447  os << "seq(";
448  const auto algs_count = theAlgs.size();
449  const auto op = isStopOverride() ? " >> " : " & ";
450  size_t i = 0;
451  while ( i < algs_count ) {
452  if ( i ) os << op;
453  if ( m_isInverted[i] ) os << "~";
454  theAlgs[i]->toControlFlowExpression( os );
455  ++i;
456  }
457  return os << ")";
458 }
void resetExecuted() override
Reset the executed state of the Algorithm for the duration of the current event.
Definition: Algorithm.cpp:767
virtual bool isStopOverride() const
Has the StopOverride mode been set?
Definition: Sequencer.cpp:199
constexpr static const auto FAILURE
Definition: StatusCode.h:88
StatusCode append(Algorithm *pAlgorithm)
Append an algorithm to the sequencer.
Definition: Sequencer.cpp:201
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:747
void setFilterPassed(bool state) const override
Set the filter passed flag to the specified state.
Definition: Algorithm.cpp:773
StatusCode remove(Algorithm *pAlgorithm)
Remove the specified algorithm from the sequencer.
Definition: Sequencer.cpp:216
Implementation of property with value of concrete type.
Definition: Property.h:383
StatusCode removeFromBranch(Algorithm *pAlgorithm)
Definition: Sequencer.cpp:220
bool isExecuted() const override
Has this algorithm been executed since the last reset?
Definition: Algorithm.cpp:757
Gaudi::Property< std::vector< std::string > > m_branchNames
Definition: Sequencer.h:222
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:332
bool isSuccess() const
Definition: StatusCode.h:287
The IAlgManager is the interface implemented by the Algorithm Factory in the Application Manager to s...
Definition: IAlgManager.h:27
virtual bool branchFilterPassed() const
Was the branch filter passed for the last event?
Definition: Sequencer.cpp:191
StatusCode stop() override
Sequencer finalization.
Definition: Sequencer.cpp:156
bool m_branchFilterPassed
Definition: Sequencer.h:236
T end(T...args)
StatusCode reinitialize() override
Sequencer Reinitialization.
Definition: Sequencer.cpp:53
const std::vector< Algorithm * > & branchAlgorithms() const
List of branch algorithms.
Definition: Sequencer.cpp:224
StatusCode executeMember(Algorithm *theAlgorithm)
Execute member algorithm.
Definition: Sequencer.cpp:413
bool isFailure() const
Definition: StatusCode.h:139
constexpr auto size(const C &c) noexcept(noexcept(c.size())) -> decltype(c.size())
StatusCode decodeBranchMemberNames()
Decode branch member name list.
Definition: Sequencer.cpp:234
STL class.
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:82
virtual StatusCode setBranchFilterPassed(bool state)
Set the branch filter passed flag for the last event.
Definition: Sequencer.cpp:193
Gaudi::Property< bool > m_stopOverride
Definition: Sequencer.h:230
StatusCode service(const Gaudi::Utils::TypeNameString &name, T *&svc, bool createIf=true)
Templated method to access a service by name.
Definition: ISvcLocator.h:79
T push_back(T...args)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
bool isEnabled() const override
Is this algorithm enabled or disabled?
Definition: Algorithm.cpp:769
Helper class to parse a string of format "type/name".
StatusCode execute() override
The actions to be performed by the sequencer on an event.
Definition: Sequencer.cpp:74
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
StatusCode decodeMemberNames()
Decode Member Name list.
Definition: Sequencer.cpp:228
StatusCode createAndAppendToBranch(const std::string &type, const std::string &name, Algorithm *&pAlgorithm)
Create a algorithm and append it to the sequencer branch.
Definition: Sequencer.cpp:210
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:51
const EventContext & getContext() const override
get the context
Definition: Algorithm.h:437
Gaudi::Property< std::vector< std::string > > m_names
Definition: Sequencer.h:214
T find_first_of(T...args)
std::ostream & toControlFlowExpression(std::ostream &os) const override
Produce string represention of the control flow expression.
Definition: Sequencer.cpp:442
T clear(T...args)
The IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:28
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Algorithm.cpp:816
constexpr static const auto SUCCESS
Definition: StatusCode.h:87
const std::vector< Algorithm * > * subAlgorithms() const
List of sub-algorithms. Returns a pointer to a vector of (sub) Algorithms.
Definition: Algorithm.cpp:783
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:79
T find(T...args)
T size(T...args)
std::vector< Algorithm * > m_branchAlgs
Definition: Sequencer.h:233
#define ON_DEBUG
Definition: Sequencer.cpp:14
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
std::vector< bool > m_isInverted
Definition: Sequencer.h:232
StatusCode createAndAppend(const std::string &type, const std::string &name, Algorithm *&pAlgorithm)
Create a algorithm and append it to the sequencer.
Definition: Sequencer.cpp:205
T begin(T...args)
const std::string & type() const
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:165
bool filterPassed() const override
Did this algorithm pass or fail its filter criterion for the last event?
Definition: Algorithm.cpp:771
StatusCode appendToBranch(Algorithm *pAlgorithm)
Append an algorithm to the sequencer branch.
Definition: Sequencer.cpp:203
void setExecuted(bool state) const override
Set the executed flag to the specified state.
Definition: Algorithm.cpp:762
T substr(T...args)
StatusCode decodeNames(Gaudi::Property< std::vector< std::string >> &theNames, std::vector< Algorithm * > &theAlgs, std::vector< bool > &theLogic)
Decode algorithm names, creating or appending algorithms as appropriate.
Definition: Sequencer.cpp:276
StatusCode finalize() override
Sequencer finalization.
Definition: Sequencer.cpp:118
StatusCode initialize() override
Initialization of a sequencer.
Definition: Sequencer.cpp:17
const std::string & name() const
std::string typeName(const std::type_info &typ)
Definition: Dictionary.cpp:23
const std::string & type() const override
The type of the algorithm object.
Definition: Algorithm.h:167
STL class.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
void resetExecuted() override
Reset the Sequencer executed state for the current event.
Definition: Sequencer.cpp:175
StatusCode sysExecute(const EventContext &ctx) override
The actions to be performed by the algorithm on an event.
Definition: Algorithm.cpp:528
std::vector< bool > m_isBranchInverted
Definition: Sequencer.h:234
StatusCode start() override
Sequencer finalization.
Definition: Sequencer.cpp:131