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