| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
GaudiSequencer.cpp
Go to the documentation of this file.
1 // Include files
2
3 // from Gaudi
4 #include "GaudiKernel/IAlgManager.h"
5 #include "GaudiAlg/GaudiSequencer.h"
6 #include "GaudiAlg/ISequencerTimerTool.h"
7 #include "GaudiKernel/IJobOptionsSvc.h"
8
9 //-----------------------------------------------------------------------------
10 // Implementation file for class : GaudiSequencer
11 //
12 // 2004-05-13 : Olivier Callot
13 //-----------------------------------------------------------------------------
14
15 //=============================================================================
16 // Standard constructor, initializes variables
17 //=============================================================================
18 GaudiSequencer::GaudiSequencer( const std::string& name,
19 ISvcLocator* pSvcLocator)
20 : GaudiAlgorithm ( name , pSvcLocator )
21 , m_timerTool( 0 )
22 {
23 declareProperty( "Members" , m_names );
24 declareProperty( "ModeOR" , m_modeOR = false );
25 declareProperty( "IgnoreFilterPassed" , m_ignoreFilter = false );
26 declareProperty( "MeasureTime" , m_measureTime = false );
27 declareProperty( "ReturnOK" , m_returnOK = false );
28 declareProperty( "ShortCircuit" , m_shortCircuit = true );
29
30 m_names.declareUpdateHandler (& GaudiSequencer::membershipHandler, this );
31 }
32 //=============================================================================
33 // Destructor
34 //=============================================================================
35 GaudiSequencer::~GaudiSequencer() {}
36
37 //=============================================================================
38 // Initialisation. Check parameters
39 //=============================================================================
40 StatusCode GaudiSequencer::initialize() {
41 GaudiAlgorithm::initialize();
42
43 if (msgLevel(MSG::DEBUG)) debug() << "==> Initialise" << endmsg;
44
45 StatusCode status = decodeNames();
46 if ( !status.isSuccess() ) return status;
47
48 m_timerTool = tool<ISequencerTimerTool>( "SequencerTimerTool" );
49 if ( m_timerTool->globalTiming() ) m_measureTime = true;
50
51 if ( m_measureTime ) {
52 m_timer = m_timerTool->addTimer( name() );
53 m_timerTool->increaseIndent();
54 } else {
55 release( m_timerTool );
56 m_timerTool = 0;
57 }
58
59 //== Initialize the algorithms
60 std::vector<AlgorithmEntry>::iterator itE;
61 for ( itE = m_entries.begin(); m_entries.end() != itE; itE++ ) {
62 if ( m_measureTime ) {
63 itE->setTimer( m_timerTool->addTimer( itE->algorithm()->name() ) );
64 }
65
66 status = itE->algorithm()->sysInitialize();
67 if ( !status.isSuccess() ) {
68 return Error( "Can not initialize " + itE->algorithm()->name(),
69 status );
70 }
71 }
72 if ( m_measureTime ) m_timerTool->decreaseIndent();
73
74 return StatusCode::SUCCESS;
75 }
76
77 //=============================================================================
78 // Main execution
79 //=============================================================================
80 StatusCode GaudiSequencer::execute() {
81
82 if ( m_measureTime ) m_timerTool->start( m_timer );
83
84 if (msgLevel(MSG::DEBUG)) debug() << "==> Execute" << endmsg;
85
86 StatusCode result = StatusCode::SUCCESS;
87
88 bool seqPass = !m_modeOR; // for OR, result will be false, unless (at least) one is true
89 // for AND, result will be true, unless (at least) one is false
90 // also see comment below ....
91
92 std::vector<AlgorithmEntry>::const_iterator itE;
93 for ( itE = m_entries.begin(); m_entries.end() != itE; ++itE ) {
94 Algorithm* myAlg = itE->algorithm();
95 if ( ! myAlg->isEnabled() ) continue;
96 if ( ! myAlg->isExecuted() ) {
97 if ( m_measureTime ) m_timerTool->start( itE->timer() );
98 result = myAlg->sysExecute();
99 if ( m_measureTime ) m_timerTool->stop( itE->timer() );
100 myAlg->setExecuted( true );
101 if ( ! result.isSuccess() ) break; //== Abort and return bad status
102 }
103 //== Check the returned status
104 if ( !m_ignoreFilter ) {
105 bool passed = myAlg->filterPassed();
106 if (msgLevel(MSG::VERBOSE))
107 verbose() << "Algorithm " << myAlg->name() << " returned filter passed "
108 << (passed ? "true" : "false") << endmsg;
109 if ( itE->reverse() ) passed = !passed;
110
111
112 //== indicate our own result. For OR, exit as soon as true.
113 // If no more, will exit with false.
114 //== for AND, exit as soon as false. Else, will be true (default)
115
116 // if not short-circuiting, make sure we latch iPass to 'true' in
117 // OR mode (i.e. it is sufficient for one item to be true in order
118 // to be true at the end, and thus we start out at 'false'), and latch
119 // to 'false' in AND mode (i.e. it is sufficient for one item to
120 // be false to the false in the end, and thus we start out at 'true')
121 // -- i.e. we should not just blindly return the 'last' passed status!
122
123 // or to put it another way: in OR mode, we don't care about things
124 // which are false, as they leave our current state alone (provided
125 // we stared as 'false'!), and in AND mode, we keep our current
126 // state until someone returns 'false' (provided we started as 'true')
127 if ( m_modeOR ? passed : !passed ) {
128 seqPass = passed;
129 if (msgLevel(MSG::VERBOSE))
130 verbose() << "SeqPass is now " << (seqPass ? "true" : "false") << endmsg;
131 if (m_shortCircuit) break;
132 }
133 }
134
135 }
136 if (msgLevel(MSG::VERBOSE))
137 verbose() << "SeqPass is " << (seqPass ? "true" : "false") << endmsg;
138 if ( !m_ignoreFilter && !m_entries.empty() ) setFilterPassed( seqPass );
139 setExecuted( true );
140
141 if ( m_measureTime ) m_timerTool->stop( m_timer );
142
143 return m_returnOK ? StatusCode::SUCCESS : result;
144 }
145
146 //=============================================================================
147 // Finalize
148 //=============================================================================
149 StatusCode GaudiSequencer::finalize() {
150
151 if (msgLevel(MSG::DEBUG)) debug() << "==> Finalize" << endmsg;
152 return GaudiAlgorithm::finalize();
153 }
154
155 //=========================================================================
156 // Execute the beginRun of every algorithm
157 //=========================================================================
158 StatusCode GaudiSequencer::beginRun ( ) {
159
160 if ( !isEnabled() ) return StatusCode::SUCCESS;
161
162 if (msgLevel(MSG::DEBUG)) debug() << "==> beginRun" << endmsg;
163 return StatusCode::SUCCESS;
164 }
165
166 //=========================================================================
167 // Execute the endRun() of every algorithm
168 //=========================================================================
169 StatusCode GaudiSequencer::endRun ( ) {
170
171 if ( !isEnabled() ) return StatusCode::SUCCESS;
172
173 if (msgLevel(MSG::DEBUG)) debug() << "==> endRun" << endmsg;
174 return StatusCode::SUCCESS;
175 }
176
177 //=========================================================================
178 // reset the executed status of all members
179 //=========================================================================
180 void GaudiSequencer::resetExecuted ( ) {
181 Algorithm::resetExecuted();
182 // algorithm doesn't call resetExecuted of subalgos! should it???
183 std::vector<AlgorithmEntry>::const_iterator itE;
184 for ( itE = m_entries.begin(); m_entries.end() != itE; ++itE ) {
185 itE->algorithm()->resetExecuted();
186 }
187 }
188 //=========================================================================
189 // Decode the input names and fills the m_algs vector.
190 //=========================================================================
191 #ifdef __ICC
192 // disable icc remark #1572: floating-point equality and inequality comparisons are unreliable
193 // The comparison are meant
194 #pragma warning(push)
195 #pragma warning(disable:1572)
196 #endif
197 StatusCode GaudiSequencer::decodeNames( ) {
198
199 StatusCode final = StatusCode::SUCCESS;
200 m_entries.clear();
201
202 //== Get the "Context" option if in the file...
203 IJobOptionsSvc* jos = svc<IJobOptionsSvc>( "JobOptionsSvc" );
204 bool addedContext = false; //= Have we added the context ?
205 bool addedRootInTES = false; //= Have we added the rootInTES ?
206 bool addedGlobalTimeOffset = false; //= Have we added the globalTimeOffset ?
207
208
209 //= Get the Application manager, to see if algorithm exist
210 IAlgManager* appMgr = svc<IAlgManager>("ApplicationMgr");
211 const std::vector<std::string>& nameVector = m_names.value();
212 std::vector<std::string>::const_iterator it;
213 for ( it = nameVector.begin(); nameVector.end() != it; it++ ) {
214 const Gaudi::Utils::TypeNameString typeName(*it);
215 const std::string &theName = typeName.name();
216 const std::string &theType = typeName.type();
217
218 //== Check wether the specified algorithm already exists. If not, create it
219 StatusCode result = StatusCode::SUCCESS;
220 SmartIF<IAlgorithm> myIAlg = appMgr->algorithm(typeName, false); // do not create it now
221 if ( !myIAlg.isValid() ) {
222 //== Set the Context if not in the jobOptions list
223 if ( "" != context() ||
224 "" != rootInTES() ||
225 0.0 != globalTimeOffset() ) {
226 bool foundContext = false;
227 bool foundRootInTES = false;
228 bool foundGlobalTimeOffset = false;
229 const std::vector<const Property*>* properties = jos->getProperties( theName );
230 if ( 0 != properties ) {
231 // Iterate over the list to set the options
232 for ( std::vector<const Property*>::const_iterator itProp = properties->begin();
233 itProp != properties->end();
234 itProp++ ) {
235 const StringProperty* sp = dynamic_cast<const StringProperty*>(*itProp);
236 if ( 0 != sp ) {
237 if ( "Context" == (*itProp)->name() ) {
238 foundContext = true;
239 }
240 if ( "RootInTES" == (*itProp)->name() ) {
241 foundRootInTES = true;
242 }
243 if ( "GlobalTimeOffset" == (*itProp)->name() ) {
244 foundGlobalTimeOffset = true;
245 }
246 }
247 }
248 }
249 if ( !foundContext && "" != context() ) {
250 StringProperty contextProperty( "Context", context() );
251 jos->addPropertyToCatalogue( theName, contextProperty ).ignore();
252 addedContext = true;
253 }
254 if ( !foundRootInTES && "" != rootInTES() ) {
255 StringProperty rootInTESProperty( "RootInTES", rootInTES() );
256 jos->addPropertyToCatalogue( theName, rootInTESProperty ).ignore();
257 addedRootInTES = true;
258 }
259 if ( !foundGlobalTimeOffset && 0.0 != globalTimeOffset() ) {
260 DoubleProperty globalTimeOffsetProperty( "GlobalTimeOffset", globalTimeOffset() );
261 jos->addPropertyToCatalogue( theName, globalTimeOffsetProperty ).ignore();
262 addedGlobalTimeOffset = true;
263 }
264 }
265
266 Algorithm *myAlg = 0;
267 result = createSubAlgorithm( theType, theName, myAlg );
268 // (MCl) this should prevent bug #35199... even if I didn't manage to
269 // reproduce it with a simple test.
270 if (result.isSuccess()) myIAlg = myAlg;
271 } else {
272 Algorithm *myAlg = dynamic_cast<Algorithm*>(myIAlg.get());
273 if (myAlg) {
274 subAlgorithms()->push_back(myAlg);
275 // when the algorithm is not created, the ref count is short by one, so we have to fix it.
276 myAlg->addRef();
277 }
278 }
279
280 //== Remove the property, in case this is not a GaudiAlgorithm...
281 if ( addedContext ) {
282 jos->removePropertyFromCatalogue( theName, "Context" ).ignore();
283 addedContext = false;
284 }
285 if ( addedRootInTES ) {
286 jos->removePropertyFromCatalogue( theName, "RootInTES" ).ignore();
287 addedRootInTES = false;
288 }
289 if ( addedGlobalTimeOffset ) {
290 jos->removePropertyFromCatalogue( theName, "GlobalTimeOffset" ).ignore();
291 addedGlobalTimeOffset = false;
292 }
293
294 // propagate the sub-algorithm into own state.
295 if ( result.isSuccess () &&
296 Gaudi::StateMachine::INITIALIZED <= FSMState() &&
297 myIAlg.isValid () &&
298 Gaudi::StateMachine::INITIALIZED > myIAlg->FSMState() )
299 {
300 StatusCode sc = myIAlg->sysInitialize() ;
301 if ( sc.isFailure() ) { result = sc ; }
302 }
303
304 // propagate the sub-algorithm into own state.
305 if ( result.isSuccess () &&
306 Gaudi::StateMachine::RUNNING <= FSMState() &&
307 myIAlg.isValid () &&
308 Gaudi::StateMachine::RUNNING > myIAlg->FSMState() )
309 {
310 StatusCode sc = myIAlg->sysStart () ;
311 if ( sc.isFailure() ) { result = sc ; }
312 }
313
314 //== Is it an Algorithm ? Strange test...
315 if ( result.isSuccess() ) {
316 // TODO: (MCl) it is possible to avoid the dynamic_cast in most of the
317 // cases by keeping the result of createSubAlgorithm.
318 Algorithm* myAlg = dynamic_cast<Algorithm*>(myIAlg.get());
319 if (myAlg!=0) {
320 // Note: The reference counting is kept by the system of sub-algorithms
321 m_entries.push_back( AlgorithmEntry( myAlg ) );
322 if (msgLevel(MSG::DEBUG)) debug () << "Added algorithm " << theName << endmsg;
323 } else {
324 warning() << theName << " is not an Algorithm - failed dynamic_cast"
325 << endmsg;
326 final = StatusCode::FAILURE;
327 }
328 } else {
329 warning() << "Unable to find or create " << theName << endmsg;
330 final = result;
331 }
332
333 }
334
335 release(appMgr).ignore();
336 release(jos).ignore();
337
338 //== Print the list of algorithms
339 MsgStream& msg = info();
340 if ( m_modeOR ) msg << "OR ";
341 msg << "Member list: ";
342 std::vector<AlgorithmEntry>::iterator itE;
343 for ( itE = m_entries.begin(); m_entries.end() != itE; itE++ ) {
344 Algorithm* myAlg = (*itE).algorithm();
345 std::string myAlgType = System::typeinfoName( typeid( *myAlg) ) ;
346 if ( myAlg->name() == myAlgType ) {
347 msg << myAlg->name();
348 } else {
349 msg << myAlgType << "/" << myAlg->name();
350 }
351 if ( itE+1 != m_entries.end() ) msg << ", ";
352 }
353 if ( "" != context() ) msg << ", with context '" << context() << "'";
354 if ( "" != rootInTES() ) msg << ", with rootInTES '" << rootInTES() << "'";
355 if ( 0.0 != globalTimeOffset() ) msg << ", with globalTimeOffset " << globalTimeOffset();
356 msg << endmsg;
357
358 return final;
359
360 }
361 #ifdef __ICC
362 // re-enable icc remark #1572
363 #pragma warning(pop)
364 #endif
365
366 //=========================================================================
367 // Interface for the Property manager
368 //=========================================================================
369 void GaudiSequencer::membershipHandler ( Property& /* p */ )
370 {
371 // no action for not-yet initialized sequencer
372 if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) { return ; } // RETURN
373
374 decodeNames().ignore();
375
376 if ( !m_measureTime ) { return ; } // RETURN
377
378 // add the entries into timer table:
379
380 if ( 0 == m_timerTool )
381 { m_timerTool = tool<ISequencerTimerTool>( "SequencerTimerTool" ) ; }
382
383 if ( m_timerTool->globalTiming() ) m_measureTime = true;
384
385 m_timer = m_timerTool->addTimer( name() );
386 m_timerTool->increaseIndent();
387
388 for ( std::vector<AlgorithmEntry>::iterator itE = m_entries.begin() ;
389 m_entries.end() != itE; ++itE )
390 {
391 itE->setTimer( m_timerTool->addTimer( itE->algorithm()->name() ) );
392 }
393
394 m_timerTool->decreaseIndent();
395
396 }
397 //=============================================================================