| # Gaudi Framework, version v21r8 |

Home |  | Generated: 17 Mar 2010

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