| # Gaudi Framework, version v21r6 |

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