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 
10 #include "GaudiKernel/Chrono.h"
11 #include "GaudiKernel/Stat.h"
13 
14 #define ON_DEBUG if (msgLevel(MSG::DEBUG))
15 #define ON_VERBOSE if (msgLevel(MSG::VERBOSE))
16 
21 : Algorithm( name, pSvcLocator )
22 {
23  // Declare Sequencer properties with their defaults
24  declareProperty( "Members", m_names );
25  declareProperty( "BranchMembers", m_branchNames );
26  declareProperty( "StopOverride", m_stopOverride=false );
27 
28  // Associate action handlers with the "Members" and "BranchMembers" properties
31 
32 }
33 
36 {
38 
39 
40  result = decodeMemberNames();
41  if( result.isFailure() ) {
42  error() << "Unable to configure one or more sequencer members " << endmsg;
43  return result;
44  }
45  result = decodeBranchMemberNames();
46  if( result.isFailure() ) {
47  error() << "Unable to configure one or more branch members " << endmsg;
48  return result;
49  }
50 
51  // Loop over all sub-algorithms
52  for (auto& alg : *subAlgorithms() ) {
53  result = alg->sysInitialize( );
54  if( result.isFailure() ) {
55  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
56  return result;
57  }
58  }
59 
60  // Loop over all branches
61  for (auto& alg : branchAlgorithms() ) {
62  result = alg->sysInitialize( );
63  if( result.isFailure() ) {
64  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
65  return result;
66  }
67  }
68 
69  return result;
70 }
71 
74 {
75  // Bypass the loop if this sequencer is disabled
76  if ( isEnabled( ) ) {
77 
78  // Loop over all members calling their reinitialize functions
79  // if they are not disabled.
80  for (auto& alg : *subAlgorithms() ) {
81  if ( alg->isEnabled( ) ) alg->reinitialize( ).ignore();
82  }
83  // Loop over all branch members calling their reinitialize functions
84  // if they are not disabled.
85  for (auto& alg : branchAlgorithms() ) {
86  if ( alg->isEnabled( ) ) {
87  alg->reinitialize( ).ignore();
88  }
89  }
90 
91  }
92  return StatusCode::SUCCESS;
93 }
94 
97 {
99  ON_DEBUG debug() << name( ) << " Sequencer::execute( )" << endmsg;
100 
101  // Bypass the loop if this sequencer is disabled or has already been executed
102  if ( isEnabled( ) && ! isExecuted( ) ) {
103  Algorithm* lastAlgorithm;
104  result = execute( *subAlgorithms( ), m_isInverted, lastAlgorithm );
105  if ( result.isSuccess( ) ) {
106  bool passed = filterPassed( );
107  if ( ! passed && ! isStopOverride( ) ) {
108 
109  // Filter failed and stop override not set. Execute the
110  // branch if there is one associated with the filter
111  // algorithm that failed. Note that the first member on
112  // the branch is the failing algorithm and so should
113  // be skipped.
114  const auto& theAlgs = branchAlgorithms( );
115  if ( !theAlgs.empty( ) ) {
116  Algorithm* branchAlgorithm = theAlgs[0];
117  if ( lastAlgorithm == branchAlgorithm ) {
118 
119  // Branch specified - Loop over branch members
120  result = execute( branchAlgorithms( ),
122  lastAlgorithm, 1 );
123  if ( result.isSuccess( ) ) {
124 
125  // The final filter passed state will be set true if either
126  // of the main or branches passed, otherwise false.
127 
128  // Save the branch filter passed state.
130  }
131  }
132  }
133  }
134  }
135 
136  // Prevent multiple executions of this sequencer for the current event
137  setExecuted( true );
138  }
139  return result;
140 }
141 
144 {
145  // Loop over all branch members calling their finalize functions
146  // if they are not disabled. Note that the Algorithm::sysFinalize
147  // function already does this for the main members.
148  for (auto & alg : branchAlgorithms() ) {
149  if (alg->sysFinalize( ).isFailure()) {
150  error() << "Unable to finalize Algorithm "
151  << alg->name() << endmsg;
152  }
153  }
154  return StatusCode::SUCCESS;
155 }
156 
159 {
161 
162 
163  // Loop over all sub-algorithms
164  for (auto& alg : *subAlgorithms() ) {
165  result = alg->sysStart( );
166  if( result.isFailure() ) {
167  error() << "Unable to start Algorithm " << alg->name() << endmsg;
168  return result;
169  }
170  }
171 
172  // Loop over all branches
173  for (auto& alg : branchAlgorithms() ) {
174  result = alg->sysStart( );
175  if( result.isFailure() ) {
176  error() << "Unable to start Algorithm " << alg->name() << endmsg;
177  return result;
178  }
179  }
180 
181  return result;
182 }
183 
186 {
187  // Loop over all branch members calling their finalize functions
188  // if they are not disabled.
189 
190  for (auto& alg : *subAlgorithms() ) {
191  if (alg->sysStop( ).isFailure()) {
192  error() << "Unable to stop Algorithm "
193  << alg->name() << endmsg;
194  }
195  }
196 
197  for (auto& alg : branchAlgorithms() ) {
198  if (alg->sysStop( ).isFailure()) {
199  error() << "Unable to stop Algorithm "
200  << alg->name() << endmsg;
201  }
202  }
203  return StatusCode::SUCCESS;
204 }
205 
208 {
210 
211  // Bypass the loop if this sequencer is disabled
212  if ( isEnabled( ) ) {
213 
214  // Loop over all members calling their sysInitialize functions
215  // if they are not disabled. Note that the Algoriithm::sysInitialize
216  // function protects this from affecting Algorithms that have already
217  // been initialized.
218  for (auto& alg : *subAlgorithms() ) {
219  result = alg->sysInitialize( );
220  if( result.isFailure() ) {
221  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
222  break;
223  }
224  result = alg->sysStart( );
225  if( result.isFailure() ) {
226  error() << "Unable to start Algorithm " << alg->name() << endmsg;
227  break;
228  }
229  }
230 
231  // Loop over all members calling their beginRun functions
232  // if they are not disabled.
233  for (auto& alg : *subAlgorithms() ) {
234  if ( ! alg->isEnabled( ) ) {
235  alg->beginRun( ).ignore();
236  }
237  }
238 
239  // Loop over all branch members calling their sysInitialize functions
240  // if they are not disabled. Note that the Algoriithm::sysInitialize
241  // function protects this from affecting Algorithms that have already
242  // been initialized.
243  for (auto& alg : branchAlgorithms() ) {
244  result = alg->sysInitialize( );
245  if( result.isFailure() ) {
246  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
247  break;
248  }
249  result = alg->sysStart( );
250  if( result.isFailure() ) {
251  error() << "Unable to start Algorithm " << alg->name() << endmsg;
252  break;
253  }
254  }
255 
256  // Loop over all branch members calling their beginRun functions
257  // if they are not disabled.
258  for (auto& alg : branchAlgorithms()) {
259  if ( ! alg->isEnabled( ) ) {
260  alg->beginRun( ).ignore();
261  }
262  }
263  }
264  return StatusCode::SUCCESS;
265 }
266 
269 {
270  // Bypass the loop if this sequencer is disabled
271  if ( isEnabled( ) ) {
272 
273  // Loop over all members calling their endRun functions
274  // if they are not disabled.
275  for (auto& alg : *subAlgorithms()) {
276  if ( ! alg->isEnabled( ) ) alg->endRun( ).ignore();
277  }
278  // Loop over all branch members calling their endRun functions
279  // if they are not disabled.
280  for (auto& alg : branchAlgorithms()) {
281  if ( ! alg->isEnabled( ) ) alg->endRun( ).ignore();
282  }
283  }
284  return StatusCode::SUCCESS;
285 }
286 
287 void
289 {
291 
292  // Loop over all members calling their resetExecuted functions
293  // if they are not disabled.
294  for (auto& alg : *subAlgorithms() ) alg->resetExecuted( );
295 
296  // Loop over all branch members calling their resetExecuted functions
297  // if they are not disabled.
298  for (auto& alg : branchAlgorithms() ) alg->resetExecuted( );
299 
300  // Reset the branch filter passed flag
301  m_branchFilterPassed = false;
302 }
303 
304 bool
306 {
307  return m_branchFilterPassed;
308 }
309 
312 {
314  return StatusCode::SUCCESS;
315 }
316 
317 bool
319 {
320  return m_stopOverride.value( );
321 }
322 
325 {
326  return append( pAlgorithm, *subAlgorithms( ) );
327 }
328 
331 {
332  return append( pAlgorithm, branchAlgorithms( ) );
333 }
334 
337  const std::string& name,
338  Algorithm*& pAlgorithm )
339 {
340  return createAndAppend( type, name, pAlgorithm, *subAlgorithms( ) );
341 }
342 
345  const std::string& name,
346  Algorithm*& pAlgorithm )
347 {
348  return createAndAppend( type, name, pAlgorithm, branchAlgorithms( ) );
349 }
350 
353 {
354  return remove( pAlgorithm->name( ) );
355 }
356 
359 {
360  return remove( algname, *subAlgorithms( ) );
361 }
362 
365 {
366  return removeFromBranch( pAlgorithm->name( ) );
367 }
368 
371 {
372  return remove( algname, branchAlgorithms( ) );
373 }
374 
377  return m_branchAlgs;
378 }
379 
382  return m_branchAlgs;
383 }
384 
387 {
388  // Decode the membership list
389  return decodeNames( m_names,
390  *subAlgorithms( ),
391  m_isInverted );
392 }
393 
394 void
396 {
397  if ( isInitialized() ) decodeMemberNames();
398 }
399 
402 {
403  // Decode the branch membership list
404  return decodeNames( m_branchNames,
405  branchAlgorithms( ),
407 }
408 
409 void
411 {
413 }
414 
421  std::vector<Algorithm*>& theAlgs )
422 {
423  // Check that the specified algorithm doesn't already exist in the membership list
424  if (std::find(std::begin(theAlgs),std::end(theAlgs),pAlgorithm)!=std::end(theAlgs)) {
425  return StatusCode::FAILURE;
426  }
427  theAlgs.push_back( pAlgorithm );
428  pAlgorithm->addRef();
429  return StatusCode::SUCCESS;
430 }
431 
434  const std::string& algName,
435  Algorithm*& pAlgorithm,
436  std::vector<Algorithm*>& theAlgs )
437 {
438  auto theAlgMgr = serviceLocator()->service<IAlgManager>("ApplicationMgr");
439  if ( !theAlgMgr ) return StatusCode::FAILURE;
440 
441  IAlgorithm* tmp;
442  StatusCode result = theAlgMgr->createAlgorithm( type, algName, tmp );
443  if ( result.isSuccess( ) ) {
444  try{
445  pAlgorithm = dynamic_cast<Algorithm*>(tmp);
446  theAlgs.push_back( pAlgorithm );
447  } catch(...){
448  error() << "Unable to create Algorithm " << algName << endmsg;
449  result = StatusCode::FAILURE;
450  }
451  }
452 
453  return result;
454 }
455 
458  std::vector<Algorithm*>& theAlgs,
459  std::vector<bool>& theLogic )
460 {
461  StatusCode result;
462  auto theAlgMgr = serviceLocator()->service<IAlgManager>("ApplicationMgr");
463  if ( theAlgMgr ) {
464  // Clear the existing list of algorithms
465  theAlgs.clear( );
466 
467  // Build the list of member algorithms from the contents of the
468  // theNames list.
469  for (const auto& n : theNames.value() ) {
470 
471  // Parse the name for a syntax of the form:
472  //
473  // <type>/<name>
474  //
475  // Where <name> is the algorithm instance name, and <type> is the
476  // algorithm class type (being a subclass of Algorithm).
478  std::string theName = typeName.name();
479  std::string theType = typeName.type();
480 
481  // Parse the name for a syntax of the form:
482  //
483  // <name>:invert
484  //
485  // Where <name> is the algorithm instance name and ":invert"
486  // indicates that the filter passed logic is inverted.
487  bool isInverted = false;
488  std::string::size_type invert = theName.find_first_of( ":" );
489  // Skip all occurrences of "::" (allow namespaces)
490  while ( std::string::npos != invert
491  && invert < (theName.size() - 1) && theName[invert+1] == ':' )
492  invert = theName.find_first_of( ":", invert+2 );
493  if ( std::string::npos != invert ) {
494  if ( theName == theType ) {
495  // This means that we got something like "Type:invert",
496  // so we have to strip the ":invert" from the type too.
497  theType = theType.substr( 0, invert );
498  }
499  theName = theName.substr( 0, invert );
500  isInverted = true;
501  }
502  // Check whether the supplied name corresponds to an existing
503  // Algorithm object.
504  SmartIF<IAlgorithm>& theIAlg = theAlgMgr->algorithm(theName, false);
505  Algorithm* theAlgorithm = nullptr;
507  if ( theIAlg ) {
508  try{
509  theAlgorithm = dynamic_cast<Algorithm*>(theIAlg.get());
510  } catch(...){
511  warning() << theName << " is not an Algorithm - Failed dynamic cast" << endmsg;
512  theAlgorithm = nullptr; // release
513  }
514  }
515  if ( theAlgorithm ) {
516 
517  // The specified Algorithm already exists - just append it to the membership list.
518  status = append( theAlgorithm, theAlgs );
519  if ( status.isSuccess( ) ) {
520  ON_DEBUG debug() << theName << " already exists - appended to member list" << endmsg;
521  } else {
522  warning() << theName << " already exists - append failed!!!" << endmsg;
523  result = StatusCode::FAILURE;
524  }
525  } else {
526 
527  // The specified name doesn't exist - create a new object of the specified type
528  // and append it to the membership list.
529  status = createAndAppend( theType, theName, theAlgorithm, theAlgs );
530  if ( status.isSuccess( ) ) {
531  ON_DEBUG debug() << theName << " doesn't exist - created and appended to member list" << endmsg;
532  } else {
533  warning() << theName << " doesn't exist - creation failed!!!" << endmsg;
534  result = StatusCode::FAILURE;
535  }
536  }
537  if ( status.isSuccess( ) ) theLogic.push_back( isInverted );
538  }
539 
540  }
541  // Print membership list
542  if ( result.isSuccess() && theAlgs.size() != 0 ) {
543  info() << "Member list: ";
544  auto ai = theAlgs.begin();
545  auto li = theLogic.begin();
546  for ( ; ai != theAlgs.end(); ++ai, ++li ) {
547 
548  if ( ai != theAlgs.begin() ) info() << ", ";
549  auto alg = *ai;
550  if ( alg->name() == System::typeinfoName(typeid(*alg)) )
551  info() << alg->name();
552  else
553  info() << System::typeinfoName(typeid(*alg)) << "/" << alg->name();
554 
555  if (*li) info() << ":invert";
556  }
557  info() << endmsg;
558  }
559  return result;
560 }
561 
564  std::vector<bool>& theLogic,
565  Algorithm*& lastAlgorithm,
566  unsigned int first )
567 {
569 
570  // Loop over all algorithms calling their execute functions if they
571  // are (a) not disabled, and (b) aren't already executed. Note that
572  // in the latter case the filter state is still examined. Terminate
573  // the loop if an algorithm indicates that it's filter didn't pass.
574  unsigned int size = theAlgs.size( );
575  for (unsigned int i = first; i < size; i++) {
576  lastAlgorithm = theAlgs[i];
577  result = executeMember( lastAlgorithm );
578  if ( result.isSuccess( ) ) {
579 
580  // Take the filter passed status of this algorithm as my own status.
581  // Note that we take into account inverted logic.
582  bool passed = lastAlgorithm->filterPassed( );
583  bool isInverted = theLogic[i];
584  if ( isInverted ) passed = ! passed;
585  setFilterPassed( passed );
586 
587  // The behaviour when the filter fails depends on the StopOverride property.
588  // The default action is to stop processing, but this default can be
589  // overridden by setting the "StopOverride" property to true.
590  if ( ! isStopOverride( ) ) {
591  if ( ! passed ) break;
592  }
593  } else {
594  break;
595  }
596  }
597  return result;
598 }
599 
602 {
604  if ( theAlgorithm->isEnabled( ) ) {
605  if ( ! theAlgorithm->isExecuted( ) ) {
606  result = theAlgorithm->sysExecute( );
607 
608  // Set the executed state of the algorithm.
609  // I think this should be done by the algorithm itself, but just in case...
610  theAlgorithm->setExecuted( true );
611  }
612  }
613  return result;
614 }
615 
618 {
620 
621  // Test that the algorithm exists in the member list
622  for (auto& alg : theAlgs ) {
623  if ( alg->name( ) == algname ) {
624 
625  // Algorithm with specified name exists in the algorithm list - remove it
626  // THIS ISN'T IMPLEMENTED YET!!!!
627  info() << "Sequencer::remove( ) isn't implemented yet!!!!!" << endmsg;
628  result = StatusCode::SUCCESS;
629  break;
630  }
631  }
632  return result;
633 }
void resetExecuted() override
Reset the executed state of the Algorithm for the duration of the current event.
Definition: Algorithm.cpp:848
virtual bool isStopOverride() const
Has the StopOverride mode been set?
Definition: Sequencer.cpp:318
StatusCode append(Algorithm *pAlgorithm)
Append an algorithm to the sequencer.
Definition: Sequencer.cpp:324
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
StatusCode remove(Algorithm *pAlgorithm)
Remove the specified algorithm from the sequencer.
Definition: Sequencer.cpp:352
StatusCode removeFromBranch(Algorithm *pAlgorithm)
Definition: Sequencer.cpp:364
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
virtual Property & declareUpdateHandler(std::function< void(Property &)> fun)
set new callback for update
Definition: Property.cpp:72
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:297
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:76
Sequencer(const std::string &name, ISvcLocator *svcloc)
Constructor(s)
Definition: Sequencer.cpp:20
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Algorithm.cpp:929
The IAlgManager is the interface implemented by the Algorithm Factory in the Application Manager to s...
Definition: IAlgManager.h:27
virtual bool branchFilterPassed() const
additional interface methods
Definition: Sequencer.cpp:305
Property * declareProperty(const std::string &name, T &property, const std::string &doc="none") const
Declare the named property.
Definition: Algorithm.h:426
StatusCode stop() override
Sequencer finalization.
Definition: Sequencer.cpp:185
void branchMembershipHandler(Property &theProp)
"BranchMembers" property handler
Definition: Sequencer.cpp:410
bool filterPassed() const override
Did this algorithm pass or fail its filter criterion for the last event?
Definition: Algorithm.cpp:857
bool m_branchFilterPassed
Definition: Sequencer.h:245
BooleanProperty m_stopOverride
Definition: Sequencer.h:244
T end(T...args)
StatusCode reinitialize() override
Sequencer Reinitialization.
Definition: Sequencer.cpp:73
StatusCode beginRun() override
Sequencer beginRun.
Definition: Sequencer.cpp:207
const std::vector< Algorithm * > & branchAlgorithms() const
List of branch algorithms.
Definition: Sequencer.cpp:376
StatusCode executeMember(Algorithm *theAlgorithm)
Execute member algorithm.
Definition: Sequencer.cpp:601
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
StringArrayProperty m_branchNames
Definition: Sequencer.h:241
StatusCode decodeBranchMemberNames()
Decode branch member name list.
Definition: Sequencer.cpp:401
STL class.
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:820
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:76
virtual StatusCode setBranchFilterPassed(bool state)
Set the branch filter passed flag for the last event.
Definition: Sequencer.cpp:311
StatusCode service(const Gaudi::Utils::TypeNameString &name, T *&svc, bool createIf=true)
Templated method to access a service by name.
Definition: ISvcLocator.h:78
T push_back(T...args)
StatusCode decodeNames(StringArrayProperty &theNames, std::vector< Algorithm * > &theAlgs, std::vector< bool > &theLogic)
Decode algorithm names, creating or appending algorithms as appropriate.
Definition: Sequencer.cpp:457
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
Helper class to parse a string of format "type/name".
Definition: TypeNameString.h:9
void setExecuted(bool state) override
Set the executed flag to the specified state.
Definition: Algorithm.cpp:844
StatusCode execute() override
The actions to be performed by the sequencer on an event.
Definition: Sequencer.cpp:96
string type
Definition: gaudirun.py:151
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
StatusCode decodeMemberNames()
Decode Member Name list.
Definition: Sequencer.cpp:386
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:344
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
StatusCode sysExecute() override
The actions to be performed by the algorithm on an event.
Definition: Algorithm.cpp:567
bool isExecuted() const override
Has this algorithm been executed since the last reset?
Definition: Algorithm.cpp:840
T find_first_of(T...args)
T clear(T...args)
The IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:25
const TYPE & value() const
explicit conversion
Definition: Property.h:341
const std::vector< Algorithm * > * subAlgorithms() const
List of sub-algorithms. Returns a pointer to a vector of (sub) Algorithms.
Definition: Algorithm.cpp:865
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:74
T find(T...args)
T size(T...args)
Property base class allowing Property* collections to be "homogeneous".
Definition: Property.h:38
void membershipHandler(Property &theProp)
"Members" property handler
Definition: Sequencer.cpp:395
std::vector< Algorithm * > m_branchAlgs
Definition: Sequencer.h:242
#define ON_DEBUG
Definition: Sequencer.cpp:14
StatusCode endRun() override
Sequencer endRun.
Definition: Sequencer.cpp:268
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
bool isInitialized() const override
Has the Algorithm already been initialized?
Definition: Algorithm.h:665
std::vector< bool > m_isInverted
Definition: Sequencer.h:240
StatusCode createAndAppend(const std::string &type, const std::string &name, Algorithm *&pAlgorithm)
Create a algorithm and append it to the sequencer.
Definition: Sequencer.cpp:336
bool isEnabled() const override
Is this algorithm enabled or disabled?
Definition: Algorithm.cpp:853
T begin(T...args)
const std::string & type() const
StatusCode appendToBranch(Algorithm *pAlgorithm)
Append an algorithm to the sequencer branch.
Definition: Sequencer.cpp:330
StringArrayProperty m_names
Definition: Sequencer.h:239
T substr(T...args)
StatusCode finalize() override
Sequencer finalization.
Definition: Sequencer.cpp:143
StatusCode initialize() override
Initialization of a sequencer.
Definition: Sequencer.cpp:35
const std::string & name() const
void ignore() const
Definition: StatusCode.h:108
std::string typeName(const std::type_info &typ)
Definition: Dictionary.cpp:21
list i
Definition: ana.py:128
void setFilterPassed(bool state) override
Set the filter passed flag to the specified state.
Definition: Algorithm.cpp:861
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
void resetExecuted() override
Reset the Sequencer executed state for the current event.
Definition: Sequencer.cpp:288
std::vector< bool > m_isBranchInverted
Definition: Sequencer.h:243
StatusCode start() override
Sequencer finalization.
Definition: Sequencer.cpp:158