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"
15 #include "boost/circular_buffer.hpp"
16 #include "boost/algorithm/string/predicate.hpp"
17 #include "boost/algorithm/string/erase.hpp"
18 namespace ba = boost::algorithm;
20 #define ON_DEBUG if (UNLIKELY(outputLevel() <= MSG::DEBUG))
21 #define ON_VERBOSE if (UNLIKELY(outputLevel() <= MSG::VERBOSE))
26 unsigned long totalRefCount(
const C& toolList )
30 [&](
unsigned long count,
const IAlgTool* tool ) {
31 return count + tool->refCount();
36 template <
typename C>
void remove(C&
c,
typename C::const_reference
i) {
60 error() <<
"Unable to initialize the Service" <<
endmsg;
65 if (
UNLIKELY(setProperties().isFailure())) {
66 error() <<
"Unable to set base properties" <<
endmsg;
101 info() <<
"Removing all tools created by ToolSvc" <<
endmsg;
106 log <<
" Tool List : ";
108 log << iTool->name() <<
":" << iTool->refCount( ) <<
" ";
131 unsigned long startRefCount = 0;
133 unsigned long startMinRefCount = 0;
135 while ( toolCount > 0 &&
137 (endRefCount != startRefCount || endMinRefCount != startMinRefCount) ) {
138 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
139 debug() << toolCount <<
" tools left to finalize. Summed refCounts: "
141 debug() <<
"Will finalize tools with refCount <= "
142 << endMinRefCount <<
endmsg;
144 startMinRefCount = endMinRefCount;
145 startRefCount = endRefCount;
146 unsigned long maxLoop = toolCount + 1;
151 unsigned long count = pTool->refCount( );
153 const std::string& toolName = pTool->name();
154 if ( count <= startMinRefCount ) {
155 ON_DEBUG debug() <<
" Performing finalization of " << toolName
156 <<
" (refCount " << count <<
")" <<
endmsg;
160 warning() <<
" FAILURE finalizing " << toolName <<
endmsg;
164 finalizedTools.push_back(pTool);
168 ON_DEBUG debug() <<
" Delaying finalization of " << toolName
169 <<
" (refCount " << count <<
")" <<
endmsg;
190 ON_DEBUG debug() <<
"Deleting " << finalizedTools.size() <<
" finalized tools" <<
endmsg;
191 auto maxLoop = totalRefCount( finalizedTools ) + 1;
192 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
193 IAlgTool* pTool = finalizedTools.front();
194 finalizedTools.pop_front();
195 auto count = pTool->refCount( );
197 ON_DEBUG debug() <<
" Performing deletion of " << pTool->name() <<
endmsg;
199 ON_VERBOSE verbose() <<
" Delaying deletion of " << pTool->name()
200 <<
" (refCount " << count <<
")" <<
endmsg;
202 finalizedTools.push_back(pTool);
210 error() <<
"Unable to finalize and delete the following tools : ";
212 error() << iTool->name() <<
": " << iTool->refCount( ) <<
" ";
218 if ( !finalizedTools.empty() ) {
219 error() <<
"Failed to delete the following " << finalizedTools.size()
220 <<
" finalized tools. Bug in ToolSvc::finalize()?: ";
221 for (
const auto& iTool : finalizedTools ) {
222 error() << iTool->name() <<
": " << iTool->refCount( ) <<
" ";
243 static const std::string s_PUBLIC =
":PUBLIC" ;
255 if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
257 return retrieve ( ba::erase_tail_copy(tooltype, s_PUBLIC.size()),
258 iid , tool ,
this , createIf ) ;
262 if ( tooltype.empty() ) {
263 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
266 auto pos = tooltype.find(
'/');
267 if ( std::string::npos == pos ) {
268 return retrieve ( tooltype , tooltype , iid , tool , parent , createIf );
270 return retrieve ( tooltype.substr( 0 , pos ),
271 tooltype.substr( pos + 1 ),
272 iid , tool , parent , createIf ) ;
288 if( toolname.empty() || (std::string::npos != tooltype.find(
'/')) )
289 {
return retrieve ( tooltype , iid , tool , parent , createIf ) ; }
292 if ( ba::ends_with( toolname, s_PUBLIC ) )
295 return retrieve ( tooltype , ba::erase_tail_copy(toolname, s_PUBLIC.size() ),
296 iid , tool ,
this , createIf ) ;
305 if( !parent ) parent =
this;
306 const std::string fullname =
nameTool( toolname, parent );
311 [&](
const IAlgTool*
i) {
return i->name() == fullname; } );
321 warning() <<
"Tool " << toolname
322 <<
" not found and creation not requested" <<
endmsg;
325 sc =
create( tooltype, toolname, parent, itool );
330 sc = itool->queryInterface( iid, pp_cast<void>(&tool) );
332 error() <<
"Tool " << toolname
333 <<
" either does not implement the correct interface, or its version is incompatible"
350 std::vector<std::string> tools;
352 if (tool->type() == toolType) tools.push_back( tool->name() );
381 unsigned long count = tool->refCount();
389 log <<
MSG::DEBUG <<
" Performing finalization of " << tool->name()
390 <<
" (refCount " << count <<
")" <<
endmsg;
394 log <<
MSG::DEBUG <<
"Performing finalization and deletion of " << tool->name() <<
endmsg;
411 const std::string &
toolname = tooltype;
412 return create( tooltype, toolname, parent, tool);
418 template <
typename T>
419 class ToolCreateGuard {
423 std::unique_ptr<IAlgTool> m_tool;
426 ToolCreateGuard(T& tools): m_tools(tools) {}
430 ToolCreateGuard(ToolCreateGuard&&) =
default;
432 void create(
const std::string& tooltype,
const std::string& fullname,
const IInterface* parent ) {
434 if (m_tool)
remove(m_tools,m_tool.get());
435 m_tool.reset(AlgTool::Factory::create(tooltype, tooltype, fullname, parent)) ;
437 if (m_tool) m_tools.push_back(m_tool.get());
449 return m_tool.release();
453 if (m_tool)
remove(m_tools,m_tool.get());
457 template <
typename C>
458 ToolCreateGuard<C> make_toolCreateGuard(C&
c) {
459 return ToolCreateGuard<C>{ c };
471 error() <<
"create(): No Tool Type given" <<
endmsg;
476 if ( !parent ) parent =
this;
484 std::string fullname =
nameTool(toolname, parent);
486 error() <<
"Tool " << fullname <<
" already exists" <<
endmsg;
491 toolguard.create( tooltype, fullname, parent );
493 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
499 fatal() <<
"Exception with tag=" << Exception.
tag()
500 <<
" is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
503 fatal() << Exception <<
endmsg;
506 catch(
const std::exception& Exception ) {
508 fatal() <<
"Standard std::exception is caught whilst instantiating tool '"
509 << tooltype <<
"'" <<
endmsg;
512 fatal() << Exception.what() <<
endmsg;
517 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '"
518 << tooltype <<
"'" <<
endmsg;
521 ON_VERBOSE verbose() <<
"Created tool " << tooltype <<
"/" << fullname <<
endmsg;
530 error() <<
"Error setting properties for tool '"
531 << fullname <<
"'" <<
endmsg;
539 sc = toolguard->sysInitialize();
545 <<
"GaudiException with tag=" << Exception.
tag()
546 <<
" caught whilst initializing tool '" << fullname <<
"'" << endmsg
550 catch(
const std::exception & Exception )
553 <<
"Standard std::exception caught whilst initializing tool '"
554 << fullname <<
"'" << endmsg << Exception.what() <<
endmsg;
560 <<
"UNKNOWN Exception caught whilst initializing tool '"
561 << fullname <<
"'" <<
endmsg;
567 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
573 sc = toolguard->sysStart();
576 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
584 tool = toolguard.release();
607 if ( !parent ) {
return this->
name() +
"." +
toolname; }
613 auto fullname = named_parent->name() +
"." +
toolname ;
619 <<
"Private Tools only allowed for components implementing INamedInterface"
630 [&](
const IAlgTool* tool) {
return tool->name() == fullname; } );
640 const std::string toolName = itool->name();
645 sc = itool->sysFinalize();
651 <<
"GaudiException with tag=" << Exception.
tag()
652 <<
" caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg
656 catch(
const std::exception & Exception )
659 <<
"Standard std::exception caught whilst finalizing tool '"
660 << toolName <<
"'" <<
endmsg << Exception.what() <<
endmsg;
666 <<
"UNKNOWN Exception caught whilst finalizing tool '"
667 << toolName <<
"'" <<
endmsg;
687 return lhs->refCount() < rhs->refCount();
715 if (
UNLIKELY(!iTool->sysStart().isSuccess())) {
717 error() << iTool->name() <<
" failed to start()" <<
endmsg;
723 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
743 if (
UNLIKELY(!iTool->sysStop().isSuccess())) {
745 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
751 error() <<
"One or more AlgTools failed to stop()" <<
endmsg;
Definition of the MsgStream class used to transmit messages.
StatusCode initialize() override
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
StatusCode finalize() override
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
auto begin(reverse_wrapper< T > &w)
bool isFailure() const
Test for a status code of FAILURE.
#define DECLARE_COMPONENT(type)
auto end(reverse_wrapper< T > &w)
This class is used for returning status codes from appropriate routines.
virtual StatusCode registerAlgTool(const IAlgTool &)=0
Definition of the basic interface.
virtual const std::string & tag() const
name tag for the exception, or exception type
Base class used to extend a class implementing other interfaces.