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 );
312 return i->name() == fullname && i->
parent() == parent;
315 ON_DEBUG debug() <<
"Retrieved tool " << toolname <<
" with parent " << parent <<
endmsg;
323 warning() <<
"Tool " << toolname
324 <<
" not found and creation not requested" <<
endmsg;
327 sc =
create( tooltype, toolname, parent, itool );
332 sc = itool->queryInterface( iid, pp_cast<void>(&tool) );
334 error() <<
"Tool " << toolname
335 <<
" either does not implement the correct interface, or its version is incompatible"
352 std::vector<std::string> tools;
354 if (tool->type() == toolType) tools.push_back( tool->name() );
382 unsigned long count = tool->refCount();
390 log <<
MSG::DEBUG <<
" Performing finalization of " << tool->name()
391 <<
" (refCount " << count <<
")" <<
endmsg;
395 log <<
MSG::DEBUG <<
"Performing finalization and deletion of " << tool->name() <<
endmsg;
412 const std::string &
toolname = tooltype;
413 return create( tooltype, toolname, parent, tool);
419 template <
typename T>
420 class ToolCreateGuard {
424 std::unique_ptr<IAlgTool> m_tool;
427 explicit ToolCreateGuard(T& tools): m_tools(tools) {}
431 ToolCreateGuard(ToolCreateGuard&&) noexcept =
default;
433 void create( const
std::
string& tooltype, const
std::
string& fullname, const
IInterface* parent ) {
435 if (m_tool)
remove(m_tools,m_tool.get());
436 m_tool.reset(AlgTool::Factory::create(tooltype, tooltype, fullname, parent)) ;
438 if (m_tool) m_tools.push_back(m_tool.get());
450 return m_tool.release();
454 if (m_tool)
remove(m_tools,m_tool.get());
458 template <
typename C>
459 ToolCreateGuard<C> make_toolCreateGuard(C&
c) {
460 return ToolCreateGuard<C>{ c };
481 error() <<
"create(): No Tool Type given" <<
endmsg;
486 if ( !parent ) parent =
this;
494 std::string fullname =
nameTool(toolname, parent);
501 error() <<
"Tool " << fullname <<
" already exists with the same parent" <<
endmsg;
503 error() <<
"... In addition, the parent is the ToolSvc: public tools cannot be cloned!" <<
endmsg;
512 toolguard.create( tooltype, fullname, parent );
514 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
520 fatal() <<
"Exception with tag=" << Exception.
tag()
521 <<
" is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
524 fatal() << Exception <<
endmsg;
527 catch(
const std::exception& Exception ) {
529 fatal() <<
"Standard std::exception is caught whilst instantiating tool '"
530 << tooltype <<
"'" <<
endmsg;
533 fatal() << Exception.what() <<
endmsg;
538 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '"
539 << tooltype <<
"'" <<
endmsg;
542 ON_VERBOSE verbose() <<
"Created tool " << tooltype <<
"/" << fullname <<
endmsg;
551 error() <<
"Error setting properties for tool '"
552 << fullname <<
"'" <<
endmsg;
560 sc = toolguard->sysInitialize();
566 <<
"GaudiException with tag=" << Exception.
tag()
567 <<
" caught whilst initializing tool '" << fullname <<
"'" << endmsg
571 catch(
const std::exception & Exception )
574 <<
"Standard std::exception caught whilst initializing tool '"
575 << fullname <<
"'" << endmsg << Exception.what() <<
endmsg;
581 <<
"UNKNOWN Exception caught whilst initializing tool '"
582 << fullname <<
"'" <<
endmsg;
588 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
594 sc = toolguard->sysStart();
597 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
605 tool = toolguard.release();
628 if ( !parent ) {
return this->
name() +
"." +
toolname; }
634 auto fullname = named_parent->name() +
"." +
toolname ;
640 <<
"Private Tools only allowed for components implementing INamedInterface"
651 [&](
const IAlgTool* tool) {
return tool->name() == fullname; } );
661 const std::string toolName = itool->name();
666 sc = itool->sysFinalize();
672 <<
"GaudiException with tag=" << Exception.
tag()
673 <<
" caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg
677 catch(
const std::exception & Exception )
680 <<
"Standard std::exception caught whilst finalizing tool '"
681 << toolName <<
"'" <<
endmsg << Exception.what() <<
endmsg;
687 <<
"UNKNOWN Exception caught whilst finalizing tool '"
688 << toolName <<
"'" <<
endmsg;
708 return lhs->refCount() < rhs->refCount();
736 if (
UNLIKELY(!iTool->sysStart().isSuccess())) {
738 error() << iTool->name() <<
" failed to start()" <<
endmsg;
744 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
762 if (
UNLIKELY(!iTool->sysStop().isSuccess())) {
764 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
770 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...
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
StatusCode finalize() override
auto begin(reverse_wrapper< T > &w)
bool isFailure() const
Test for a status code of FAILURE.
auto end(reverse_wrapper< T > &w)
This class is used for returning status codes from appropriate routines.
virtual StatusCode registerAlgTool(const IAlgTool &)=0
#define DECLARE_COMPONENT(type)
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.