| # Gaudi Framework, version v23r1 |

Home |  | Generated: Wed Feb 29 2012

# GaudiSequencer.cpp

Go to the documentation of this file.

    00001 // $Id: GaudiSequencer.cpp,v 1.18 2008/10/10 13:50:35 marcocle Exp $
    00002 // Include files
    00003
    00004 // from Gaudi
    00005 #include "GaudiKernel/AlgFactory.h"
    00006 #include "GaudiKernel/IAlgManager.h"
    00007 #include "GaudiAlg/GaudiSequencer.h"
    00008 #include "GaudiAlg/ISequencerTimerTool.h"
    00009 #include "GaudiKernel/IJobOptionsSvc.h"
    00010
    00011 //-----------------------------------------------------------------------------
    00012 // Implementation file for class : GaudiSequencer
    00013 //
    00014 // 2004-05-13 : Olivier Callot
    00015 //-----------------------------------------------------------------------------
    00016
    00017 //=============================================================================
    00018 // Standard constructor, initializes variables
    00019 //=============================================================================
    00020 GaudiSequencer::GaudiSequencer( const std::string& name,
    00021                                 ISvcLocator* pSvcLocator)
    00022   : GaudiAlgorithm ( name , pSvcLocator )
    00023   , m_timerTool( 0 )
    00024 {
    00025   declareProperty( "Members"             , m_names                  );
    00026   declareProperty( "ModeOR"              , m_modeOR         = false );
    00027   declareProperty( "IgnoreFilterPassed"  , m_ignoreFilter   = false );
    00028   declareProperty( "MeasureTime"         , m_measureTime    = false );
    00029   declareProperty( "ReturnOK"            , m_returnOK       = false );
    00030   declareProperty( "ShortCircuit"        , m_shortCircuit   = true  );
    00031
    00032   m_names.declareUpdateHandler (& GaudiSequencer::membershipHandler, this );
    00033 }
    00034 //=============================================================================
    00035 // Destructor
    00036 //=============================================================================
    00037 GaudiSequencer::~GaudiSequencer() {}
    00038
    00039 //=============================================================================
    00040 // Initialisation. Check parameters
    00041 //=============================================================================
    00042 StatusCode GaudiSequencer::initialize() {
    00043   GaudiAlgorithm::initialize();
    00044
    00045   if (msgLevel(MSG::DEBUG)) debug() << "==> Initialise" << endmsg;
    00046
    00047   StatusCode status = decodeNames();
    00048   if ( !status.isSuccess() ) return status;
    00049
    00050   m_timerTool = tool<ISequencerTimerTool>( "SequencerTimerTool" );
    00051   if ( m_timerTool->globalTiming() ) m_measureTime = true;
    00052
    00053   if ( m_measureTime ) {
    00054     m_timer = m_timerTool->addTimer( name() );
    00055     m_timerTool->increaseIndent();
    00056   } else {
    00057     release( m_timerTool );
    00058     m_timerTool = 0;
    00059   }
    00060
    00061   //== Initialize the algorithms
    00062   std::vector<AlgorithmEntry>::iterator itE;
    00063   for ( itE = m_entries.begin(); m_entries.end() != itE; itE++ ) {
    00064     if ( m_measureTime ) {
    00065       itE->setTimer( m_timerTool->addTimer( itE->algorithm()->name() ) );
    00066     }
    00067
    00068     status = itE->algorithm()->sysInitialize();
    00069     if ( !status.isSuccess() ) {
    00070       return Error( "Can not initialize " + itE->algorithm()->name(),
    00071                     status );
    00072     }
    00073   }
    00074   if ( m_measureTime ) m_timerTool->decreaseIndent();
    00075
    00076   return StatusCode::SUCCESS;
    00077 }
    00078
    00079 //=============================================================================
    00080 // Main execution
    00081 //=============================================================================
    00082 StatusCode GaudiSequencer::execute() {
    00083
    00084   if ( m_measureTime ) m_timerTool->start( m_timer );
    00085
    00086   if (msgLevel(MSG::DEBUG)) debug() << "==> Execute" << endmsg;
    00087
    00088   StatusCode result = StatusCode::SUCCESS;
    00089
    00090   bool seqPass = !m_modeOR; //  for OR, result will be false, unless (at least) one is true
    00091                             //  for AND, result will be true, unless (at least) one is false
    00092                             //    also see comment below ....
    00093
    00094   std::vector<AlgorithmEntry>::const_iterator itE;
    00095   for ( itE = m_entries.begin(); m_entries.end() != itE; ++itE ) {
    00096     Algorithm* myAlg = itE->algorithm();
    00097     if ( ! myAlg->isEnabled() ) continue;
    00098     if ( ! myAlg->isExecuted() ) {
    00099       if ( m_measureTime ) m_timerTool->start( itE->timer() );
    00100       result = myAlg->sysExecute();
    00101       if ( m_measureTime ) m_timerTool->stop( itE->timer() );
    00102       myAlg->setExecuted( true );
    00103       if ( ! result.isSuccess() ) break;  //== Abort and return bad status
    00104     }
    00105     //== Check the returned status
    00106     if ( !m_ignoreFilter ) {
    00107       bool passed = myAlg->filterPassed();
    00108       if (msgLevel(MSG::VERBOSE))
    00109         verbose() << "Algorithm " << myAlg->name() << " returned filter passed "
    00110                   << (passed ? "true" : "false") << endmsg;
    00111       if ( itE->reverse() ) passed = !passed;
    00112
    00113
    00114       //== indicate our own result. For OR, exit as soon as true.
    00115       //        If no more, will exit with false.
    00116       //== for AND, exit as soon as false. Else, will be true (default)
    00117
    00118       // if not short-circuiting, make sure we latch iPass to 'true' in
    00119       // OR mode (i.e. it is sufficient for one item to be true in order
    00120       // to be true at the end, and thus we start out at 'false'), and latch
    00121       // to 'false' in AND mode (i.e. it is sufficient for one item to
    00122       // be false to the false in the end, and thus we start out at 'true')
    00123       // -- i.e. we should not just blindly return the 'last' passed status!
    00124
    00125       // or to put it another way: in OR mode, we don't care about things
    00126       // which are false, as they leave our current state alone (provided
    00127       // we stared as 'false'!), and in AND mode, we keep our current
    00128       // state until someone returns 'false' (provided we started as 'true')
    00129       if ( m_modeOR ? passed : !passed ) {
    00130         seqPass = passed;
    00131         if (msgLevel(MSG::VERBOSE))
    00132           verbose() << "SeqPass is now " << (seqPass ? "true" : "false") << endmsg;
    00133         if (m_shortCircuit) break;
    00134       }
    00135     }
    00136
    00137   }
    00138   if (msgLevel(MSG::VERBOSE))
    00139       verbose() << "SeqPass is " << (seqPass ? "true" : "false") << endmsg;
    00140   if ( !m_ignoreFilter && !m_entries.empty() ) setFilterPassed( seqPass );
    00141   setExecuted( true );
    00142
    00143   if ( m_measureTime ) m_timerTool->stop( m_timer );
    00144
    00145   return m_returnOK ? StatusCode::SUCCESS : result;
    00146 }
    00147
    00148 //=============================================================================
    00149 //  Finalize
    00150 //=============================================================================
    00151 StatusCode GaudiSequencer::finalize() {
    00152
    00153   if (msgLevel(MSG::DEBUG)) debug() << "==> Finalize" << endmsg;
    00154   return  GaudiAlgorithm::finalize();
    00155 }
    00156
    00157 //=========================================================================
    00158 //  Execute the beginRun of every algorithm
    00159 //=========================================================================
    00160 StatusCode GaudiSequencer::beginRun ( ) {
    00161
    00162   if ( !isEnabled() ) return StatusCode::SUCCESS;
    00163
    00164   if (msgLevel(MSG::DEBUG)) debug() << "==> beginRun" << endmsg;
    00165   return StatusCode::SUCCESS;
    00166 }
    00167
    00168 //=========================================================================
    00169 //  Execute the endRun() of every algorithm
    00170 //=========================================================================
    00171 StatusCode GaudiSequencer::endRun ( ) {
    00172
    00173   if ( !isEnabled() ) return StatusCode::SUCCESS;
    00174
    00175   if (msgLevel(MSG::DEBUG)) debug() << "==> endRun" << endmsg;
    00176   return StatusCode::SUCCESS;
    00177 }
    00178
    00179 //=========================================================================
    00180 // reset the executed status of all members
    00181 //=========================================================================
    00182 void GaudiSequencer::resetExecuted ( ) {
    00183   Algorithm::resetExecuted();
    00184   // algorithm doesn't call resetExecuted of subalgos! should it???
    00185   std::vector<AlgorithmEntry>::const_iterator itE;
    00186   for ( itE = m_entries.begin(); m_entries.end() != itE; ++itE ) {
    00187     itE->algorithm()->resetExecuted();
    00188   }
    00189 }
    00190 //=========================================================================
    00191 //  Decode the input names and fills the m_algs vector.
    00192 //=========================================================================
    00193 #ifdef __ICC
    00194 // disable icc remark #1572: floating-point equality and inequality comparisons are unreliable
    00195 //   The comparison are meant
    00196 #pragma warning(push)
    00197 #pragma warning(disable:1572)
    00198 #endif
    00199 StatusCode GaudiSequencer::decodeNames( )  {
    00200
    00201   StatusCode final = StatusCode::SUCCESS;
    00202   m_entries.clear();
    00203
    00204   //== Get the "Context" option if in the file...
    00205   IJobOptionsSvc* jos = svc<IJobOptionsSvc>( "JobOptionsSvc" );
    00206   bool addedContext = false;  //= Have we added the context ?
    00207   bool addedRootInTES = false;  //= Have we added the rootInTES ?
    00208   bool addedGlobalTimeOffset = false;  //= Have we added the globalTimeOffset ?
    00209
    00210
    00211   //= Get the Application manager, to see if algorithm exist
    00212   IAlgManager* appMgr = svc<IAlgManager>("ApplicationMgr");
    00213   const std::vector<std::string>& nameVector = m_names.value();
    00214   std::vector<std::string>::const_iterator it;
    00215   for ( it = nameVector.begin(); nameVector.end() != it; it++ ) {
    00216     const Gaudi::Utils::TypeNameString typeName(*it);
    00217     const std::string &theName = typeName.name();
    00218     const std::string &theType = typeName.type();
    00219
    00220     //== Check wether the specified algorithm already exists. If not, create it
    00221     StatusCode result = StatusCode::SUCCESS;
    00222     SmartIF<IAlgorithm> myIAlg = appMgr->algorithm(typeName, false); // do not create it now
    00223     if ( !myIAlg.isValid() ) {
    00224       //== Set the Context if not in the jobOptions list
    00225       if ( ""  != context() ||
    00226            ""  != rootInTES() ||
    00227            0.0 != globalTimeOffset() ) {
    00228         bool foundContext = false;
    00229         bool foundRootInTES = false;
    00230         bool foundGlobalTimeOffset = false;
    00231         const std::vector<const Property*>* properties = jos->getProperties( theName );
    00232         if ( 0 != properties ) {
    00233           // Iterate over the list to set the options
    00234           for ( std::vector<const Property*>::const_iterator itProp = properties->begin();
    00235                itProp != properties->end();
    00236                itProp++ )   {
    00237             const StringProperty* sp = dynamic_cast<const StringProperty*>(*itProp);
    00238             if ( 0 != sp )    {
    00239               if ( "Context" == (*itProp)->name() ) {
    00240                 foundContext = true;
    00241               }
    00242               if ( "RootInTES" == (*itProp)->name() ) {
    00243                 foundRootInTES = true;
    00244               }
    00245               if ( "GlobalTimeOffset" == (*itProp)->name() ) {
    00246                 foundGlobalTimeOffset = true;
    00247               }
    00248             }
    00249           }
    00250         }
    00251         if ( !foundContext && "" != context() ) {
    00252           StringProperty contextProperty( "Context", context() );
    00253           jos->addPropertyToCatalogue( theName, contextProperty ).ignore();
    00254           addedContext = true;
    00255         }
    00256         if ( !foundRootInTES && "" != rootInTES() ) {
    00257           StringProperty rootInTESProperty( "RootInTES", rootInTES() );
    00258           jos->addPropertyToCatalogue( theName, rootInTESProperty ).ignore();
    00259           addedRootInTES = true;
    00260         }
    00261         if ( !foundGlobalTimeOffset && 0.0 != globalTimeOffset() ) {
    00262           DoubleProperty globalTimeOffsetProperty( "GlobalTimeOffset", globalTimeOffset() );
    00263           jos->addPropertyToCatalogue( theName, globalTimeOffsetProperty ).ignore();
    00264           addedGlobalTimeOffset = true;
    00265         }
    00266       }
    00267
    00268       Algorithm *myAlg = 0;
    00269       result = createSubAlgorithm( theType, theName, myAlg );
    00270       // (MCl) this should prevent bug #35199... even if I didn't manage to
    00271       // reproduce it with a simple test.
    00272       if (result.isSuccess()) myIAlg = myAlg;
    00273     } else {
    00274       Algorithm *myAlg = dynamic_cast<Algorithm*>(myIAlg.get());
    00275       if (myAlg) {
    00276         subAlgorithms()->push_back(myAlg);
    00277         // when the algorithm is not created, the ref count is short by one, so we have to fix it.
    00278         myAlg->addRef();
    00279       }
    00280     }
    00281
    00282     //== Remove the property, in case this is not a GaudiAlgorithm...
    00283     if ( addedContext ) {
    00284       jos->removePropertyFromCatalogue( theName, "Context" ).ignore();
    00285       addedContext = false;
    00286     }
    00287     if ( addedRootInTES ) {
    00288       jos->removePropertyFromCatalogue( theName, "RootInTES" ).ignore();
    00289       addedRootInTES = false;
    00290     }
    00291     if ( addedGlobalTimeOffset ) {
    00292       jos->removePropertyFromCatalogue( theName, "GlobalTimeOffset" ).ignore();
    00293       addedGlobalTimeOffset = false;
    00294     }
    00295
    00296     // propagate the sub-algorithm into own state.
    00297     if ( result.isSuccess () &&
    00298          Gaudi::StateMachine::INITIALIZED <= FSMState() &&
    00299          myIAlg.isValid   () &&
    00300          Gaudi::StateMachine::INITIALIZED  > myIAlg->FSMState() )
    00301     {
    00302       StatusCode sc = myIAlg->sysInitialize() ;
    00303       if  ( sc.isFailure() ) { result = sc ; }
    00304     }
    00305
    00306     // propagate the sub-algorithm into own state.
    00307     if ( result.isSuccess () &&
    00308          Gaudi::StateMachine::RUNNING <= FSMState() &&
    00309          myIAlg.isValid   () &&
    00310          Gaudi::StateMachine::RUNNING  > myIAlg->FSMState() )
    00311     {
    00312       StatusCode sc = myIAlg->sysStart () ;
    00313       if  ( sc.isFailure() ) { result = sc ; }
    00314     }
    00315
    00316     //== Is it an Algorithm ?  Strange test...
    00317     if ( result.isSuccess() ) {
    00318       // TODO: (MCl) it is possible to avoid the dynamic_cast in most of the
    00319       //             cases by keeping the result of createSubAlgorithm.
    00320       Algorithm*  myAlg = dynamic_cast<Algorithm*>(myIAlg.get());
    00321       if (myAlg!=0) {
    00322         // Note: The reference counting is kept by the system of sub-algorithms
    00323         m_entries.push_back( AlgorithmEntry( myAlg ) );
    00324         if (msgLevel(MSG::DEBUG)) debug () << "Added algorithm " << theName << endmsg;
    00325       } else {
    00326         warning() << theName << " is not an Algorithm - failed dynamic_cast"
    00327                   << endmsg;
    00328         final = StatusCode::FAILURE;
    00329       }
    00330     } else {
    00331       warning() << "Unable to find or create " << theName << endmsg;
    00332       final = result;
    00333     }
    00334
    00335   }
    00336
    00337   release(appMgr).ignore();
    00338   release(jos).ignore();
    00339
    00340   //== Print the list of algorithms
    00341   MsgStream& msg = info();
    00342   if ( m_modeOR ) msg << "OR ";
    00343   msg << "Member list: ";
    00344   std::vector<AlgorithmEntry>::iterator itE;
    00345   for ( itE = m_entries.begin(); m_entries.end() != itE; itE++ ) {
    00346     Algorithm* myAlg = (*itE).algorithm();
    00347     std::string myAlgType = System::typeinfoName( typeid( *myAlg) ) ;
    00348     if ( myAlg->name() == myAlgType ) {
    00349       msg << myAlg->name();
    00350     } else {
    00351       msg << myAlgType << "/" << myAlg->name();
    00352     }
    00353     if ( itE+1 != m_entries.end() ) msg << ", ";
    00354   }
    00355   if ( "" != context() ) msg << ", with context '" << context() << "'";
    00356   if ( "" != rootInTES() ) msg << ", with rootInTES '" << rootInTES() << "'";
    00357   if ( 0.0 != globalTimeOffset() ) msg << ", with globalTimeOffset " << globalTimeOffset();
    00358   msg << endmsg;
    00359
    00360   return final;
    00361
    00362 }
    00363 #ifdef __ICC
    00364 // re-enable icc remark #1572
    00365 #pragma warning(pop)
    00366 #endif
    00367
    00368 //=========================================================================
    00369 //  Interface for the Property manager
    00370 //=========================================================================
    00371 void GaudiSequencer::membershipHandler ( Property& /* p */ )
    00372 {
    00373   // no action for not-yet initialized sequencer
    00374   if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) { return ; } // RETURN
    00375
    00376   decodeNames().ignore();
    00377
    00378   if  ( !m_measureTime ) { return ; }                                // RETURN
    00379
    00380   // add the entries into timer table:
    00381
    00382   if ( 0 == m_timerTool )
    00383   { m_timerTool = tool<ISequencerTimerTool>( "SequencerTimerTool" ) ; }
    00384
    00385   if ( m_timerTool->globalTiming() ) m_measureTime = true;
    00386
    00387   m_timer = m_timerTool->addTimer( name() );
    00388   m_timerTool->increaseIndent();
    00389
    00390   for ( std::vector<AlgorithmEntry>::iterator itE = m_entries.begin() ;
    00391         m_entries.end() != itE; ++itE )
    00392   {
    00393     itE->setTimer( m_timerTool->addTimer( itE->algorithm()->name() ) );
    00394   }
    00395
    00396   m_timerTool->decreaseIndent();
    00397
    00398 }
    00399 //=============================================================================

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines