![]() |
|
|
Generated: 18 Jul 2008 |
00001 // $Id: GaudiSequencer.cpp,v 1.17 2008/06/02 14:22:04 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" << endreq; 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" << endreq; 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_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" << endreq; 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" << endreq; 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" << endreq; 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 StatusCode GaudiSequencer::decodeNames( ) { 00187 00188 StatusCode final = StatusCode::SUCCESS; 00189 m_entries.clear(); 00190 00191 //== Get the "Context" option if in the file... 00192 IJobOptionsSvc* jos = svc<IJobOptionsSvc>( "JobOptionsSvc" ); 00193 bool addedContext = false; //= Have we added the context ? 00194 bool addedRootInTES = false; //= Have we added the rootInTES ? 00195 bool addedGlobalTimeOffset = false; //= Have we added the globalTimeOffset ? 00196 00197 00198 //= Get the Application manager, to see if algorithm exist 00199 IAlgManager* appMgr = svc<IAlgManager>("ApplicationMgr"); 00200 const std::vector<std::string>& nameVector = m_names.value(); 00201 std::vector<std::string>::const_iterator it; 00202 for ( it = nameVector.begin(); nameVector.end() != it; it++ ) { 00203 std::string theName( *it ); 00204 std::string theType( *it ); 00205 std::string::size_type slash = it->find_first_of( '/' ); 00206 if ( slash != std::string::npos ) { 00207 theType = it->substr( 0, slash ); 00208 theName = it->substr( slash+1 ); 00209 } 00210 //== handling of extensions to the name ??? 00211 00212 //== Check wether the specified algorithm already exists. If not, create it 00213 00214 IAlgorithm* myIAlg; 00215 StatusCode result = appMgr->getAlgorithm( theName, myIAlg ); 00216 if ( !result.isSuccess() ) { 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()) 00266 myIAlg = myAlg; 00267 } 00268 00269 //== Remove the property, in case this is not a GaudiAlgorithm... 00270 if ( addedContext ) { 00271 jos->removePropertyFromCatalogue( theName, "Context" ).ignore(); 00272 addedContext = false; 00273 } 00274 if ( addedRootInTES ) { 00275 jos->removePropertyFromCatalogue( theName, "RootInTES" ).ignore(); 00276 addedRootInTES = false; 00277 } 00278 if ( addedGlobalTimeOffset ) { 00279 jos->removePropertyFromCatalogue( theName, "GlobalTimeOffset" ).ignore(); 00280 addedGlobalTimeOffset = false; 00281 } 00282 00283 //== Is it an Algorithm ? Strange test... 00284 if ( result.isSuccess() ) { 00285 // TODO: (MCl) it is possible to avoid the dynamic_cast in most of the 00286 // cases by keeping the result of createSubAlgorithm. 00287 Algorithm* myAlg = dynamic_cast<Algorithm*>( myIAlg ); 00288 if (myAlg!=0) { 00289 m_entries.push_back( AlgorithmEntry( myAlg ) ); 00290 myAlg->addRef(); //== Indicate it is used. 00291 debug () << "Added algorithm " << theName << endreq; 00292 } else { 00293 warning() << theName << " is not an Algorithm - failed dynamic_cast" 00294 << endreq; 00295 final = StatusCode::FAILURE; 00296 } 00297 } else { 00298 warning() << "Unable to find or create " << theName << endreq; 00299 final = result; 00300 } 00301 00302 } 00303 release(appMgr).ignore(); 00304 release(jos).ignore(); 00305 00306 //== Print the list of algorithms 00307 MsgStream& msg = info(); 00308 if ( m_modeOR ) msg << "OR "; 00309 msg << "Member list: "; 00310 std::vector<AlgorithmEntry>::iterator itE; 00311 for ( itE = m_entries.begin(); m_entries.end() != itE; itE++ ) { 00312 Algorithm* myAlg = (*itE).algorithm(); 00313 std::string myAlgType = System::typeinfoName( typeid( *myAlg) ) ; 00314 if ( myAlg->name() == myAlgType ) { 00315 msg << myAlg->name(); 00316 } else { 00317 msg << myAlgType << "/" << myAlg->name(); 00318 } 00319 if ( itE+1 != m_entries.end() ) msg << ", "; 00320 } 00321 if ( "" != context() ) msg << ", with context '" << context() << "'"; 00322 if ( "" != rootInTES() ) msg << ", with rootInTES '" << rootInTES() << "'"; 00323 if ( 0.0 != globalTimeOffset() ) msg << ", with globalTimeOffset " << globalTimeOffset(); 00324 msg << endreq; 00325 00326 return final; 00327 00328 } 00329 00330 //========================================================================= 00331 // Interface for the Property manager 00332 //========================================================================= 00333 void GaudiSequencer::membershipHandler ( Property& ) { 00334 if ( isInitialized() ) decodeNames().ignore(); 00335 } 00336 //=============================================================================