| # Gaudi Framework, version v20r4
Generated: 8 Jan 2009

# ToolSvc.cpp

Go to the documentation of this file.

    00001 // $Id: ToolSvc.cpp,v 1.39 2008/11/02 14:17:13 marcocle Exp $
    00002
    00003 // Include Files
    00004 #include "GaudiKernel/MsgStream.h"
    00005 #include "GaudiKernel/Service.h"
    00006 #include "GaudiKernel/SvcFactory.h"
    00007 #include "GaudiKernel/ISvcLocator.h"
    00008 #include "GaudiKernel/IAlgorithm.h"
    00009 #include "GaudiKernel/GaudiException.h"
    00010 #include "GaudiKernel/AlgTool.h"
    00011 #include "GaudiKernel/IHistorySvc.h"
    00012 #include "GaudiKernel/ToolFactory.h"
    00013 #include "ToolSvc.h"
    00014 #include <algorithm>
    00015 #include <map>
    00016 #include <string>
    00017 #include <cassert>
    00018 #include "boost/lambda/bind.hpp"
    00019
    00020
    00021
    00022 // Instantiation of a static factory class used by clients to create
    00023 //  instances of this service
    00024 DECLARE_SERVICE_FACTORY(ToolSvc)
    00025
    00026 using ROOT::Reflex::PluginService;
    00027 namespace bl = boost::lambda;
    00028
    00029 //------------------------------------------------------------------------------
    00030 ToolSvc::ToolSvc( const std::string& name, ISvcLocator* svc )
    00031   //------------------------------------------------------------------------------
    00032   : Service(name, svc),
    00033     m_pHistorySvc(0)
    00034  { }
    00035
    00036 //------------------------------------------------------------------------------
    00037 ToolSvc::~ToolSvc()
    00038   //------------------------------------------------------------------------------
    00039 {
    00040
    00041 }
    00042
    00043 //------------------------------------------------------------------------------
    00044 StatusCode ToolSvc::initialize()
    00045   //------------------------------------------------------------------------------
    00046 {
    00047
    00048   // initialize the Service Base class
    00049   StatusCode status = Service::initialize();
    00050   if ( status.isFailure() )
    00051   {
    00052     MsgStream log( msgSvc(), name() );
    00053     log << MSG::ERROR << "Unable to initialize the Service" << endreq;
    00054     return status;
    00055   }
    00056
    00057   // set my own (ToolSvc) properties via the jobOptionService
    00058   if (setProperties().isFailure()) {
    00059     MsgStream log( msgSvc(), name() );
    00060     log << MSG::ERROR << "Unable to set base properties" << endreq;
    00061     return StatusCode::FAILURE;
    00062   }
    00063
    00064   return status;
    00065 }
    00066
    00067 //------------------------------------------------------------------------------
    00068 StatusCode ToolSvc::finalize()
    00069   //------------------------------------------------------------------------------
    00070 {
    00071   // Finalize and delete all left-over tools. Normally all tools created with
    00072   // ToolSvc are left over, since ToolSvc holds a refCount (via AlgTool ctor).
    00073   // Several cases need to be covered:
    00074   // 1) Simple dependencies: no circular dependencies between tools,
    00075   //    and tools not using other tools
    00076   // 2) Tools-using-tools (but no circular dependencies)
    00077   //   a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
    00078   //   b) release() is called in the tool destructor  (e.g. via ToolHandle)
    00079   // 3) Circular dependencies between tools
    00080   //   a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
    00081   //   b) release() is called in the tool destructor  (e.g. via ToolHandle)
    00082   // 4) In addition to each of the above cases, refCounting of a particular tool
    00083   //    might not have been done correctly in the code. Typically release()
    00084   //    is not called, so we are left with a too high refCount.
    00085   //    What to do with those, and how to avoid a crash while handling them...
    00086
    00095   MsgStream log( msgSvc(), name() );
    00096   ListTools finalizedTools; // list of tools that have been finalized
    00097   log << MSG::INFO  << "Removing all tools created by ToolSvc" << endreq;
    00098
    00099   // Print out list of tools
    00100   log << MSG::DEBUG << "  Tool List : ";
    00101   for ( ListTools::const_iterator iTool = m_instancesTools.begin();
    00102         iTool != m_instancesTools.end(); ++iTool ) {
    00103     log << (*iTool)->name() << ":" << refCountTool( *iTool ) << " ";
    00104   }
    00105   log << endreq;
    00106
    00107   //
    00108   // first pass: Finalize all tools (but don't delete them)
    00109   //
    00122   bool fail(false);
    00123   size_t toolCount = m_instancesTools.size();
    00124   unsigned long startRefCount = 0;
    00125   unsigned long endRefCount = totalToolRefCount();
    00126   unsigned long startMinRefCount = 0;
    00127   unsigned long endMinRefCount = minimumToolRefCount();
    00128   while ( toolCount > 0 &&
    00129           endRefCount > 0 &&
    00130           (endRefCount != startRefCount || endMinRefCount != startMinRefCount) ) {
    00131     if ( endMinRefCount != startMinRefCount ) {
    00132       log << MSG::DEBUG << toolCount << " tools left to finalize. Summed refCounts: "
    00133           << endRefCount << endreq;
    00134       log << MSG::DEBUG << "Will finalize tools with refCount <= "
    00135           << endMinRefCount << endreq;
    00136     }
    00137     startMinRefCount = endMinRefCount;
    00138     startRefCount = endRefCount;
    00139     unsigned long maxLoop = toolCount + 1;
    00140     while ( --maxLoop > 0 &&  m_instancesTools.size() > 0 ) {
    00141       IAlgTool* pTool = m_instancesTools.back();
    00142       // removing tool from list makes ToolSvc::releaseTool( IAlgTool* ) a noop
    00143       m_instancesTools.pop_back();
    00144       unsigned long count = refCountTool( pTool );
    00145       // cache tool name
    00146       std::string toolName = pTool->name();
    00147       if ( count <= startMinRefCount ) {
    00148         log << MSG::DEBUG << "  Performing finalization of " << toolName
    00149             << " (refCount " << count << ")" << endreq;
    00150         // finalize of one tool may trigger a release of another tool
    00151         //      pTool->sysFinalize().ignore();
    00152         if (!finalizeTool(pTool).isSuccess()) fail = true;
    00153         // postpone deletion
    00154         finalizedTools.push_back(pTool);
    00155       } else {
    00156         // Place back in list to try again later
    00157         // ToolSvc::releaseTool( IAlgTool* ) remains active for this tool
    00158         log << MSG::DEBUG << "  Delaying   finalization of " << toolName
    00159             << " (refCount " << count << ")" << endreq;
    00160         m_instancesTools.push_front(pTool);
    00161       }
    00162     } // end of inner loop
    00163     toolCount = m_instancesTools.size();
    00164     endRefCount = totalToolRefCount();
    00165     endMinRefCount = minimumToolRefCount();
    00166   }; // end of outer loop
    00167
    00168   //
    00169   // Second pass: Delete all finalized tools
    00170   //
    00171   // Delete in the order of increasing number of refCounts.
    00172   // Loop over tools in the same order as the order in which they were finalized.
    00173   // All tools in the list of finalized tools are no longer in the instancesTools list.
    00174   // If a tool destructor calls releaseTool() on another tool, this will have no
    00175   // effect on the 'other tool' if this 'other tool' is in the list of finalized tools.
    00176   // If this 'other tool' is still in the instancesTools list, it may trigger finalization
    00177   // (in releaseTool()), deletion and removal from the instancesTools list.
    00178   // Therefore, the check on non-finalised tools should happen *after* the deletion
    00179   // of the finalized tools.
    00180   log << MSG::DEBUG << "Deleting " << finalizedTools.size() << " finalized tools" << endreq;
    00181   unsigned long maxLoop = totalToolRefCount( finalizedTools ) + 1;
    00182   while ( --maxLoop > 0 && finalizedTools.size() > 0 ) {
    00183     IAlgTool* pTool = finalizedTools.front();
    00184     finalizedTools.pop_front();
    00185     unsigned long count = refCountTool( pTool );
    00186     if ( count == 1 ) {
    00187       log << MSG::DEBUG << "  Performing deletion of " << pTool->name() << endreq;
    00188     } else {
    00189       log << MSG::VERBOSE << "  Delaying   deletion of " << pTool->name()
    00190           << " (refCount " << count << ")" << endreq;
    00191       // Put it back at the end of the list if refCount still not zero
    00192       finalizedTools.push_back(pTool);
    00193     }
    00194     // do a forced release
    00195     pTool->release();
    00196   }
    00197
    00198   // Error if by now not all tools are properly finalised
    00199   if ( !m_instancesTools.empty() ) {
    00200     log << MSG::ERROR << "Unable to finalize and delete the following tools : ";
    00201     for ( ListTools::const_iterator iTool = m_instancesTools.begin();
    00202           iTool != m_instancesTools.end(); ++iTool ) {
    00203       log << (*iTool)->name() << ": " << refCountTool( *iTool ) << " ";
    00204     }
    00205     log << endreq;
    00206   }
    00207
    00208   // by now, all tools should be deleted and removed.
    00209   if ( finalizedTools.size() > 0 ) {
    00210     log << MSG::ERROR << "Failed to delete the following " <<  finalizedTools.size()
    00211         << " finalized tools. Bug in ToolSvc::finalize()?: ";
    00212     for ( ListTools::const_iterator iTool = finalizedTools.begin();
    00213           iTool != finalizedTools.end(); ++iTool ) {
    00214       log << (*iTool)->name() << ": " << refCountTool( *iTool ) << " ";
    00215     }
    00216     log << endreq;
    00217   }
    00218
    00219   if ( 0 != m_pHistorySvc ) {
    00220     m_pHistorySvc->release();
    00221   }
    00222
    00223   // Finalize this specific service
    00224   if (! Service::finalize().isSuccess() || fail) {
    00225     return StatusCode::FAILURE;
    00226   } else {
    00227     return StatusCode::SUCCESS;
    00228   }
    00229
    00230
    00231 }
    00232
    00233 //------------------------------------------------------------------------------
    00234 StatusCode ToolSvc::queryInterface( const InterfaceID& riid, void** ppvInterface )
    00235   //------------------------------------------------------------------------------
    00236 {
    00237   if ( IID_IToolSvc == riid )    {
    00238     *ppvInterface = (IToolSvc*)this;
    00239   }
    00240   else  {
    00241     // Interface is not directly available: try out a base class
    00242     return Service::queryInterface(riid, ppvInterface);
    00243   }
    00244   addRef();
    00245   return StatusCode::SUCCESS;
    00246 }
    00247
    00248 // ===================================================================================
    00252 // ===================================================================================
    00253 namespace
    00254 {
    00255   const std::string s_PUBLIC = ":PUBLIC" ;
    00256 }
    00257
    00258 //------------------------------------------------------------------------------
    00259 StatusCode ToolSvc::retrieve ( const std::string& tooltype ,
    00260                                const InterfaceID& iid      ,
    00261                                IAlgTool*&         tool     ,
    00262                                const IInterface*  parent   ,
    00263                                bool               createIf )
    00264 //------------------------------------------------------------------------------
    00265 {
    00266
    00267   // protect against empty type
    00268   if ( tooltype.empty() ) {
    00269     MsgStream log( msgSvc(), name() );
    00270     log << MSG::ERROR << "retrieve(): No Tool Type/Name given" << endreq;
    00271     return StatusCode::FAILURE;
    00272   }
    00273
    00274   {
    00275     // check for tools, which by name is required to be public:
    00276     const std::string::size_type pos = tooltype.find ( s_PUBLIC ) ;
    00277     if ( std::string::npos != pos )
    00278     {
    00279       // set parent for PUBLIC tool
    00280       parent = this ;
    00281       return retrieve ( std::string( tooltype , 0 , pos ) ,
    00282                         iid , tool , parent , createIf ) ;
    00283     }
    00284   }
    00285
    00286   const std::string::size_type pos = tooltype.find('/');
    00287   if( std::string::npos == pos )
    00288   { return retrieve ( tooltype , tooltype , iid , tool , parent , createIf );}
    00289   const std::string newtype ( tooltype ,       0 , pos               ) ;
    00290   const std::string newname ( tooltype , pos + 1 , std::string::npos ) ;
    00291   return retrieve ( newtype , newname , iid , tool , parent , createIf ) ;
    00292 }
    00293
    00294 // ===================================================================================
    00295
    00296 //------------------------------------------------------------------------------
    00297 StatusCode ToolSvc::retrieve ( const std::string& tooltype ,
    00298                                const std::string& toolname ,
    00299                                const InterfaceID& iid      ,
    00300                                IAlgTool*&         tool     ,
    00301                                const IInterface*  parent   ,
    00302                                bool               createIf )
    00303   //------------------------------------------------------------------------------
    00304 {
    00305   MsgStream log( msgSvc(), name() );
    00306
    00307   // check the applicability of another method:
    00308   // ignore the provided name if it is empty or the type contains a name
    00309   if( toolname.empty() || (std::string::npos != tooltype.find('/')) )
    00310   { return retrieve ( tooltype , iid , tool , parent , createIf ) ; }
    00311
    00312   {
    00313     // check for tools, which by name is required to be public:
    00314     const std::string::size_type pos = toolname.find ( s_PUBLIC ) ;
    00315     if ( std::string::npos != pos )
    00316     {
    00317       // set parent for PUBLIC tool
    00318       parent = this ;
    00319       return retrieve ( tooltype , std::string( toolname , 0 , pos ) ,
    00320                         iid , tool , parent , createIf ) ;
    00321     }
    00322   }
    00323
    00324   IAlgTool* itool = 0;
    00325   StatusCode sc(StatusCode::FAILURE);
    00326
    00327   tool = 0;
    00328
    00329   // If parent is not specified it means it is the ToolSvc itself
    00330   if( 0 == parent ) {
    00331     parent = this;
    00332   }
    00333   const std::string fullname = nameTool( toolname, parent );
    00334
    00335   // Find tool in list of those already existing, and tell its
    00336   // interface that it has been used one more time
    00337   ListTools::const_iterator it;
    00338   for( it = m_instancesTools.begin(); it != m_instancesTools.end(); ++it ) {
    00339     if( (*it)->name() == fullname ) {
    00340       log << MSG::DEBUG << "Retrieved tool " << toolname << endreq;
    00341       itool = *it;
    00342       break;
    00343     }
    00344   }
    00345
    00346   if ( 0 == itool ) {
    00347     // Instances of this tool do not exist, create an instance if desired
    00348     // otherwise return failure
    00349     if( !createIf ) {
    00350       log << MSG::WARNING << "Tool " << toolname
    00351           << " not found and creation not requested" << endreq;
    00352       return sc;
    00353     }
    00354     else {
    00355       sc = create( tooltype, toolname, parent, itool );
    00356       if ( sc.isFailure() ) { return sc; }
    00357     }
    00358   }
    00359
    00360   // Get the right interface of it
    00361   sc = itool->queryInterface( iid, (void**)&tool);
    00362   if( sc.isFailure() ) {
    00363     log << MSG::ERROR << "Tool " << toolname
    00364         << " either does not implement the correct interface, or its version is incompatible"
    00365         << endreq;
    00366     return sc;
    00367   }
    00371   if (!m_observers.empty()) {
    00372      std::for_each( m_observers.begin(),
    00373                     m_observers.end(),
    00374                     bl::bind(&IToolSvc::Observer::onRetrieve,
    00375                              bl::_1,
    00376                              itool));
    00377   }
    00378
    00379   return sc;
    00380 }
    00381 //------------------------------------------------------------------------------
    00382 std::vector<std::string> ToolSvc::getInstances( const std::string& toolType )
    00383 //------------------------------------------------------------------------------
    00384 {
    00385
    00386   std::vector<std::string> tools;
    00387
    00388   ListTools::const_iterator it;
    00389   for (it = m_instancesTools.begin(); it != m_instancesTools.end(); ++it) {
    00390     if ((*it)->type() == toolType) {
    00391       tools.push_back( (*it)->name() );
    00392     }
    00393   }
    00394
    00395   return tools;
    00396
    00397 }
    00398 //------------------------------------------------------------------------------
    00399 StatusCode ToolSvc::releaseTool( IAlgTool* tool )
    00400   //------------------------------------------------------------------------------
    00401 {
    00402   StatusCode sc(StatusCode::SUCCESS);
    00403   // test if tool is in known list (protect trying to access a previously deleted tool)
    00404   if ( m_instancesTools.rend() != std::find( m_instancesTools.rbegin(),
    00405                                               m_instancesTools.rend(),
    00406                                               tool ) ) {
    00407     unsigned long count = refCountTool(tool);
    00408     if ( count == 1 ) {
    00409       MsgStream log( msgSvc(), name() );
    00410       // finalize the tool
    00411
    00412       if ( Gaudi::StateMachine::OFFLINE == m_targetState ) {
    00413         // We are being called during ToolSvc::finalize()
    00414         // message format matches the one in ToolSvc::finalize()
    00415         log << MSG::DEBUG << "  Performing finalization of " << tool->name()
    00416             << " (refCount " << count << ")" << endreq;
    00417         // message format matches the one in ToolSvc::finalize()
    00418         log << MSG::DEBUG << "  Performing     deletion of " << tool->name() << endreq;
    00419       } else {
    00420         log << MSG::DEBUG << "Performing finalization and deletion of " << tool->name() << endreq;
    00421       }
    00422       sc = finalizeTool(tool);
    00423       // remove from known tools...
    00424       m_instancesTools.remove(tool);
    00425     }
    00426     tool->release();
    00427   }
    00428
    00429   return sc;
    00430 }
    00431
    00432 //------------------------------------------------------------------------------
    00433 StatusCode ToolSvc::create(const std::string& tooltype,
    00434                            const IInterface* parent,
    00435                            IAlgTool*& tool)
    00436   //------------------------------------------------------------------------------
    00437 {
    00438   const std::string & toolname = tooltype;
    00439   return create( tooltype, toolname, parent, tool);
    00440 }
    00441
    00442 namespace {
    00445 class ToolCreateGuard {
    00446 public:
    00447   ToolCreateGuard(ToolSvc::ListTools &listTools):
    00448     m_list(listTools),
    00449     m_tool(0)
    00450   {}
    00452   void set(IAlgTool* tool) {
    00453     if (m_tool) { // remove previous content
    00454       m_list.remove(m_tool);
    00455       delete m_tool;
    00456     }
    00457     if (tool) { // set new content
    00458       m_tool = tool;
    00459       m_list.push_back(m_tool);
    00460     }
    00461   }
    00462   ToolCreateGuard& operator=(IAlgTool* tool) {
    00463     set(tool);
    00464     return *this;
    00465   }
    00467   IAlgTool* get() {
    00468     return m_tool;
    00469   }
    00470   IAlgTool& operator*() const {
    00471     assert(m_tool != 0);
    00472     return *m_tool;
    00473   }
    00474   IAlgTool* operator->() const {
    00475     assert(m_tool != 0);
    00476     return m_tool;
    00477   }
    00479   IAlgTool* release() {
    00480     IAlgTool* tool = m_tool;
    00481     m_tool = 0;
    00482     return tool;
    00483   }
    00485   ~ToolCreateGuard(){
    00486     set(0);
    00487   }
    00488 private:
    00490   ToolSvc::ListTools& m_list;
    00492   IAlgTool* m_tool;
    00493 };
    00494 }
    00495 //------------------------------------------------------------------------------
    00496 StatusCode ToolSvc::create(const std::string& tooltype,
    00497                            const std::string& toolname,
    00498                            const IInterface* parent,
    00499                            IAlgTool*& tool)
    00500   //------------------------------------------------------------------------------
    00501 {
    00502   MsgStream log( msgSvc(), name() );
    00503   // protect against empty type
    00504   if ( tooltype.empty() ) {
    00505     log << MSG::ERROR << "create(): No Tool Type given" << endreq;
    00506     return StatusCode::FAILURE;
    00507   }
    00508
    00509   // If parent has not been specified, assume it is the ToolSvc
    00510   if ( 0 == parent ) parent = this;
    00511
    00512   tool = 0;
    00513   // Automatically deletes the tool if not explicitly kept (i.e. on success).
    00514   // The tool is removed from the list of known tools too.
    00515   ToolCreateGuard toolguard(m_instancesTools);
    00516
    00517   // Check if the tool already exist : this should never happen
    00518   const std::string fullname = nameTool(toolname, parent);
    00519   if( existsTool( fullname ) ) {
    00520     log << MSG::ERROR << "Tool " << fullname << " already exists" << endreq;
    00521     return StatusCode::FAILURE;
    00522   }
    00523   // instantiate the tool using the factory
    00524   try {
    00525     toolguard = PluginService::Create<IAlgTool*>(tooltype, tooltype, fullname, parent);
    00526     if ( ! toolguard.get() ){
    00527        log << MSG::ERROR
    00528            << "Cannot create tool " << tooltype << " (No factory found)" << endreq;
    00529        return StatusCode::FAILURE;
    00530     }
    00531   }
    00532   catch ( const GaudiException& Exception )  {
    00533     // (1) perform the printout of message
    00534     MsgStream log ( msgSvc() , name() );
    00535     log << MSG::FATAL << "Exception with tag=" << Exception.tag()
    00536         << " is caught whilst instantiating tool '" << tooltype << "'" << endreq;
    00537     // (2) print  the exception itself
    00538     // (NB!  - GaudiException is a linked list of all "previous exceptions")
    00539     log << MSG::FATAL << Exception  << endreq;
    00540     return StatusCode::FAILURE;
    00541   }
    00542   catch( const std::exception& Exception ) {
    00543     // (1) perform the printout of message
    00544     MsgStream log ( msgSvc() , name() );
    00545     log << MSG::FATAL
    00546         << "Standard std::exception is caught whilst instantiating tool '"
    00547           << tooltype << "'" << endreq;
    00548     // (2) print  the exception itself
    00549     // (NB!  - GaudiException is a linked list of all "previous exceptions")
    00550     log << MSG::FATAL << Exception.what()  << endreq;
    00551     return StatusCode::FAILURE;
    00552   }
    00553   catch(...) {
    00554     // (1) perform the printout
    00555     MsgStream log ( msgSvc() , name() );
    00556     log << MSG::FATAL << "UNKNOWN Exception is caught whilst instantiating tool '"
    00557         << tooltype << "'" << endreq;
    00558     return StatusCode::FAILURE;
    00559   }
    00560   log << MSG::VERBOSE << "Created tool " << tooltype << "/" << fullname << endreq;
    00561
    00562   // Since only AlgTool has the setProperties() method it is necessary to cast
    00563   // to downcast IAlgTool to AlgTool in order to set the properties via the JobOptions
    00564   // service
    00565   AlgTool* mytool = dynamic_cast<AlgTool*> (toolguard.get());
    00566   if ( mytool != 0 ) {
    00567     StatusCode sc = mytool->setProperties();
    00568     if ( sc.isFailure() ) {
    00569       MsgStream log ( msgSvc() , name() );
    00570       log << MSG::ERROR << "Error setting properties for tool '"
    00571           << fullname << "'" << endreq;
    00572       return sc;
    00573     }
    00574   }
    00575
    00576   // Initialize the Tool
    00577   StatusCode sc (StatusCode::FAILURE,true);
    00578   try { sc = toolguard->sysInitialize(); }
    00579
    00580   // Catch any exceptions
    00581   catch ( const GaudiException & Exception )
    00582     {
    00583       MsgStream msg ( msgSvc(), name() );
    00584       msg << MSG::ERROR
    00585           << "GaudiException with tag=" << Exception.tag()
    00586           << " caught whilst initializing tool '" << fullname << "'" << endreq
    00587           << Exception << endreq;
    00588       return StatusCode::FAILURE;
    00589     }
    00590   catch( const std::exception & Exception )
    00591     {
    00592       MsgStream msg ( msgSvc(), name() );
    00593       msg << MSG::ERROR
    00594           << "Standard std::exception caught whilst initializing tool '"
    00595           << fullname << "'" << endreq << Exception.what() << endreq;
    00596       return StatusCode::FAILURE;
    00597     }
    00598   catch (...)
    00599     {
    00600       MsgStream msg ( msgSvc(), name() );
    00601       msg << MSG::ERROR
    00602           << "UNKNOWN Exception caught whilst initializing tool '"
    00603           << fullname << "'" << endreq;
    00604       return StatusCode::FAILURE;
    00605     }
    00606
    00607   // Status of tool intialization
    00608   if ( sc.isFailure() ) {
    00609     MsgStream log( msgSvc(), name() );
    00610     log << MSG::ERROR << "Error initializing tool '" << fullname << "'" << endreq;
    00611     return sc;
    00612   }
    00613
    00614   // The tool has been successfully created and initialized,
    00615   // so we the guard can be released
    00616   tool = toolguard.release();
    00617
    00621   if (!m_observers.empty()) {
    00622       std::for_each( m_observers.begin(),
    00623                      m_observers.end(),
    00624                      bl::bind(&IToolSvc::Observer::onCreate,
    00625                               bl::_1,
    00626                               tool));
    00627   }
    00628   // TODO: replace by generic callback
    00629   // Register the tool with the HistorySvc
    00630   if (m_pHistorySvc != 0 ||
    00631       service("HistorySvc",m_pHistorySvc,false).isSuccess() ) {
    00632     m_pHistorySvc->registerAlgTool(*tool).ignore();
    00633   }
    00634
    00635   return StatusCode::SUCCESS;
    00636
    00637 }
    00638
    00639 //------------------------------------------------------------------------------
    00640 std::string ToolSvc::nameTool( const std::string& toolname,
    00641                                const IInterface* parent )
    00642   //------------------------------------------------------------------------------
    00643 {
    00644
    00645   std::string fullname = "";
    00646   if ( parent == 0 ) { return this->name() + "." + toolname; }    // RETURN
    00647
    00648
    00649   IInterface* cparent = const_cast<IInterface*>( parent ) ;
    00650   // check that parent has a name!
    00651   INamedInterface* _p = 0 ;
    00652   StatusCode sc = cparent->queryInterface( INamedInterface::interfaceID() , pp_cast<void>(&_p) ) ;
    00653   if ( sc.isSuccess() )
    00654   {
    00655     fullname = _p->name() + "." + toolname ;
    00656     _p->release() ;
    00657     return fullname ;                                          // RETURN
    00658   }
    00659
    00660   MsgStream log ( msgSvc(), name() );
    00661   log << MSG::ERROR
    00662       << "Private Tools only allowed for INamedInterfaces"
    00663       << endreq;
    00664   //
    00665   return "." + toolname ;
    00666 }
    00667
    00668 //------------------------------------------------------------------------------
    00669 bool ToolSvc::existsTool( const std::string& fullname) const
    00670   //------------------------------------------------------------------------------
    00671 {
    00672   for ( ListTools::const_iterator it = m_instancesTools.begin();
    00673         it != m_instancesTools.end(); ++it ) {
    00674     if ( (*it)->name() == fullname ) { return true; }
    00675   }
    00676   return false;
    00677 }
    00678
    00679 //------------------------------------------------------------------------------
    00680 StatusCode ToolSvc::finalizeTool( IAlgTool* itool ) const
    00681   //------------------------------------------------------------------------------
    00682 {
    00683
    00684   // Cache tool name in case of errors
    00685   const std::string toolName = itool->name();
    00686   StatusCode sc;
    00687
    00688   // Finalise the tool inside a try block
    00689   try { sc = itool->sysFinalize(); }
    00690
    00691   // Catch any exceptions
    00692   catch ( const GaudiException & Exception )
    00693   {
    00694     MsgStream msg ( msgSvc(), name() );
    00695     msg << MSG::ERROR
    00696         << "GaudiException with tag=" << Exception.tag()
    00697         << " caught whilst finalizing tool '" << toolName << "'" << endreq
    00698         << Exception << endreq;
    00699     sc = StatusCode::FAILURE;
    00700   }
    00701   catch( const std::exception & Exception )
    00702   {
    00703     MsgStream msg ( msgSvc(), name() );
    00704     msg << MSG::ERROR
    00705         << "Standard std::exception caught whilst finalizing tool '"
    00706         << toolName << "'" << endreq << Exception.what() << endreq;
    00707     sc = StatusCode::FAILURE;
    00708   }
    00709   catch (...)
    00710   {
    00711     MsgStream msg ( msgSvc(), name() );
    00712     msg << MSG::ERROR
    00713         << "UNKNOWN Exception caught whilst finalizing tool '"
    00714         << toolName << "'" << endreq;
    00715     sc = StatusCode::FAILURE;
    00716   }
    00717
    00718   return sc;
    00719
    00720 }
    00721
    00722 //------------------------------------------------------------------------------
    00723 unsigned long ToolSvc::totalToolRefCount( const ToolSvc::ListTools& toolList ) const
    00724 //------------------------------------------------------------------------------
    00725 {
    00726   unsigned long count = 0;
    00727   for ( ListTools::const_iterator iTool = toolList.begin();
    00728         iTool != toolList.end(); ++iTool ) {
    00729     count += refCountTool( *iTool );
    00730   }
    00731   return count;
    00732 }
    00733
    00734 //------------------------------------------------------------------------------
    00735 unsigned long ToolSvc::totalToolRefCount() const
    00736 //------------------------------------------------------------------------------
    00737 {
    00738   return totalToolRefCount( m_instancesTools );
    00739 }
    00740 //------------------------------------------------------------------------------
    00741 unsigned long ToolSvc::minimumToolRefCount() const
    00742 //------------------------------------------------------------------------------
    00743 {
    00744   unsigned long count = 0;
    00745   if ( m_instancesTools.size() > 0 ) {
    00746     ListTools::const_iterator iTool = m_instancesTools.begin();
    00747     // start with first
    00748     count = refCountTool( *iTool );
    00749     // then compare the others
    00750     for( ++iTool; iTool != m_instancesTools.end(); ++iTool ) {
    00751       count = std::min( count, refCountTool( *iTool ) );
    00752     }
    00753   }
    00754   return count;
    00755 }
    00756
    00757 void ToolSvc::registerObserver(IToolSvc::Observer* obs) {
    00758   if ( 0 == obs )
    00759     throw GaudiException( "Received NULL pointer", this->name() + "::registerObserver", StatusCode::FAILURE );
    00760   m_observers.push_back(obs);
    00761 }
    00762
    00763 void ToolSvc::unRegisterObserver(IToolSvc::Observer* obs) {
    00764   std::vector<IToolSvc::Observer*>::iterator i =
    00765     find(m_observers.begin(),m_observers.end(),obs);
    00766   if (i!=m_observers.end()) m_observers.erase(i);
    00767 }