| The Gaudi Framework v28r2p1 (f1a77ff4)

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

- File List
- File Members

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