Gaudi Framework, version v23r4

Home   Generated: Mon Sep 17 2012
Classes | Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes

GaudiSequencer Class Reference

Sequencer for executing several algorithms, stopping when one is faulty. More...

#include <GaudiSequencer.h>

Inheritance diagram for GaudiSequencer:
Inheritance graph
[legend]
Collaboration diagram for GaudiSequencer:
Collaboration graph
[legend]

List of all members.

Classes

class  AlgorithmEntry

Public Member Functions

 GaudiSequencer (const std::string &name, ISvcLocator *pSvcLocator)
 Standard constructor.
virtual ~GaudiSequencer ()
 Destructor.
virtual StatusCode initialize ()
 Algorithm initialization.
virtual StatusCode execute ()
 Algorithm execution.
virtual StatusCode finalize ()
 Algorithm finalization.
virtual StatusCode beginRun ()
 Algorithm beginRun.
virtual StatusCode endRun ()
 Algorithm endRun.
void resetExecuted ()
 Called before an event processing.
void membershipHandler (Property &theProp)
 for asynchronous changes in the list of algorithms

Protected Member Functions

StatusCode decodeNames ()
 Decode a vector of string.

Private Member Functions

 GaudiSequencer (const GaudiSequencer &a)
 Private copy, copy not allowed.
GaudiSequenceroperator= (const GaudiSequencer &a)
 Private assignment operator: This is not allowed.

Private Attributes

StringArrayProperty m_names
 Input string, list of algorithms.
std::vector< AlgorithmEntrym_entries
 List of algorithms to process.
bool m_modeOR
 Indicates that the OR is wanted instead of AND.
bool m_shortCircuit
 Indicates whether to stop processing as soon as possible, or to always execute _all_ subalgorithms.
bool m_ignoreFilter
 True if one continues always.
bool m_isInitialized
 Indicate that we are ready.
bool m_measureTime
 Flag to measure time.
bool m_returnOK
 Forces the sequencer to return a good status.
ISequencerTimerToolm_timerTool
 Pointer to the timer tool.
int m_timer
 Timer number for the sequencer.

Detailed Description

Sequencer for executing several algorithms, stopping when one is faulty.

Default behaviour (ModeOR=False) is to execute all algorithms until one returns filterPassed() = False. If ShortCircuit is set to False, then all algorithms will be executed.

In OR mode, the logic is opposite. All algorithms until one returns filterPassed() = True. To then exit one must onter-intuitively set ShortCircuit to False. If the default value ShortCircuit=True is left then all algorithms will be executed.

Author:
Olivier Callot
Date:
2004-05-13

Definition at line 27 of file GaudiSequencer.h.


Constructor & Destructor Documentation

GaudiSequencer::GaudiSequencer ( const std::string name,
ISvcLocator pSvcLocator 
)

Standard constructor.

Definition at line 20 of file GaudiSequencer.cpp.

  : GaudiAlgorithm ( name , pSvcLocator )
  , m_timerTool( 0 )
{
  declareProperty( "Members"             , m_names                  );
  declareProperty( "ModeOR"              , m_modeOR         = false );
  declareProperty( "IgnoreFilterPassed"  , m_ignoreFilter   = false );
  declareProperty( "MeasureTime"         , m_measureTime    = false );
  declareProperty( "ReturnOK"            , m_returnOK       = false );
  declareProperty( "ShortCircuit"        , m_shortCircuit   = true  );

  m_names.declareUpdateHandler (& GaudiSequencer::membershipHandler, this );
}
GaudiSequencer::~GaudiSequencer (  ) [virtual]

Destructor.

Definition at line 37 of file GaudiSequencer.cpp.

{}
GaudiSequencer::GaudiSequencer ( const GaudiSequencer a ) [private]

Private copy, copy not allowed.


Member Function Documentation

StatusCode GaudiSequencer::beginRun (  ) [virtual]

