The Gaudi Framework  v30r3 (a5ef0a68)
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 
20 Sequencer::Sequencer( const std::string& name, ISvcLocator* pSvcLocator ) : Algorithm( name, pSvcLocator )
21 {
22  // Associate action handlers with the "Members" and "BranchMembers" properties
23  m_names.declareUpdateHandler( [this]( Gaudi::Details::PropertyBase& ) {
24  if ( isInitialized() ) decodeMemberNames().ignore();
25  } );
26  m_branchNames.declareUpdateHandler( [this]( Gaudi::Details::PropertyBase& ) {
27  if ( isInitialized() ) decodeBranchMemberNames().ignore();
28  } );
29 }
30 
32 {
34 
35  result = decodeMemberNames();
36  if ( result.isFailure() ) {
37  error() << "Unable to configure one or more sequencer members " << endmsg;
38  return result;
39  }
40  result = decodeBranchMemberNames();
41  if ( result.isFailure() ) {
42  error() << "Unable to configure one or more branch members " << endmsg;
43  return result;
44  }
45 
46  // Loop over all sub-algorithms
47  for ( auto& alg : *subAlgorithms() ) {
48  result = alg->sysInitialize();
49  if ( result.isFailure() ) {
50  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
51  return result;
52  }
53  }
54 
55  // Loop over all branches
56  for ( auto& alg : branchAlgorithms() ) {
57  result = alg->sysInitialize();
58  if ( result.isFailure() ) {
59  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
60  return result;
61  }
62  }
63 
64  return result;
65 }
66 
68 {
69  // Bypass the loop if this sequencer is disabled
70  if ( isEnabled() ) {
71 
72  // Loop over all members calling their reinitialize functions
73  // if they are not disabled.
74  for ( auto& alg : *subAlgorithms() ) {
75  if ( alg->isEnabled() ) alg->reinitialize().ignore();
76  }
77  // Loop over all branch members calling their reinitialize functions
78  // if they are not disabled.
79  for ( auto& alg : branchAlgorithms() ) {
80  if ( alg->isEnabled() ) {
81  alg->reinitialize().ignore();
82  }
83  }
84  }
85  return StatusCode::SUCCESS;
86 }
87 
89 {
91  ON_DEBUG debug() << name() << " Sequencer::execute( )" << endmsg;
92 
93  // Bypass the loop if this sequencer is disabled or has already been executed
94  if ( isEnabled() && !isExecuted() ) {
95  Algorithm* lastAlgorithm;
96  result = execute( *subAlgorithms(), m_isInverted, lastAlgorithm );
97  if ( result.isSuccess() ) {
98  bool passed = filterPassed();
99  if ( !passed && !isStopOverride() ) {
100 
101  // Filter failed and stop override not set. Execute the
102  // branch if there is one associated with the filter
103  // algorithm that failed. Note that the first member on
104  // the branch is the failing algorithm and so should
105  // be skipped.
106  const auto& theAlgs = branchAlgorithms();
107  if ( !theAlgs.empty() ) {
108  Algorithm* branchAlgorithm = theAlgs[0];
109  if ( lastAlgorithm == branchAlgorithm ) {
110 
111  // Branch specified - Loop over branch members
112  result = execute( branchAlgorithms(), m_isBranchInverted, lastAlgorithm, 1 );
113  if ( result.isSuccess() ) {
114 
115  // The final filter passed state will be set true if either
116  // of the main or branches passed, otherwise false.
117 
118  // Save the branch filter passed state.
120  }
121  }
122  }
123  }
124  }
125 
126  // Prevent multiple executions of this sequencer for the current event
127  setExecuted( true );
128  }
129  return result;
130 }
131 
133 {
134  // Loop over all branch members calling their finalize functions
135  // if they are not disabled. Note that the Algorithm::sysFinalize
136  // function already does this for the main members.
137  for ( auto& alg : branchAlgorithms() ) {
138  if ( alg->sysFinalize().isFailure() ) {
139  error() << "Unable to finalize Algorithm " << alg->name() << endmsg;
140  }
141  }
142  return StatusCode::SUCCESS;
143 }
144 
146 {
148 
149  // Loop over all sub-algorithms
150  for ( auto& alg : *subAlgorithms() ) {
151  result = alg->sysStart();
152  if ( result.isFailure() ) {
153  error() << "Unable to start Algorithm " << alg->name() << endmsg;
154  return result;
155  }
156  }
157 
158  // Loop over all branches
159  for ( auto& alg : branchAlgorithms() ) {
160  result = alg->sysStart();
161  if ( result.isFailure() ) {
162  error() << "Unable to start Algorithm " << alg->name() << endmsg;
163  return result;
164  }
165  }
166 
167  return result;
168 }
169 
171 {
172  // Loop over all branch members calling their finalize functions
173  // if they are not disabled.
174 
175  for ( auto& alg : *subAlgorithms() ) {
176  if ( alg->sysStop().isFailure() ) {
177  error() << "Unable to stop Algorithm " << alg->name() << endmsg;
178  }
179  }
180 
181  for ( auto& alg : branchAlgorithms() ) {
182  if ( alg->sysStop().isFailure() ) {
183  error() << "Unable to stop Algorithm " << alg->name() << endmsg;
184  }
185  }
186  return StatusCode::SUCCESS;
187 }
188 
190 {
192 
193  // Loop over all members calling their resetExecuted functions
194  // if they are not disabled.
195  for ( auto& alg : *subAlgorithms() ) alg->resetExecuted();
196 
197  // Loop over all branch members calling their resetExecuted functions
198  // if they are not disabled.
199  for ( auto& alg : branchAlgorithms() ) alg->resetExecuted();
200 
201  // Reset the branch filter passed flag
202  m_branchFilterPassed = false;
203 }
204 
206 
208 {
210  return StatusCode::SUCCESS;
211 }
212 
213 bool Sequencer::isStopOverride() const { return m_stopOverride.value(); }
214 
215 StatusCode Sequencer::append( Algorithm* pAlgorithm ) { return append( pAlgorithm, *subAlgorithms() ); }
216 
217 StatusCode Sequencer::appendToBranch( Algorithm* pAlgorithm ) { return append( pAlgorithm, branchAlgorithms() ); }
218 
220 {
221  return createAndAppend( type, name, pAlgorithm, *subAlgorithms() );
222 }
223 
225  Algorithm*& pAlgorithm )
226 {
227  return createAndAppend( type, name, pAlgorithm, branchAlgorithms() );
228 }
229 
230 StatusCode Sequencer::remove( Algorithm* pAlgorithm ) { return remove( pAlgorithm->name() ); }
231 
232 StatusCode Sequencer::remove( const std::string& algname ) { return remove( algname, *subAlgorithms() ); }
233 
234 StatusCode Sequencer::removeFromBranch( Algorithm* pAlgorithm ) { return removeFromBranch( pAlgorithm->name() ); }
235 
236 StatusCode Sequencer::removeFromBranch( const std::string& algname ) { return remove( algname, branchAlgorithms() ); }
237 
239 
241 
243 {
244  // Decode the membership list
246 }
247 
249 {
250  // Decode the branch membership list
252 }
253 
259 {
260  // Check that the specified algorithm doesn't already exist in the membership list
261  if ( std::find( std::begin( theAlgs ), std::end( theAlgs ), pAlgorithm ) != std::end( theAlgs ) ) {
262  return StatusCode::FAILURE;
263  }
264  theAlgs.push_back( pAlgorithm );
265  pAlgorithm->addRef();
266  return StatusCode::SUCCESS;
267 }
268 
270  std::vector<Algorithm*>& theAlgs )
271 {
272  auto theAlgMgr = serviceLocator()->service<IAlgManager>( "ApplicationMgr" );
273  if ( !theAlgMgr ) return StatusCode::FAILURE;
274 
275  IAlgorithm* tmp;
276  StatusCode result = theAlgMgr->createAlgorithm( type, algName, tmp );
277  if ( result.isSuccess() ) {
278  try {
279  pAlgorithm = dynamic_cast<Algorithm*>( tmp );
280  theAlgs.push_back( pAlgorithm );
281  } catch ( ... ) {
282  error() << "Unable to create Algorithm " << algName << endmsg;
283  result = StatusCode::FAILURE;
284  }
285  }
286 
287  return result;
288 }
289 
291  std::vector<Algorithm*>& theAlgs, std::vector<bool>& theLogic )
292 {
293  StatusCode result;
294  auto theAlgMgr = serviceLocator()->service<IAlgManager>( "ApplicationMgr" );
295  if ( theAlgMgr ) {
296  // Clear the existing list of algorithms
297  theAlgs.clear();
298 
299  // Build the list of member algorithms from the contents of the
300  // theNames list.
301  for ( const auto& n : theNames.value() ) {
302 
303  // Parse the name for a syntax of the form:
304  //
305  // <type>/<name>
306  //
307  // Where <name> is the algorithm instance name, and <type> is the
308  // algorithm class type (being a subclass of Algorithm).
310  std::string theName = typeName.name();
311  std::string theType = typeName.type();
312 
313  // Parse the name for a syntax of the form:
314  //
315  // <name>:invert
316  //
317  // Where <name> is the algorithm instance name and ":invert"
318  // indicates that the filter passed logic is inverted.
319  bool isInverted = false;
320  std::string::size_type invert = theName.find_first_of( ":" );
321  // Skip all occurrences of "::" (allow namespaces)
322  while ( std::string::npos != invert && invert < ( theName.size() - 1 ) && theName[invert + 1] == ':' )
323  invert = theName.find_first_of( ":", invert + 2 );
324  if ( std::string::npos != invert ) {
325  if ( theName == theType ) {
326  // This means that we got something like "Type:invert",
327  // so we have to strip the ":invert" from the type too.
328  theType = theType.substr( 0, invert );
329  }
330  theName = theName.substr( 0, invert );
331  isInverted = true;
332  }
333  // Check whether the supplied name corresponds to an existing
334  // Algorithm object.
335  SmartIF<IAlgorithm>& theIAlg = theAlgMgr->algorithm( theName, false );
336  Algorithm* theAlgorithm = nullptr;
338  if ( theIAlg ) {
339  try {
340  theAlgorithm = dynamic_cast<Algorithm*>( theIAlg.get() );
341  } catch ( ... ) {
342  warning() << theName << " is not an Algorithm - Failed dynamic cast" << endmsg;
343  theAlgorithm = nullptr; // release
344  }
345  }
346  if ( theAlgorithm ) {
347 
348  // The specified Algorithm already exists - just append it to the membership list.
349  status = append( theAlgorithm, theAlgs );
350  if ( status.isSuccess() ) {
351  ON_DEBUG debug() << theName << " already exists - appended to member list" << endmsg;
352  } else {
353  warning() << theName << " already exists - append failed!!!" << endmsg;
354  result = StatusCode::FAILURE;
355  }
356  } else {
357 
358  // The specified name doesn't exist - create a new object of the specified type
359  // and append it to the membership list.
360  status = createAndAppend( theType, theName, theAlgorithm, theAlgs );
361  if ( status.isSuccess() ) {
362  ON_DEBUG debug() << theName << " doesn't exist - created and appended to member list" << endmsg;
363  } else {
364  warning() << theName << " doesn't exist - creation failed!!!" << endmsg;
365  result = StatusCode::FAILURE;
366  }
367  }
368  if ( status.isSuccess() ) theLogic.push_back( isInverted );
369  }
370  }
371  // Print membership list
372  if ( result.isSuccess() && theAlgs.size() != 0 ) {
373  info() << "Member list: ";
374  auto ai = theAlgs.begin();
375  auto li = theLogic.begin();
376  for ( ; ai != theAlgs.end(); ++ai, ++li ) {
377 
378  if ( ai != theAlgs.begin() ) info() << ", ";
379  auto alg = *ai;
380  if ( alg->name() == System::typeinfoName( typeid( *alg ) ) )
381  info() << alg->name();
382  else
383  info() << System::typeinfoName( typeid( *alg ) ) << "/" << alg->name();
384 
385  if ( *li ) info() << ":invert";
386  }
387  info() << endmsg;
388  }
389  return result;
390 }
391 
393  Algorithm*& lastAlgorithm, unsigned int first )
394 {
396 
397  // Loop over all algorithms calling their execute functions if they
398  // are (a) not disabled, and (b) aren't already executed. Note that
399  // in the latter case the filter state is still examined. Terminate
400  // the loop if an algorithm indicates that it's filter didn't pass.
401  unsigned int size = theAlgs.size();
402  for ( unsigned int i = first; i < size; i++ ) {
403  lastAlgorithm = theAlgs[i];
404  result = executeMember( lastAlgorithm );
405  if ( result.isSuccess() ) {
406 
407  // Take the filter passed status of this algorithm as my own status.
408  // Note that we take into account inverted logic.
409  bool passed = lastAlgorithm->filterPassed();
410  bool isInverted = theLogic[i];
411  if ( isInverted ) passed = !passed;
412  setFilterPassed( passed );
413 
414  // The behaviour when the filter fails depends on the StopOverride property.
415  // The default action is to stop processing, but this default can be
416  // overridden by setting the "StopOverride" property to true.
417  if ( !isStopOverride() ) {
418  if ( !passed ) break;
419  }
420  } else {
421  break;
422  }
423  }
424  return result;
425 }
426 
428 {
430  if ( theAlgorithm->isEnabled() ) {
431  if ( !theAlgorithm->isExecuted() ) {
432  result = theAlgorithm->sysExecute( getContext() );
433  }
434  }
435  return result;
436 }
437 
439 {
441 
442  // Test that the algorithm exists in the member list
443  for ( auto& alg : theAlgs ) {
444  if ( alg->name() == algname ) {
445 
446  // Algorithm with specified name exists in the algorithm list - remove it
447  // THIS ISN'T IMPLEMENTED YET!!!!
448  info() << "Sequencer::remove( ) isn't implemented yet!!!!!" << endmsg;
449  result = StatusCode::SUCCESS;
450  break;
451  }
452  }
453  return result;
454 }
455 
457 {
458  auto& theAlgs = *subAlgorithms();
459  if ( theAlgs.empty() ) return os << "CFTrue";
460 
461  os << "seq(";
462  const auto algs_count = theAlgs.size();
463  const auto op = isStopOverride() ? " >> " : " & ";
464  size_t i = 0;
465  while ( i < algs_count ) {
466  if ( i ) os << op;
467  if ( m_isInverted[i] ) os << "~";
468  theAlgs[i]->toControlFlowExpression( os );
469  ++i;
470  }
471  return os << ")";
472 }
void resetExecuted() override
Reset the executed state of the Algorithm for the duration of the current event.
Definition: Algorithm.cpp:785
virtual bool isStopOverride() const
Has the StopOverride mode been set?
Definition: Sequencer.cpp:213
constexpr static const auto FAILURE
Definition: StatusCode.h:88
StatusCode append(Algorithm *pAlgorithm)
Append an algorithm to the sequencer.
Definition: Sequencer.cpp:215
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:765
void setFilterPassed(bool state) const override
Set the filter passed flag to the specified state.
Definition: Algorithm.cpp:791
StatusCode remove(Algorithm *pAlgorithm)
Remove the specified algorithm from the sequencer.
Definition: Sequencer.cpp:230
Implementation of property with value of concrete type.
Definition: Property.h:381
StatusCode removeFromBranch(Algorithm *pAlgorithm)
Definition: Sequencer.cpp:234
bool isExecuted() const override
Has this algorithm been executed since the last reset?
Definition: Algorithm.cpp:775
Gaudi::Property< std::vector< std::string > > m_branchNames
Definition: Sequencer.h:218
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
Sequencer(const std::string &name, ISvcLocator *svcloc)
Constructor(s)
Definition: Sequencer.cpp:20
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:205
StatusCode stop() override
Sequencer finalization.
Definition: Sequencer.cpp:170
bool m_branchFilterPassed
Definition: Sequencer.h:225
T end(T...args)
StatusCode reinitialize() override
Sequencer Reinitialization.
Definition: Sequencer.cpp:67
const std::vector< Algorithm * > & branchAlgorithms() const
List of branch algorithms.
Definition: Sequencer.cpp:238
StatusCode executeMember(Algorithm *theAlgorithm)
Execute member algorithm.
Definition: Sequencer.cpp:427
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:248
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:207
Gaudi::Property< bool > m_stopOverride
Definition: Sequencer.h:219
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:787
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:88
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
StatusCode decodeMemberNames()
Decode Member Name list.
Definition: Sequencer.cpp:242
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:224
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:436
Gaudi::Property< std::vector< std::string > > m_names
Definition: Sequencer.h:217
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:456
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Definition: Property.h:32
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:834
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:801
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:78
T find(T...args)
T size(T...args)
std::vector< Algorithm * > m_branchAlgs
Definition: Sequencer.h:222
#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:221
StatusCode createAndAppend(const std::string &type, const std::string &name, Algorithm *&pAlgorithm)
Create a algorithm and append it to the sequencer.
Definition: Sequencer.cpp:219
T begin(T...args)
bool isInitialized() const override
Has the Algorithm already been initialized?
Definition: Algorithm.h:501
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:789
StatusCode appendToBranch(Algorithm *pAlgorithm)
Append an algorithm to the sequencer branch.
Definition: Sequencer.cpp:217
void setExecuted(bool state) const override
Set the executed flag to the specified state.
Definition: Algorithm.cpp:780
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:290
StatusCode finalize() override
Sequencer finalization.
Definition: Sequencer.cpp:132
StatusCode initialize() override
Initialization of a sequencer.
Definition: Sequencer.cpp:31
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:166
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:189
StatusCode sysExecute(const EventContext &ctx) override
The actions to be performed by the algorithm on an event.
Definition: Algorithm.cpp:545
std::vector< bool > m_isBranchInverted
Definition: Sequencer.h:223
StatusCode start() override
Sequencer finalization.
Definition: Sequencer.cpp:145