Gaudi Framework, version v22r0

Home   Generated: 9 Feb 2011

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   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   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       }
00106       //== Check the returned status
00107       if ( !m_ignoreFilter ) {
00108         bool passed = myAlg->filterPassed();
00109       if ( itE->reverse() ) passed = !passed;
00110 
00111         //== indicate our own result. For OR, exit as soon as true.
00112         //        If no more, will exit with false.
00113         //== for AND, exit as soon as false. Else, will be true (default)
00114 
00115       // if not short-circuiting, make sure we latch iPass to 'true' in
00116       // OR mode (i.e. it is sufficient for one item to be true in order
00117       // to be true at the end, and thus we start out at 'false'), and latch
00118       // to 'false' in AND mode (i.e. it is sufficient for one item to
00119       // be false to the false in the end, and thus we start out at 'true')
00120       // -- i.e. we should not just blindly return the 'last' passed status!
00121 
00122       // or to put it another way: in OR mode, we don't care about things
00123       // which are false, as they leave our current state alone (provided
00124       // we stared as 'false'!), and in AND mode, we keep our current
00125       // state until someone returns 'false' (provided we started as 'true')
00126       if ( m_modeOR ? passed : !passed ) {
00127         seqPass = passed;
00128         if (m_shortCircuit) break;
00129       }
00130     }
00131 
00132   }
00133   if ( !m_ignoreFilter && !m_entries.empty() ) setFilterPassed( seqPass );
00134   setExecuted( true );
00135 
00136   if ( m_measureTime ) m_timerTool->stop( m_timer );
00137 
00138   return m_returnOK ? StatusCode::SUCCESS : result;
00139 }
00140 
00141 //=============================================================================
00142 //  Finalize
00143 //=============================================================================
00144 StatusCode GaudiSequencer::finalize() {
00145 
00146   debug() << "==> Finalize" << endmsg;
00147   return  GaudiAlgorithm::finalize();
00148 }
00149 
00150 //=========================================================================
00151 //  Execute the beginRun of every algorithm
00152 //=========================================================================
00153 StatusCode GaudiSequencer::beginRun ( ) {
00154 
00155   if ( !isEnabled() ) return StatusCode::SUCCESS;
00156 
00157   debug() << "==> beginRun" << endmsg;
00158   return StatusCode::SUCCESS;
00159 }
00160 
00161 //=========================================================================
00162 //  Execute the endRun() of every algorithm
00163 //=========================================================================
00164 StatusCode GaudiSequencer::endRun ( ) {
00165 
00166   if ( !isEnabled() ) return StatusCode::SUCCESS;
00167 
00168   debug() << "==> endRun" << endmsg;
00169   return StatusCode::SUCCESS;
00170 }
00171 
00172 //=========================================================================
00173 // reset the executed status of all members
00174 //=========================================================================
00175 void GaudiSequencer::resetExecuted ( ) {
00176   Algorithm::resetExecuted();
00177   // algorithm doesn't call resetExecuted of subalgos! should it???
00178   std::vector<AlgorithmEntry>::const_iterator itE;
00179   for ( itE = m_entries.begin(); m_entries.end() != itE; ++itE ) {
00180     itE->algorithm()->resetExecuted();
00181   }
00182 }
00183 //=========================================================================
00184 //  Decode the input names and fills the m_algs vector.
00185 //=========================================================================
00186 #ifdef __ICC
00187 // disable icc remark #1572: floating-point equality and inequality comparisons are unreliable
00188 //   The comparison are meant
00189 #pragma warning(push)
00190 #pragma warning(disable:1572)
00191 #endif
00192 StatusCode GaudiSequencer::decodeNames( )  {
00193 
00194   StatusCode final = StatusCode::SUCCESS;
00195   m_entries.clear();
00196 
00197   //== Get the "Context" option if in the file...
00198   IJobOptionsSvc* jos = svc<IJobOptionsSvc>( "JobOptionsSvc" );
00199   bool addedContext = false;  //= Have we added the context ?
00200   bool addedRootInTES = false;  //= Have we added the rootInTES ?
00201   bool addedGlobalTimeOffset = false;  //= Have we added the globalTimeOffset ?
00202 
00203 
00204   //= Get the Application manager, to see if algorithm exist
00205   IAlgManager* appMgr = svc<IAlgManager>("ApplicationMgr");
00206   const std::vector<std::string>& nameVector = m_names.value();
00207   std::vector<std::string>::const_iterator it;
00208   for ( it = nameVector.begin(); nameVector.end() != it; it++ ) {
00209     const Gaudi::Utils::TypeNameString typeName(*it);
00210     const std::string &theName = typeName.name();
00211     const std::string &theType = typeName.type();
00212 
00213     //== Check wether the specified algorithm already exists. If not, create it
00214     StatusCode result = StatusCode::SUCCESS;
00215     SmartIF<IAlgorithm> myIAlg = appMgr->algorithm(typeName, false); // do not create it now
00216     if ( !myIAlg.isValid() ) {
00217       //== Set the Context if not in the jobOptions list
00218       if ( ""  != context() ||
00219            ""  != rootInTES() ||
00220            0.0 != globalTimeOffset() ) {
00221         bool foundContext = false;
00222         bool foundRootInTES = false;
00223         bool foundGlobalTimeOffset = false;
00224         const std::vector<const Property*>* properties = jos->getProperties( theName );
00225         if ( 0 != properties ) {
00226           // Iterate over the list to set the options
00227           for ( std::vector<const Property*>::const_iterator itProp = properties->begin();
00228                itProp != properties->end();
00229                itProp++ )   {
00230             const StringProperty* sp = dynamic_cast<const StringProperty*>(*itProp);
00231             if ( 0 != sp )    {
00232               if ( "Context" == (*itProp)->name() ) {
00233                 foundContext = true;
00234               }
00235               if ( "RootInTES" == (*itProp)->name() ) {
00236                 foundRootInTES = true;
00237               }
00238               if ( "GlobalTimeOffset" == (*itProp)->name() ) {
00239                 foundGlobalTimeOffset = true;
00240               }
00241             }
00242           }
00243         }
00244         if ( !foundContext && "" != context() ) {
00245           StringProperty contextProperty( "Context", context() );
00246           jos->addPropertyToCatalogue( theName, contextProperty ).ignore();
00247           addedContext = true;
00248         }
00249         if ( !foundRootInTES && "" != rootInTES() ) {
00250           StringProperty rootInTESProperty( "RootInTES", rootInTES() );
00251           jos->addPropertyToCatalogue( theName, rootInTESProperty ).ignore();
00252           addedRootInTES = true;
00253         }
00254         if ( !foundGlobalTimeOffset && 0.0 != globalTimeOffset() ) {
00255           DoubleProperty globalTimeOffsetProperty( "GlobalTimeOffset", globalTimeOffset() );
00256           jos->addPropertyToCatalogue( theName, globalTimeOffsetProperty ).ignore();
00257           addedGlobalTimeOffset = true;
00258         }
00259       }
00260 
00261       Algorithm *myAlg = 0;
00262       result = createSubAlgorithm( theType, theName, myAlg );
00263       // (MCl) this should prevent bug #35199... even if I didn't manage to
00264       // reproduce it with a simple test.
00265       if (result.isSuccess()) myIAlg = myAlg;
00266     } else {
00267       Algorithm *myAlg = dynamic_cast<Algorithm*>(myIAlg.get());
00268       if (myAlg) {
00269         subAlgorithms()->push_back(myAlg);
00270         // when the algorithm is not created, the ref count is short by one, so we have to fix it.
00271         myAlg->addRef();
00272       }
00273     }
00274 
00275     //== Remove the property, in case this is not a GaudiAlgorithm...
00276     if ( addedContext ) {
00277       jos->removePropertyFromCatalogue( theName, "Context" ).ignore();
00278       addedContext = false;
00279     }
00280     if ( addedRootInTES ) {
00281       jos->removePropertyFromCatalogue( theName, "RootInTES" ).ignore();
00282       addedRootInTES = false;
00283     }
00284     if ( addedGlobalTimeOffset ) {
00285       jos->removePropertyFromCatalogue( theName, "GlobalTimeOffset" ).ignore();
00286       addedGlobalTimeOffset = false;
00287     }
00288 
00289     // propagate the sub-algorithm into own state. 
00290     if ( result.isSuccess () && 
00291          Gaudi::StateMachine::INITIALIZED <= FSMState() && 
00292          myIAlg.isValid   () && 
00293          Gaudi::StateMachine::INITIALIZED  > myIAlg->FSMState() ) 
00294     {
00295       StatusCode sc = myIAlg->sysInitialize() ;
00296       if  ( sc.isFailure() ) { result = sc ; }
00297     }
00298     
00299     // propagate the sub-algorithm into own state. 
00300     if ( result.isSuccess () && 
00301          Gaudi::StateMachine::RUNNING <= FSMState() && 
00302          myIAlg.isValid   () && 
00303          Gaudi::StateMachine::RUNNING  > myIAlg->FSMState() ) 
00304     {
00305       StatusCode sc = myIAlg->sysStart () ;
00306       if  ( sc.isFailure() ) { result = sc ; }
00307     }
00308 
00309     //== Is it an Algorithm ?  Strange test...
00310     if ( result.isSuccess() ) {
00311       // TODO: (MCl) it is possible to avoid the dynamic_cast in most of the
00312       //             cases by keeping the result of createSubAlgorithm.
00313       Algorithm*  myAlg = dynamic_cast<Algorithm*>(myIAlg.get());
00314       if (myAlg!=0) {
00315         // Note: The reference counting is kept by the system of sub-algorithms
00316         m_entries.push_back( AlgorithmEntry( myAlg ) );
00317         debug () << "Added algorithm " << theName << endmsg;
00318       } else {
00319         warning() << theName << " is not an Algorithm - failed dynamic_cast"
00320                   << endmsg;
00321         final = StatusCode::FAILURE;
00322       }
00323     } else {
00324       warning() << "Unable to find or create " << theName << endmsg;
00325       final = result;
00326     }
00327 
00328   }
00329 
00330   release(appMgr).ignore();
00331   release(jos).ignore();
00332 
00333   //== Print the list of algorithms
00334   MsgStream& msg = info();
00335   if ( m_modeOR ) msg << "OR ";
00336   msg << "Member list: ";
00337   std::vector<AlgorithmEntry>::iterator itE;
00338   for ( itE = m_entries.begin(); m_entries.end() != itE; itE++ ) {
00339     Algorithm* myAlg = (*itE).algorithm();
00340     std::string myAlgType = System::typeinfoName( typeid( *myAlg) ) ;
00341     if ( myAlg->name() == myAlgType ) {
00342       msg << myAlg->name();
00343     } else {
00344       msg << myAlgType << "/" << myAlg->name();
00345     }
00346     if ( itE+1 != m_entries.end() ) msg << ", ";
00347   }
00348   if ( "" != context() ) msg << ", with context '" << context() << "'";
00349   if ( "" != rootInTES() ) msg << ", with rootInTES '" << rootInTES() << "'";
00350   if ( 0.0 != globalTimeOffset() ) msg << ", with globalTimeOffset " << globalTimeOffset();
00351   msg << endmsg;
00352 
00353   return final;
00354 
00355 }
00356 #ifdef __ICC
00357 // re-enable icc remark #1572
00358 #pragma warning(pop)
00359 #endif
00360 
00361 //=========================================================================
00362 //  Interface for the Property manager
00363 //=========================================================================
00364 void GaudiSequencer::membershipHandler ( Property& /* p */ ) 
00365 {
00366   // no action for not-yet initialized sequencer 
00367   if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) { return ; } // RETURN 
00368   
00369   decodeNames().ignore();
00370   
00371   if  ( !m_measureTime ) { return ; }                                // RETURN 
00372   
00373   // add the entries into timer table: 
00374   
00375   if ( 0 == m_timerTool ) 
00376   { m_timerTool = tool<ISequencerTimerTool>( "SequencerTimerTool" ) ; }
00377   
00378   if ( m_timerTool->globalTiming() ) m_measureTime = true;
00379   
00380   m_timer = m_timerTool->addTimer( name() );
00381   m_timerTool->increaseIndent();
00382   
00383   for ( std::vector<AlgorithmEntry>::iterator itE = m_entries.begin() ; 
00384         m_entries.end() != itE; ++itE ) 
00385   {
00386     itE->setTimer( m_timerTool->addTimer( itE->algorithm()->name() ) );
00387   }
00388   
00389   m_timerTool->decreaseIndent();
00390   
00391 }
00392 //=============================================================================
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Wed Feb 9 16:24:48 2011 for Gaudi Framework, version v22r0 by Doxygen version 1.6.2 written by Dimitri van Heesch, © 1997-2004