Algorithm beginRun.

Reimplemented from Algorithm.

Definition at line 160 of file GaudiSequencer.cpp.

                                      {

  if ( !isEnabled() ) return StatusCode::SUCCESS;

  if (msgLevel(MSG::DEBUG)) debug() << "==> beginRun" << endmsg;
  return StatusCode::SUCCESS;
}
StatusCode GaudiSequencer::decodeNames (  ) [protected]

Decode a vector of string.

Definition at line 199 of file GaudiSequencer.cpp.

                                         {

  StatusCode final = StatusCode::SUCCESS;
  m_entries.clear();

  //== Get the "Context" option if in the file...
  IJobOptionsSvc* jos = svc<IJobOptionsSvc>( "JobOptionsSvc" );
  bool addedContext = false;  //= Have we added the context ?
  bool addedRootInTES = false;  //= Have we added the rootInTES ?
  bool addedGlobalTimeOffset = false;  //= Have we added the globalTimeOffset ?


  //= Get the Application manager, to see if algorithm exist
  IAlgManager* appMgr = svc<IAlgManager>("ApplicationMgr");
  const std::vector<std::string>& nameVector = m_names.value();
  std::vector<std::string>::const_iterator it;
  for ( it = nameVector.begin(); nameVector.end() != it; it++ ) {
    const Gaudi::Utils::TypeNameString typeName(*it);
    const std::string &theName = typeName.name();
    const std::string &theType = typeName.type();

    //== Check wether the specified algorithm already exists. If not, create it
    StatusCode result = StatusCode::SUCCESS;
    SmartIF<IAlgorithm> myIAlg = appMgr->algorithm(typeName, false); // do not create it now
    if ( !myIAlg.isValid() ) {
      //== Set the Context if not in the jobOptions list
      if ( ""  != context() ||
           ""  != rootInTES() ||
           0.0 != globalTimeOffset() ) {
        bool foundContext = false;
        bool foundRootInTES = false;
        bool foundGlobalTimeOffset = false;
        const std::vector<const Property*>* properties = jos->getProperties( theName );
        if ( 0 != properties ) {
          // Iterate over the list to set the options
          for ( std::vector<const Property*>::const_iterator itProp = properties->begin();
               itProp != properties->end();
               itProp++ )   {
            const StringProperty* sp = dynamic_cast<const StringProperty*>(*itProp);
            if ( 0 != sp )    {
              if ( "Context" == (*itProp)->name() ) {
                foundContext = true;
              }
              if ( "RootInTES" == (*itProp)->name() ) {
                foundRootInTES = true;
              }
              if ( "GlobalTimeOffset" == (*itProp)->name() ) {
                foundGlobalTimeOffset = true;
              }
            }
          }
        }
        if ( !foundContext && "" != context() ) {
          StringProperty contextProperty( "Context", context() );
          jos->addPropertyToCatalogue( theName, contextProperty ).ignore();
          addedContext = true;
        }
        if ( !foundRootInTES && "" != rootInTES() ) {
          StringProperty rootInTESProperty( "RootInTES", rootInTES() );
          jos->addPropertyToCatalogue( theName, rootInTESProperty ).ignore();
          addedRootInTES = true;
        }
        if ( !foundGlobalTimeOffset && 0.0 != globalTimeOffset() ) {
          DoubleProperty globalTimeOffsetProperty( "GlobalTimeOffset", globalTimeOffset() );
          jos->addPropertyToCatalogue( theName, globalTimeOffsetProperty ).ignore();
          addedGlobalTimeOffset = true;
        }
      }

      Algorithm *myAlg = 0;
      result = createSubAlgorithm( theType, theName, myAlg );
      // (MCl) this should prevent bug #35199... even if I didn't manage to
      // reproduce it with a simple test.
      if (result.isSuccess()) myIAlg = myAlg;
    } else {
      Algorithm *myAlg = dynamic_cast<Algorithm*>(myIAlg.get());
      if (myAlg) {
        subAlgorithms()->push_back(myAlg);
        // when the algorithm is not created, the ref count is short by one, so we have to fix it.
        myAlg->addRef();
      }
    }

    //== Remove the property, in case this is not a GaudiAlgorithm...
    if ( addedContext ) {
      jos->removePropertyFromCatalogue( theName, "Context" ).ignore();
      addedContext = false;
    }
    if ( addedRootInTES ) {
      jos->removePropertyFromCatalogue( theName, "RootInTES" ).ignore();
      addedRootInTES = false;
    }
    if ( addedGlobalTimeOffset ) {
      jos->removePropertyFromCatalogue( theName, "GlobalTimeOffset" ).ignore();
      addedGlobalTimeOffset = false;
    }

    // propagate the sub-algorithm into own state.
    if ( result.isSuccess () &&
         Gaudi::StateMachine::INITIALIZED <= FSMState() &&
         myIAlg.isValid   () &&
         Gaudi::StateMachine::INITIALIZED  > myIAlg->FSMState() )
    {
      StatusCode sc = myIAlg->sysInitialize() ;
      if  ( sc.isFailure() ) { result = sc ; }
    }

    // propagate the sub-algorithm into own state.
    if ( result.isSuccess () &&
         Gaudi::StateMachine::RUNNING <= FSMState() &&
         myIAlg.isValid   () &&
         Gaudi::StateMachine::RUNNING  > myIAlg->FSMState() )
    {
      StatusCode sc = myIAlg->sysStart () ;
      if  ( sc.isFailure() ) { result = sc ; }
    }

    //== Is it an Algorithm ?  Strange test...
    if ( result.isSuccess() ) {
      // TODO: (MCl) it is possible to avoid the dynamic_cast in most of the
      //             cases by keeping the result of createSubAlgorithm.
      Algorithm*  myAlg = dynamic_cast<Algorithm*>(myIAlg.get());
      if (myAlg!=0) {
        // Note: The reference counting is kept by the system of sub-algorithms
        m_entries.push_back( AlgorithmEntry( myAlg ) );
        if (msgLevel(MSG::DEBUG)) debug () << "Added algorithm " << theName << endmsg;
      } else {
        warning() << theName << " is not an Algorithm - failed dynamic_cast"
                  << endmsg;
        final = StatusCode::FAILURE;
      }
    } else {
      warning() << "Unable to find or create " << theName << endmsg;
      final = result;
    }

  }

  release(appMgr).ignore();
  release(jos).ignore();

  //== Print the list of algorithms
  MsgStream& msg = info();
  if ( m_modeOR ) msg << "OR ";
  msg << "Member list: ";
  std::vector<AlgorithmEntry>::iterator itE;
  for ( itE = m_entries.begin(); m_entries.end() != itE; itE++ ) {
    Algorithm* myAlg = (*itE).algorithm();
    std::string myAlgType = System::typeinfoName( typeid( *myAlg) ) ;
    if ( myAlg->name() == myAlgType ) {
      msg << myAlg->name();
    } else {
      msg << myAlgType << "/" << myAlg->name();
    }
    if ( itE+1 != m_entries.end() ) msg << ", ";
  }
  if ( "" != context() ) msg << ", with context '" << context() << "'";
  if ( "" != rootInTES() ) msg << ", with rootInTES '" << rootInTES() << "'";
  if ( 0.0 != globalTimeOffset() ) msg << ", with globalTimeOffset " << globalTimeOffset();
  msg << endmsg;

  return final;

}
StatusCode GaudiSequencer::endRun (  ) [virtual]

