| The Gaudi Framework v32r1 (f65d50dc)

ToolSvc.cpp
Go to the documentation of this file.
1 // Include Files
2 #include "ToolSvc.h"
3 #include "GaudiKernel/AlgTool.h"
4 #include "GaudiKernel/GaudiException.h"
5 #include "GaudiKernel/IAlgorithm.h"
6 #include "GaudiKernel/IHistorySvc.h"
7 #include "GaudiKernel/ISvcLocator.h"
8 #include "GaudiKernel/MsgStream.h"
9 #include "GaudiKernel/Service.h"
10 #include "boost/algorithm/string/erase.hpp"
11 #include "boost/algorithm/string/predicate.hpp"
12 #include "boost/circular_buffer.hpp"
13 #include <algorithm>
14 #include <cassert>
15 #include <functional>
16 #include <map>
17 #include <numeric>
18 #include <string>
19 namespace ba = boost::algorithm;
20
21 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
22 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
23
24 namespace {
25 //------------------------------------------------------------------------------
26 template <typename C>
27 unsigned long totalRefCount( const C& toolList )
28 //------------------------------------------------------------------------------
29 {
30 return std::accumulate( std::begin( toolList ), std::end( toolList ), 0ul,
31 [&]( unsigned long count, const IAlgTool* tool ) { return count + tool->refCount(); } );
32 }
33
35 template <typename C>
36 void remove( C& c, typename C::const_reference i ) {
37 c.erase( std::remove( std::begin( c ), std::end( c ), i ), std::end( c ) );
38 }
39 } // namespace
40
41 // Instantiation of a static factory class used by clients to create
42 // instances of this service
43 DECLARE_COMPONENT( ToolSvc )
44
45 //------------------------------------------------------------------------------
46 ToolSvc::~ToolSvc() {
47 // tell the remaining observers that we're gone, and forget about unregistering..
48 std::for_each( std::begin( m_observers ), std::end( m_observers ),
49 [&]( IToolSvc::Observer* obs ) { obs->setUnregister( {} ); } );
50 }
51 //------------------------------------------------------------------------------
52 StatusCode ToolSvc::initialize()
53 //------------------------------------------------------------------------------
54 {
55
56 // initialize the Service Base class
57 StatusCode status = Service::initialize();
58 if ( UNLIKELY( status.isFailure() ) ) {
59 error() << "Unable to initialize the Service" << endmsg;
60 return status;
61 }
62
63 // set my own (ToolSvc) properties via the jobOptionService
64 if ( UNLIKELY( setProperties().isFailure() ) ) {
65 error() << "Unable to set base properties" << endmsg;
66 return StatusCode::FAILURE;
67 }
68
69 return status;
70 }
71
72 //------------------------------------------------------------------------------
73 StatusCode ToolSvc::finalize()
74 //------------------------------------------------------------------------------
75 {
76 // Finalize and delete all left-over tools. Normally all tools created with
77 // ToolSvc are left over, since ToolSvc holds a refCount (via AlgTool ctor).
78 // Several cases need to be covered:
79 // 1) Simple dependencies: no circular dependencies between tools,
80 // and tools not using other tools
81 // 2) Tools-using-tools (but no circular dependencies)
82 // a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
83 // b) release() is called in the tool destructor (e.g. via ToolHandle)
84 // 3) Circular dependencies between tools
85 // a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
86 // b) release() is called in the tool destructor (e.g. via ToolHandle)
87 // 4) In addition to each of the above cases, refCounting of a particular tool
88 // might not have been done correctly in the code. Typically release()
89 // is not called, so we are left with a too high refCount.
90 // What to do with those, and how to avoid a crash while handling them...
91
100 info() << "Removing all tools created by ToolSvc" << endmsg;
101
102 // Print out list of tools
103 ON_DEBUG {
104 auto& log = debug();
105 log << " Tool List : ";
106 for ( const auto& iTool : m_instancesTools ) { log << iTool->name() << ":" << iTool->refCount() << " "; }
107 log << endmsg;
108 }
109
110 //
111 // first pass: Finalize all tools (but don't delete them)
112 //
125 boost::circular_buffer<IAlgTool*> finalizedTools( m_instancesTools.size() ); // list of tools that have been finalized
126 bool fail( false );
127 size_t toolCount = m_instancesTools.size();
128 unsigned long startRefCount = 0;
129 unsigned long endRefCount = totalToolRefCount();
130 unsigned long startMinRefCount = 0;
131 unsigned long endMinRefCount = minimumToolRefCount();
132 while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
133 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
134 debug() << toolCount << " tools left to finalize. Summed refCounts: " << endRefCount << endmsg;
135 debug() << "Will finalize tools with refCount <= " << endMinRefCount << endmsg;
136 }
137 startMinRefCount = endMinRefCount;
138 startRefCount = endRefCount;
139 unsigned long maxLoop = toolCount + 1;
140 while ( --maxLoop > 0 && !m_instancesTools.empty() ) {
141 IAlgTool* pTool = m_instancesTools.back();
142 // removing tool from list makes ToolSvc::releaseTool( IAlgTool* ) a noop
143 m_instancesTools.pop_back();
144 unsigned long count = pTool->refCount();
145 // cache tool name
146 const std::string& toolName = pTool->name();
147 if ( count <= startMinRefCount ) {
148 ON_DEBUG debug() << " Performing finalization of " << toolName << " (refCount " << count << ")" << endmsg;
149 // finalize of one tool may trigger a release of another tool
150 // pTool->sysFinalize().ignore();
151 if ( !finalizeTool( pTool ).isSuccess() ) {
152 warning() << " FAILURE finalizing " << toolName << endmsg;
153 fail = true;
154 }
155 // postpone deletion
156 finalizedTools.push_back( pTool );
157 } else {
158 // Place back at the front of the list to try again later
159 // ToolSvc::releaseTool( IAlgTool* ) remains active for this tool
160 ON_DEBUG debug() << " Delaying finalization of " << toolName << " (refCount " << count << ")" << endmsg;
161 m_instancesTools.insert( std::begin( m_instancesTools ), pTool );
162 }
163 } // end of inner loop
164 toolCount = m_instancesTools.size();
165 endRefCount = totalToolRefCount();
166 endMinRefCount = minimumToolRefCount();
167 }; // end of outer loop
168
169 //
170 // Second pass: Delete all finalized tools
171 //
172 // Delete in the order of increasing number of refCounts.
173 // Loop over tools in the same order as the order in which they were finalized.
174 // All tools in the list of finalized tools are no longer in the instancesTools list.
175 // If a tool destructor calls releaseTool() on another tool, this will have no
176 // effect on the 'other tool' if this 'other tool' is in the list of finalized tools.
177 // If this 'other tool' is still in the instancesTools list, it may trigger finalization
178 // (in releaseTool()), deletion and removal from the instancesTools list.
179 // Therefore, the check on non-finalised tools should happen *after* the deletion
180 // of the finalized tools.
181 ON_DEBUG debug() << "Deleting " << finalizedTools.size() << " finalized tools" << endmsg;
182 auto maxLoop = totalRefCount( finalizedTools ) + 1;
183 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
184 IAlgTool* pTool = finalizedTools.front();
185 finalizedTools.pop_front();
186 auto count = pTool->refCount();
187 if ( count == 1 ) {
188 ON_DEBUG debug() << " Performing deletion of " << pTool->name() << endmsg;
189 } else {
190 ON_VERBOSE verbose() << " Delaying deletion of " << pTool->name() << " (refCount " << count << ")" << endmsg;
191 // Move to the end when refCount still not zero
192 finalizedTools.push_back( pTool );
193 }
194 // do a forced release
195 pTool->release();
196 }
197
198 // Error if by now not all tools are properly finalised
199 if ( !m_instancesTools.empty() ) {
200 error() << "Unable to finalize and delete the following tools : ";
201 for ( const auto& iTool : m_instancesTools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
202 error() << endmsg;
203 }
204
205 // by now, all tools should be deleted and removed.
206 if ( !finalizedTools.empty() ) {
207 error() << "Failed to delete the following " << finalizedTools.size()
208 << " finalized tools. Bug in ToolSvc::finalize()?: ";
209 for ( const auto& iTool : finalizedTools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
210 error() << endmsg;
211 }
212
213 if ( m_pHistorySvc ) m_pHistorySvc->release();
214
215 // Finalize this specific service
216 return ( Service::finalize().isSuccess() && !fail ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
217 }
218
219 // ===================================================================================
223 // ===================================================================================
224 namespace {
225 static const std::string s_PUBLIC = ":PUBLIC";
226 }
227
228 //------------------------------------------------------------------------------
229 StatusCode ToolSvc::retrieve( const std::string& tooltype, const InterfaceID& iid, IAlgTool*& tool,
230 const IInterface* parent, bool createIf )
231 //------------------------------------------------------------------------------
232 {
233 // check for tools, which by name are required to be public:
234 if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
235 // parent for PUBLIC tool is 'this', i.e. ToolSvc
236 return retrieve( ba::erase_tail_copy( tooltype, s_PUBLIC.size() ), iid, tool, this, createIf );
237 }
238
239 // protect against empty type
240 if ( tooltype.empty() ) {
241 error() << "retrieve(): No Tool Type/Name given" << endmsg;
242 return StatusCode::FAILURE;
243 }
244 auto pos = tooltype.find( '/' );
245 if ( std::string::npos == pos ) { return retrieve( tooltype, tooltype, iid, tool, parent, createIf ); }
246 return retrieve( tooltype.substr( 0, pos ), tooltype.substr( pos + 1 ), iid, tool, parent, createIf );
247 }
248
249 // ===================================================================================
250
251 //------------------------------------------------------------------------------
252 StatusCode ToolSvc::retrieve( const std::string& tooltype, const std::string& toolname, const InterfaceID& iid,
253 IAlgTool*& tool, const IInterface* parent, bool createIf )
254 //------------------------------------------------------------------------------
255 {
256 // check the applicability of another method:
257 // ignore the provided name if it is empty or the type contains a name
258 if ( toolname.empty() || ( std::string::npos != tooltype.find( '/' ) ) ) {
259 return retrieve( tooltype, iid, tool, parent, createIf );
260 }
261
262 // check for tools, which by name are required to be public:
263 if ( ba::ends_with( toolname, s_PUBLIC ) ) {
264 // parent for PUBLIC tool is this, i.e. ToolSvc
265 return retrieve( tooltype, ba::erase_tail_copy( toolname, s_PUBLIC.size() ), iid, tool, this, createIf );
266 }
267
268 std::lock_guard<CallMutex> lock( m_mut );
269
270 IAlgTool* itool = nullptr;
271 StatusCode sc( StatusCode::FAILURE );
272
273 tool = nullptr;
274
275 // If parent is not specified it means it is the ToolSvc itself
276 if ( !parent ) parent = this;
277 const std::string fullname = nameTool( toolname, parent );
278
279 // Find tool in list of those already existing, and tell its
280 // interface that it has been used one more time
281 auto it = std::find_if( std::begin( m_instancesTools ), std::end( m_instancesTools ),
282 [&]( const IAlgTool* i ) { return i->name() == fullname && i->parent() == parent; } );
283 if ( it != std::end( m_instancesTools ) ) {
284 ON_DEBUG debug() << "Retrieved tool " << toolname << " with parent " << parent << endmsg;
285 itool = *it;
286 }
287
288 if ( !itool ) {
289 // Instances of this tool do not exist, create an instance if desired
290 // otherwise return failure
291 if ( UNLIKELY( !createIf ) ) {
292 warning() << "Tool " << toolname << " not found and creation not requested" << endmsg;
293 return sc;
294 }
295 sc = create( tooltype, toolname, parent, itool );
296 if ( sc.isFailure() ) { return sc; }
297 }
298
299 // Get the right interface of it
300 sc = itool->queryInterface( iid, pp_cast<void>( &tool ) );
301 if ( UNLIKELY( sc.isFailure() ) ) {
302 error() << "Tool " << toolname << " either does not implement the correct interface, or its version is incompatible"
303 << endmsg;
304 return sc;
305 }
306
310 std::for_each( std::begin( m_observers ), std::end( m_observers ),
311 [&]( IToolSvc::Observer* obs ) { obs->onRetrieve( itool ); } );
312 return sc;
313 }
314 //------------------------------------------------------------------------------
315 std::vector<std::string> ToolSvc::getInstances( const std::string& toolType )
316 //------------------------------------------------------------------------------
317 {
318
319 std::lock_guard<CallMutex> lock( m_mut );
320 std::vector<std::string> tools;
321 for ( const auto& tool : m_instancesTools ) {
322 if ( tool->type() == toolType ) tools.push_back( tool->name() );
323 }
324 return tools;
325 }
326 //------------------------------------------------------------------------------
327 std::vector<std::string> ToolSvc::getInstances() const
328 //------------------------------------------------------------------------------
329 {
330 std::lock_guard<CallMutex> lock( m_mut );
331 std::vector<std::string> tools{m_instancesTools.size()};
332 std::transform( std::begin( m_instancesTools ), std::end( m_instancesTools ), std::begin( tools ),
333 []( const IAlgTool* t ) { return t->name(); } );
334 return tools;
335 }
336 //------------------------------------------------------------------------------
337 std::vector<IAlgTool*> ToolSvc::getTools() const
338 //------------------------------------------------------------------------------
339 {
340 std::lock_guard<CallMutex> lock( m_mut );
341 return std::vector<IAlgTool*>{std::begin( m_instancesTools ), std::end( m_instancesTools )};
342 }
343 //------------------------------------------------------------------------------
344 StatusCode ToolSvc::releaseTool( IAlgTool* tool )
345 //------------------------------------------------------------------------------
346 {
347 std::lock_guard<CallMutex> lock( m_mut );
348 StatusCode sc( StatusCode::SUCCESS );
349 // test if tool is in known list (protect trying to access a previously deleted tool)
350 if ( m_instancesTools.rend() != std::find( m_instancesTools.rbegin(), m_instancesTools.rend(), tool ) ) {
351 unsigned long count = tool->refCount();
352 if ( count == 1 ) {
353 // finalize the tool
354
355 if ( Gaudi::StateMachine::OFFLINE == m_targetState ) {
356 // We are being called during ToolSvc::finalize()
357 // message format matches the one in ToolSvc::finalize()
358 debug() << " Performing finalization of " << tool->name() << " (refCount " << count << ")" << endmsg;
359 // message format matches the one in ToolSvc::finalize()
360 debug() << " Performing deletion of " << tool->name() << endmsg;
361 } else {
362 debug() << "Performing finalization and deletion of " << tool->name() << endmsg;
363 }
364 sc = finalizeTool( tool );
365 // remove from known tools...
366 remove( m_instancesTools, tool );
367 }
368 tool->release();
369 }
370 return sc;
371 }
372
373 //------------------------------------------------------------------------------
374 StatusCode ToolSvc::create( const std::string& tooltype, const IInterface* parent, IAlgTool*& tool )
375 //------------------------------------------------------------------------------
376 {
377 const std::string& toolname = tooltype;
378 return create( tooltype, toolname, parent, tool );
379 }
380
381 namespace {
384 template <typename T>
385 class ToolCreateGuard {
387 T& m_tools;
389 std::unique_ptr<IAlgTool> m_tool;
390
391 public:
392 explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
393 // we don't get a move constructor by default because we
394 // have a non-trivial destructor... However, the default
395 // one is just fine...
396 ToolCreateGuard( ToolCreateGuard&& ) noexcept = default;
398 void create( const std::string& tooltype, const std::string& fullname, const IInterface* parent ) {
399 // remove previous content
400 if ( m_tool ) remove( m_tools, m_tool.get() );
401 m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
402 // set new content
403 if ( m_tool ) m_tools.push_back( m_tool.get() );
404 }
406 IAlgTool* get() { return m_tool.get(); }
407 IAlgTool* operator->() const {
408 assert( m_tool );
409 return m_tool.get();
410 }
412 IAlgTool* release() { return m_tool.release(); }
414 ~ToolCreateGuard() {
415 if ( m_tool ) remove( m_tools, m_tool.get() );
416 }
417 };
418
419 template <typename C>
420 ToolCreateGuard<C> make_toolCreateGuard( C& c ) {
421 return ToolCreateGuard<C>{c};
422 }
423 } // namespace
424
425 //------------------------------------------------------------------------------
433 StatusCode ToolSvc::create( const std::string& tooltype, const std::string& toolname, const IInterface* parent,
434 IAlgTool*& tool )
435 //------------------------------------------------------------------------------
436 {
437
438 std::lock_guard<CallMutex> lock( m_mut );
439 // protect against empty type
440 if ( UNLIKELY( tooltype.empty() ) ) {
441 error() << "create(): No Tool Type given" << endmsg;
442 return StatusCode::FAILURE;
443 }
444
445 // If parent has not been specified, assume it is the ToolSvc
446 if ( !parent ) parent = this;
447
448 tool = nullptr;
449 // Automatically deletes the tool if not explicitly kept (i.e. on success).
450 // The tool is removed from the list of known tools too.
451 auto toolguard = make_toolCreateGuard( m_instancesTools );
452
453 // Check if the tool already exist : this could happen with clones
454 std::string fullname = nameTool( toolname, parent );
455 if ( UNLIKELY( existsTool( fullname ) ) ) {
456 // Now check if the parent is the same. This allows for clones
457 for ( IAlgTool* iAlgTool : m_instancesTools ) {
458 if ( iAlgTool->name() == toolname && iAlgTool->parent() == parent ) {
459 // The tool exist with this name, type and parent: this is bad!
460 // This excludes the possibility of cloning public tools intrinsecally
461 error() << "Tool " << fullname << " already exists with the same parent" << endmsg;
462 if ( parent == this )
463 error() << "... In addition, the parent is the ToolSvc: public tools cannot be cloned!" << endmsg;
464
465 return StatusCode::FAILURE;
466 }
467 }
468 ON_DEBUG debug() << "Creating clone of " << fullname << endmsg;
469 }
470 // instantiate the tool using the factory
471 try {
472 toolguard.create( tooltype, fullname, parent );
473 if ( UNLIKELY( !toolguard.get() ) ) {
474 error() << "Cannot create tool " << tooltype << " (No factory found)" << endmsg;
475 return StatusCode::FAILURE;
476 }
477 } catch ( const GaudiException& Exception ) {
478 // (1) perform the printout of message
479 fatal() << "Exception with tag=" << Exception.tag() << " is caught whilst instantiating tool '" << tooltype << "'"
480 << endmsg;
481 // (2) print the exception itself
482 // (NB! - GaudiException is a linked list of all "previous exceptions")
483 fatal() << Exception << endmsg;
484 return StatusCode::FAILURE;
485 } catch ( const std::exception& Exception ) {
486 // (1) perform the printout of message
487 fatal() << "Standard std::exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
488 // (2) print the exception itself
489 // (NB! - GaudiException is a linked list of all "previous exceptions")
490 fatal() << Exception.what() << endmsg;
491 return StatusCode::FAILURE;
492 } catch ( ... ) {
493 // (1) perform the printout
494 fatal() << "UNKNOWN Exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
495 return StatusCode::FAILURE;
496 }
497 ON_VERBOSE verbose() << "Created tool " << tooltype << "/" << fullname << endmsg;
498
499 // Since only AlgTool has the setProperties() method it is necessary to cast
500 // to downcast IAlgTool to AlgTool in order to set the properties via the JobOptions
501 // service
502 AlgTool* mytool = dynamic_cast<AlgTool*>( toolguard.get() );
503 if ( mytool ) {
504 StatusCode sc = mytool->setProperties();
505 if ( UNLIKELY( sc.isFailure() ) ) {
506 error() << "Error setting properties for tool '" << fullname << "'" << endmsg;
507 return sc;
508 }
509 }
510
511 // Initialize the Tool
512 StatusCode sc( StatusCode::FAILURE, true );
513 try {
514 sc = toolguard->sysInitialize();
515 }
516 // Catch any exceptions
517 catch ( const GaudiException& Exception ) {
518 error() << "GaudiException with tag=" << Exception.tag() << " caught whilst initializing tool '" << fullname << "'"
519 << endmsg << Exception << endmsg;
520 return StatusCode::FAILURE;
521 } catch ( const std::exception& Exception ) {
522 error() << "Standard std::exception caught whilst initializing tool '" << fullname << "'" << endmsg
523 << Exception.what() << endmsg;
524 return StatusCode::FAILURE;
525 } catch ( ... ) {
526 error() << "UNKNOWN Exception caught whilst initializing tool '" << fullname << "'" << endmsg;
527 return StatusCode::FAILURE;
528 }
529
530 // Status of tool initialization
531 if ( UNLIKELY( sc.isFailure() ) ) {
532 error() << "Error initializing tool '" << fullname << "'" << endmsg;
533 return sc;
534 }
535
536 // Start the tool if we are running.
537 if ( m_state == Gaudi::StateMachine::RUNNING ) {
538 sc = toolguard->sysStart();
539
540 if ( UNLIKELY( sc.isFailure() ) ) {
541 error() << "Error starting tool '" << fullname << "'" << endmsg;
542 return sc;
543 }
544 }
545
546 // The tool has been successfully created and initialized,
547 // so we inform the guard that it can release it
548 tool = toolguard.release();
549
553 std::for_each( m_observers.begin(), m_observers.end(), [&]( IToolSvc::Observer* obs ) { obs->onCreate( tool ); } );
554 // TODO: replace by generic callback
555 // Register the tool with the HistorySvc
556 if ( m_pHistorySvc || service( "HistorySvc", m_pHistorySvc, false ).isSuccess() ) {
557 m_pHistorySvc->registerAlgTool( *tool ).ignore();
558 }
559 return StatusCode::SUCCESS;
560 }
561
562 //------------------------------------------------------------------------------
563 std::string ToolSvc::nameTool( const std::string& toolname, const IInterface* parent )
564 //------------------------------------------------------------------------------
565 {
566
567 if ( !parent ) { return this->name() + "." + toolname; } // RETURN
568
569 // check that parent has a name!
570 auto named_parent = SmartIF<INamedInterface>( const_cast<IInterface*>( parent ) );
571 if ( named_parent ) {
572 auto fullname = named_parent->name() + "." + toolname;
573 return fullname; // RETURN
574 }
575
576 error() << "Private Tools only allowed for components implementing INamedInterface" << endmsg;
577 //
578 return "." + toolname;
579 }
580
581 //------------------------------------------------------------------------------
582 bool ToolSvc::existsTool( const std::string& fullname ) const
583 //------------------------------------------------------------------------------
584 {
585 std::lock_guard<CallMutex> lock( m_mut );
586 auto i = std::find_if( std::begin( m_instancesTools ), std::end( m_instancesTools ),
587 [&]( const IAlgTool* tool ) { return tool->name() == fullname; } );
588 return i != std::end( m_instancesTools );
589 }
590
591 //------------------------------------------------------------------------------
592 StatusCode ToolSvc::finalizeTool( IAlgTool* itool ) const
593 //------------------------------------------------------------------------------
594 {
595
596 // Cache tool name in case of errors
597 const std::string toolName = itool->name();
598 StatusCode sc;
599
600 // Finalise the tool inside a try block
601 try {
602 sc = itool->sysFinalize();
603 }
604 // Catch any exceptions
605 catch ( const GaudiException& Exception ) {
606 error() << "GaudiException with tag=" << Exception.tag() << " caught whilst finalizing tool '" << toolName << "'"
607 << endmsg << Exception << endmsg;
608 sc = StatusCode::FAILURE;
609 } catch ( const std::exception& Exception ) {
610 error() << "Standard std::exception caught whilst finalizing tool '" << toolName << "'" << endmsg
611 << Exception.what() << endmsg;
612 sc = StatusCode::FAILURE;
613 } catch ( ... ) {
614 error() << "UNKNOWN Exception caught whilst finalizing tool '" << toolName << "'" << endmsg;
615 sc = StatusCode::FAILURE;
616 }
617
618 return sc;
619 }
620
621 //------------------------------------------------------------------------------
622 unsigned long ToolSvc::totalToolRefCount() const
623 //------------------------------------------------------------------------------
624 {
625 return totalRefCount( m_instancesTools );
626 }
627 //------------------------------------------------------------------------------
628 unsigned long ToolSvc::minimumToolRefCount() const
629 //------------------------------------------------------------------------------
630 {
631 auto i =
632 std::min_element( std::begin( m_instancesTools ), std::end( m_instancesTools ),
633 []( const IAlgTool* lhs, const IAlgTool* rhs ) { return lhs->refCount() < rhs->refCount(); } );
634 return i != std::end( m_instancesTools ) ? ( *i )->refCount() : 0;
635 }
636
637 //------------------------------------------------------------------------------
638 void ToolSvc::registerObserver( IToolSvc::Observer* obs ) {
639 //------------------------------------------------------------------------------
640 if ( !obs ) throw GaudiException( "Received NULL pointer", this->name() + "::registerObserver", StatusCode::FAILURE );
641
642 std::lock_guard<CallMutex> lock( m_mut );
643 obs->setUnregister( [this, obs]() {
644 std::lock_guard<CallMutex> lock( m_mut );
645 auto i = std::find( m_observers.begin(), m_observers.end(), obs );
646 if ( i != m_observers.end() ) m_observers.erase( i );
647 } );
648 m_observers.push_back( obs );
649 }
650
651 //------------------------------------------------------------------------------
652 StatusCode ToolSvc::start()
653 //------------------------------------------------------------------------------
654 {
655
656 ON_DEBUG debug() << "START transition for AlgTools" << endmsg;
657
658 bool fail( false );
659 for ( auto& iTool : m_instancesTools ) {
660 ON_VERBOSE verbose() << iTool->name() << "::start()" << endmsg;
661
662 if ( UNLIKELY( !iTool->sysStart().isSuccess() ) ) {
663 fail = true;
664 error() << iTool->name() << " failed to start()" << endmsg;
665 }
666 }
667
668 if ( UNLIKELY( fail ) ) {
669 error() << "One or more AlgTools failed to start()" << endmsg;
670 return StatusCode::FAILURE;
671 }
672 return StatusCode::SUCCESS;
673 }
674
675 //------------------------------------------------------------------------------
676 StatusCode ToolSvc::stop()
677 //------------------------------------------------------------------------------
678 {
679
680 ON_DEBUG debug() << "STOP transition for AlgTools" << endmsg;
681
682 bool fail( false );
683 for ( auto& iTool : m_instancesTools ) {
684 ON_VERBOSE verbose() << iTool->name() << "::stop()" << endmsg;
685
686 if ( UNLIKELY( !iTool->sysStop().isSuccess() ) ) {
687 fail = true;
688 error() << iTool->name() << " failed to stop()" << endmsg;
689 }
690 }
691
692 if ( UNLIKELY( fail ) ) {
693 error() << "One or more AlgTools failed to stop()" << endmsg;
694 return StatusCode::FAILURE;
695 }
696 return StatusCode::SUCCESS;
697 }
ToolSvc::m_pHistorySvc
IHistorySvc * m_pHistorySvc
Pointer to HistorySvc.
Definition: ToolSvc.h:94
ToolSvc::getInstances
std::vector< std::string > getInstances() const override
Get names of all tool instances.
Definition: ToolSvc.cpp:327
UNLIKELY
#define UNLIKELY(x)
Definition: Kernel.h:96
Service::m_targetState
Gaudi::StateMachine::State m_targetState
Service state.
Definition: Service.h:155
Service::initialize
StatusCode initialize() override
Definition: Service.cpp:60
SmartIF< INamedInterface >
std::vector::empty
T empty(T... args)
GaudiException
Define general base for Gaudi exception.
Definition: GaudiException.h:21
ToolSvc::releaseTool
StatusCode releaseTool(IAlgTool *tool) override
Release tool.
Definition: ToolSvc.cpp:344
gaudirun.c
c
Definition: gaudirun.py:487
Service::m_state
Gaudi::StateMachine::State m_state
Service state.
Definition: Service.h:153
gaudirun.default
default
Definition: gaudirun.py:169
Service::finalize
StatusCode finalize() override
Definition: Service.cpp:164
MsgStream.h
CommonMessagingBase::warning
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
Definition: CommonMessaging.h:101
ToolSvc::nameTool
std::string nameTool(const std::string &nameByUser, const IInterface *parent)
Get Tool full name by combining nameByUser and "parent" part.
Definition: ToolSvc.cpp:563
std::vector::rend
T rend(T... args)
IToolSvc::Observer
allow call-backs when a tool is a created or retrieved
Definition: IToolSvc.h:221
IAlgorithm.h
AlgTool.h
ToolSvc::create
StatusCode create(const std::string &type, const IInterface *parent, IAlgTool *&tool)
Create Tool standard way with automatically assigned name.
Definition: ToolSvc.cpp:374
GaudiException::tag
virtual const std::string & tag() const
name tag for the exception, or exception type
Definition: GaudiException.h:67
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
std
STL namespace.
ToolSvc::registerObserver
void registerObserver(IToolSvc::Observer *obs) override
Definition: ToolSvc.cpp:638
ToolSvc::minimumToolRefCount
unsigned long minimumToolRefCount() const
The minimum number of refCounts of all tools.
Definition: ToolSvc.cpp:628
std::end
T end(T... args)
CommonMessagingBase::info
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
Definition: CommonMessaging.h:104
std::remove
T remove(T... args)
ToolSvc::m_observers
std::vector< IToolSvc::Observer * > m_observers
Definition: ToolSvc.h:96
ToolSvc::initialize
StatusCode initialize() override
Initialize the service.
Definition: ToolSvc.cpp:52
ToolSvc
This service manages tools.
Definition: ToolSvc.h:24
AlgTool::setProperties
StatusCode setProperties()
Method for setting declared properties to the values specified in the jobOptions via the job option s...
Definition: AlgTool.cpp:107
INamedInterface::name
virtual const std::string & name() const =0
Retrieve the name of the instance.
std::string
STL class.
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
ToolSvc::start
StatusCode start() override
Definition: ToolSvc.cpp:652
Service.h
IToolSvc::Observer::onCreate
virtual void onCreate(const IAlgTool *)
Definition: IToolSvc.h:228
Service::name
const std::string & name() const override
Retrieve name of the service.
Definition: Service.cpp:274
std::vector::push_back
T push_back(T... args)
InterfaceID
Interface ID class.
Definition: IInterface.h:29
CommonMessagingBase::error
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
Definition: CommonMessaging.h:98
std::exception::what
T what(T... args)
StatusCode
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
IHistorySvc::registerAlgTool
virtual StatusCode registerAlgTool(const IAlgTool &)=0
GaudiException.h
IInterface
Definition of the basic interface.
Definition: IInterface.h:244
IInterface::refCount
virtual unsigned long refCount() const =0
Current reference count.
gaudirun.toolname
toolname
Definition: gaudirun.py:417
std::vector::erase
T erase(T... args)
std::vector::pop_back
T pop_back(T... args)
CommonMessagingBase::verbose
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
Definition: CommonMessaging.h:110
ToolSvc::getTools
std::vector< IAlgTool * > getTools() const override
Get pointers to all tool instances.
Definition: ToolSvc.cpp:337
IHistorySvc.h
ToolSvc::existsTool
bool existsTool(const std::string &toolname) const
Check if the tool instance exists.
Definition: ToolSvc.cpp:582
CommonMessagingBase::debug
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
Definition: CommonMessaging.h:107
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:267
std::exception
STL class.
Service::setProperties
StatusCode setProperties()
Method for setting declared properties to the values specified for the job.
Definition: Service.cpp:280
IAlgTool::parent
virtual const IInterface * parent() const =0
The parent of the concrete AlgTool.
std::unique_ptr::get
T get(T... args)
GaudiPython.GaudiAlgs.iAlgTool
iAlgTool
Definition: GaudiAlgs.py:55
std::vector::insert
T insert(T... args)
ToolSvc::totalToolRefCount
unsigned long totalToolRefCount() const
The total number of refCounts on all tools in the instancesTools list.
Definition: ToolSvc.cpp:622
std::string::find
T find(T... args)
std::vector::size
T size(T... args)
StatusCode::ignore
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:153
Gaudi::StateMachine::RUNNING
Definition: StateMachine.h:16
IToolSvc::Observer::setUnregister
void setUnregister(std::function< void()> unregister)
Definition: IToolSvc.h:226
Gaudi::Functional::details::get
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Definition: FunctionalDetails.h:332
std::vector< std::string >
IInterface::release
virtual unsigned long release()=0
Release Interface instance.
std::unique_ptr
STL class.
std::lock_guard
ToolSvc::m_instancesTools
std::vector< IAlgTool * > m_instancesTools
Common Tools.
Definition: ToolSvc.h:91
std::begin
T begin(T... args)
IToolSvc::Observer::onRetrieve
virtual void onRetrieve(const IAlgTool *)
Definition: IToolSvc.h:229
AlgTool
Base class from which all the concrete tool classes should be derived.
Definition: AlgTool.h:47
IAlgTool
The interface implemented by the AlgTool base class.
Definition: IAlgTool.h:23
ON_DEBUG
#define ON_DEBUG
Definition: ToolSvc.cpp:21
ToolSvc::finalize
StatusCode finalize() override
Finalize the service.
Definition: ToolSvc.cpp:73
std::vector::back
T back(T... args)
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:86
std::string::substr
T substr(T... args)
Service::service
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn't already exist.
Definition: Service.h:83
ToolSvc::finalizeTool
StatusCode finalizeTool(IAlgTool *itool) const
Finalize the given tool, with exception handling.
Definition: ToolSvc.cpp:592
std::transform
T transform(T... args)
StatusCode::isFailure
bool isFailure() const
Definition: StatusCode.h:130
std::accumulate
T accumulate(T... args)
ToolSvc::m_mut
CallMutex m_mut
Definition: ToolSvc.h:99
std::min_element
T min_element(T... args)
Gaudi::StateMachine::OFFLINE
Definition: StateMachine.h:13
std::for_each
T for_each(T... args)
ISvcLocator.h
ToolSvc::stop
StatusCode stop() override
Definition: ToolSvc.cpp:676
ON_VERBOSE
#define ON_VERBOSE
Definition: ToolSvc.cpp:22
CommonMessagingBase::fatal
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
Definition: CommonMessaging.h:92
ToolSvc.h
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
Gaudi.Configuration.log
log
Definition: Configuration.py:13
IInterface::queryInterface
virtual StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.
ToolSvc::retrieve
StatusCode retrieve(const std::string &type, const InterfaceID &iid, IAlgTool *&tool, const IInterface *parent, bool createIf) override
Retrieve tool, create it by default as common tool if it does not already exist.
Definition: ToolSvc.cpp:229
std::vector::rbegin
T rbegin(T... args)