| # Gaudi Framework, version v21r10p1 |

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