Algorithm endRun.

Reimplemented from Algorithm.

Definition at line 171 of file GaudiSequencer.cpp.

                                    {

  if ( !isEnabled() ) return StatusCode::SUCCESS;

  if (msgLevel(MSG::DEBUG)) debug() << "==> endRun" << endmsg;
  return StatusCode::SUCCESS;
}
StatusCode GaudiSequencer::execute (  ) [virtual]

Algorithm execution.

Reimplemented from GaudiAlgorithm.

Definition at line 82 of file GaudiSequencer.cpp.

                                   {

  if ( m_measureTime ) m_timerTool->start( m_timer );

  if (msgLevel(MSG::DEBUG)) debug() << "==> Execute" << endmsg;

  StatusCode result = StatusCode::SUCCESS;

  bool seqPass = !m_modeOR; //  for OR, result will be false, unless (at least) one is true
                            //  for AND, result will be true, unless (at least) one is false
                            //    also see comment below ....

  std::vector<AlgorithmEntry>::const_iterator itE;
  for ( itE = m_entries.begin(); m_entries.end() != itE; ++itE ) {
    Algorithm* myAlg = itE->algorithm();
    if ( ! myAlg->isEnabled() ) continue;
    if ( ! myAlg->isExecuted() ) {
      if ( m_measureTime ) m_timerTool->start( itE->timer() );
      result = myAlg->sysExecute();
      if ( m_measureTime ) m_timerTool->stop( itE->timer() );
      myAlg->setExecuted( true );
      if ( ! result.isSuccess() ) break;  //== Abort and return bad status
    }
    //== Check the returned status
    if ( !m_ignoreFilter ) {
      bool passed = myAlg->filterPassed();
      if (msgLevel(MSG::VERBOSE))
        verbose() << "Algorithm " << myAlg->name() << " returned filter passed "
                  << (passed ? "true" : "false") << endmsg;
      if ( itE->reverse() ) passed = !passed;


      //== indicate our own result. For OR, exit as soon as true.
      //        If no more, will exit with false.
      //== for AND, exit as soon as false. Else, will be true (default)

      // if not short-circuiting, make sure we latch iPass to 'true' in
      // OR mode (i.e. it is sufficient for one item to be true in order
      // to be true at the end, and thus we start out at 'false'), and latch
      // to 'false' in AND mode (i.e. it is sufficient for one item to
      // be false to the false in the end, and thus we start out at 'true')
      // -- i.e. we should not just blindly return the 'last' passed status!

      // or to put it another way: in OR mode, we don't care about things
      // which are false, as they leave our current state alone (provided
      // we stared as 'false'!), and in AND mode, we keep our current
      // state until someone returns 'false' (provided we started as 'true')
      if ( m_modeOR ? passed : !passed ) {
        seqPass = passed;
        if (msgLevel(MSG::VERBOSE))
          verbose() << "SeqPass is now " << (seqPass ? "true" : "false") << endmsg;
        if (m_shortCircuit) break;
      }
    }

  }
  if (msgLevel(MSG::VERBOSE))
      verbose() << "SeqPass is " << (seqPass ? "true" : "false") << endmsg;
  if ( !m_ignoreFilter && !m_entries.empty() ) setFilterPassed( seqPass );
  setExecuted( true );

  if ( m_measureTime ) m_timerTool->stop( m_timer );

  return m_returnOK ? StatusCode::SUCCESS : result;
}
StatusCode GaudiSequencer::finalize (  ) [virtual]

