Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 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

Generated at Thu Jun 28 2012 23:27:15 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004