Algorithm finalization.

Reimplemented from GaudiAlgorithm.

Definition at line 151 of file GaudiSequencer.cpp.

                                    {

  if (msgLevel(MSG::DEBUG)) debug() << "==> Finalize" << endmsg;
  return  GaudiAlgorithm::finalize();
}
StatusCode GaudiSequencer::initialize (  ) [virtual]

Algorithm initialization.

Reimplemented from GaudiAlgorithm.

Definition at line 42 of file GaudiSequencer.cpp.

                                      {
  GaudiAlgorithm::initialize();

  if (msgLevel(MSG::DEBUG)) debug() << "==> Initialise" << endmsg;

  StatusCode status = decodeNames();
  if ( !status.isSuccess() ) return status;

  m_timerTool = tool<ISequencerTimerTool>( "SequencerTimerTool" );
  if ( m_timerTool->globalTiming() ) m_measureTime = true;

  if ( m_measureTime ) {
    m_timer = m_timerTool->addTimer( name() );
    m_timerTool->increaseIndent();
  } else {
    release( m_timerTool );
    m_timerTool = 0;
  }

  //== Initialize the algorithms
  std::vector<AlgorithmEntry>::iterator itE;
  for ( itE = m_entries.begin(); m_entries.end() != itE; itE++ ) {
    if ( m_measureTime ) {
      itE->setTimer( m_timerTool->addTimer( itE->algorithm()->name() ) );
    }

    status = itE->algorithm()->sysInitialize();
    if ( !status.isSuccess() ) {
      return Error( "Can not initialize " + itE->algorithm()->name(),
                    status );
    }
  }
  if ( m_measureTime ) m_timerTool->decreaseIndent();

  return StatusCode::SUCCESS;
}
void GaudiSequencer::membershipHandler ( Property theProp )

for asynchronous changes in the list of algorithms

Definition at line 371 of file GaudiSequencer.cpp.

{
  // no action for not-yet initialized sequencer
  if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) { return ; } // RETURN

  decodeNames().ignore();

  if  ( !m_measureTime ) { return ; }                                // RETURN

  // add the entries into timer table:

  if ( 0 == m_timerTool )
  { m_timerTool = tool<ISequencerTimerTool>( "SequencerTimerTool" ) ; }

  if ( m_timerTool->globalTiming() ) m_measureTime = true;

  m_timer = m_timerTool->addTimer( name() );
  m_timerTool->increaseIndent();

  for ( std::vector<AlgorithmEntry>::iterator itE = m_entries.begin() ;
        m_entries.end() != itE; ++itE )
  {
    itE->setTimer( m_timerTool->addTimer( itE->algorithm()->name() ) );
  }

  m_timerTool->decreaseIndent();

}
GaudiSequencer& GaudiSequencer::operator= ( const GaudiSequencer a ) [private]

Private assignment operator: This is not allowed.

void GaudiSequencer::resetExecuted (  ) [virtual]

Called before an event processing.

Reimplemented from Algorithm.

Definition at line 182 of file GaudiSequencer.cpp.

                                     {
  Algorithm::resetExecuted();
  // algorithm doesn't call resetExecuted of subalgos! should it???
  std::vector<AlgorithmEntry>::const_iterator itE;
  for ( itE = m_entries.begin(); m_entries.end() != itE; ++itE ) {
    itE->algorithm()->resetExecuted();
  }
}

Member Data Documentation

List of algorithms to process.

Definition at line 82 of file GaudiSequencer.h.

True if one continues always.

Definition at line 87 of file GaudiSequencer.h.

Indicate that we are ready.

Definition at line 88 of file GaudiSequencer.h.

Flag to measure time.

Definition at line 89 of file GaudiSequencer.h.

bool GaudiSequencer::m_modeOR [private]

Indicates that the OR is wanted instead of AND.

Definition at line 83 of file GaudiSequencer.h.

Input string, list of algorithms.

Definition at line 81 of file GaudiSequencer.h.

Forces the sequencer to return a good status.

Definition at line 90 of file GaudiSequencer.h.

Indicates whether to stop processing as soon as possible, or to always execute _all_ subalgorithms.

In MOdeOR=True the behaviour is the exact opposite.

Definition at line 84 of file GaudiSequencer.h.

int GaudiSequencer::m_timer [private]

Timer number for the sequencer.

Definition at line 92 of file GaudiSequencer.h.

Pointer to the timer tool.

Definition at line 91 of file GaudiSequencer.h.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Mon Sep 17 2012 13:49:46 for Gaudi Framework, version v23r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004