00001
00002 #include "GaudiKernel/MsgStream.h"
00003 #include "GaudiKernel/Service.h"
00004 #include "GaudiKernel/SvcFactory.h"
00005 #include "GaudiKernel/ISvcLocator.h"
00006 #include "GaudiKernel/IAlgorithm.h"
00007 #include "GaudiKernel/GaudiException.h"
00008 #include "GaudiKernel/AlgTool.h"
00009 #include "GaudiKernel/IHistorySvc.h"
00010 #include "GaudiKernel/ToolFactory.h"
00011 #include "ToolSvc.h"
00012 #include <algorithm>
00013 #include <map>
00014 #include <string>
00015 #include <cassert>
00016 #ifdef __ICC
00017
00018
00019 #pragma warning(disable:177)
00020 #endif
00021 #include "boost/lambda/bind.hpp"
00022
00023 #define ON_DEBUG if (UNLIKELY(outputLevel() <= MSG::DEBUG))
00024 #define ON_VERBOSE if (UNLIKELY(outputLevel() <= MSG::VERBOSE))
00025
00026
00027
00028 DECLARE_SERVICE_FACTORY(ToolSvc)
00029
00030 using ROOT::Reflex::PluginService;
00031 namespace bl = boost::lambda;
00032
00033
00034 ToolSvc::ToolSvc( const std::string& name, ISvcLocator* svc )
00035
00036 : base_class(name, svc),
00037 m_pHistorySvc(0)
00038 { }
00039
00040
00041 ToolSvc::~ToolSvc()
00042
00043 {
00044
00045 }
00046
00047
00048 StatusCode ToolSvc::initialize()
00049
00050 {
00051
00052
00053 StatusCode status = Service::initialize();
00054 if (UNLIKELY(status.isFailure()))
00055 {
00056 error() << "Unable to initialize the Service" << endmsg;
00057 return status;
00058 }
00059
00060
00061 if (UNLIKELY(setProperties().isFailure())) {
00062 error() << "Unable to set base properties" << endmsg;
00063 return StatusCode::FAILURE;
00064 }
00065
00066 return status;
00067 }
00068
00069
00070 StatusCode ToolSvc::finalize()
00071
00072 {
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00097 ListTools finalizedTools;
00098 info() << "Removing all tools created by ToolSvc" << endmsg;
00099
00100
00101 ON_DEBUG {
00102 MsgStream &log = debug();
00103 log << " 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
00112
00113
00126 bool fail(false);
00127 size_t toolCount = m_instancesTools.size();
00128 unsigned long startRefCount = 0;
00129 unsigned long endRefCount = totalToolRefCount();
00130 unsigned long startMinRefCount = 0;
00131 unsigned long endMinRefCount = minimumToolRefCount();
00132 while ( toolCount > 0 &&
00133 endRefCount > 0 &&
00134 (endRefCount != startRefCount || endMinRefCount != startMinRefCount) ) {
00135 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
00136 debug() << toolCount << " tools left to finalize. Summed refCounts: "
00137 << endRefCount << endmsg;
00138 debug() << "Will finalize tools with refCount <= "
00139 << endMinRefCount << endmsg;
00140 }
00141 startMinRefCount = endMinRefCount;
00142 startRefCount = endRefCount;
00143 unsigned long maxLoop = toolCount + 1;
00144 while ( --maxLoop > 0 && m_instancesTools.size() > 0 ) {
00145 IAlgTool* pTool = m_instancesTools.back();
00146
00147 m_instancesTools.pop_back();
00148 unsigned long count = refCountTool( pTool );
00149
00150 std::string toolName = pTool->name();
00151 if ( count <= startMinRefCount ) {
00152 ON_DEBUG debug() << " Performing finalization of " << toolName
00153 << " (refCount " << count << ")" << endmsg;
00154
00155
00156 if (!finalizeTool(pTool).isSuccess()) {
00157 warning() << " FAILURE finalizing " << toolName << endmsg;
00158 fail = true;
00159 }
00160
00161 finalizedTools.push_back(pTool);
00162 } else {
00163
00164
00165 ON_DEBUG debug() << " Delaying finalization of " << toolName
00166 << " (refCount " << count << ")" << endmsg;
00167 m_instancesTools.push_front(pTool);
00168 }
00169 }
00170 toolCount = m_instancesTools.size();
00171 endRefCount = totalToolRefCount();
00172 endMinRefCount = minimumToolRefCount();
00173 };
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 ON_DEBUG 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 ON_DEBUG debug() << " Performing deletion of " << pTool->name() << endmsg;
00195 } else {
00196 ON_VERBOSE verbose() << " Delaying deletion of " << pTool->name()
00197 << " (refCount " << count << ")" << endmsg;
00198
00199 finalizedTools.push_back(pTool);
00200 }
00201
00202 pTool->release();
00203 }
00204
00205
00206 if ( !m_instancesTools.empty() ) {
00207 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 error() << (*iTool)->name() << ": " << refCountTool( *iTool ) << " ";
00211 }
00212 error() << endmsg;
00213 }
00214
00215
00216 if ( finalizedTools.size() > 0 ) {
00217 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 error() << (*iTool)->name() << ": " << refCountTool( *iTool ) << " ";
00222 }
00223 error() << endmsg;
00224 }
00225
00226 if ( 0 != m_pHistorySvc ) {
00227 m_pHistorySvc->release();
00228 }
00229
00230
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
00260 if ( tooltype.empty() ) {
00261 error() << "retrieve(): No Tool Type/Name given" << endmsg;
00262 return StatusCode::FAILURE;
00263 }
00264
00265 {
00266
00267 const std::string::size_type pos = tooltype.find ( s_PUBLIC ) ;
00268 if ( std::string::npos != pos )
00269 {
00270
00271 parent = this ;
00272 return retrieve ( std::string( tooltype , 0 , pos ) ,
00273 iid , tool , parent , createIf ) ;
00274 }
00275 }
00276
00277 const std::string::size_type pos = tooltype.find('/');
00278 if( std::string::npos == pos ) {
00279 return retrieve ( tooltype , tooltype , iid , tool , parent , createIf );
00280 }
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
00298
00299 if( toolname.empty() || (std::string::npos != tooltype.find('/')) )
00300 { return retrieve ( tooltype , iid , tool , parent , createIf ) ; }
00301
00302 {
00303
00304 const std::string::size_type pos = toolname.find ( s_PUBLIC ) ;
00305 if ( std::string::npos != pos )
00306 {
00307
00308 parent = this ;
00309 return retrieve ( tooltype , std::string( toolname , 0 , pos ) ,
00310 iid , tool , parent , createIf ) ;
00311 }
00312 }
00313
00314 IAlgTool* itool = 0;
00315 StatusCode sc(StatusCode::FAILURE);
00316
00317 tool = 0;
00318
00319
00320 if( 0 == parent ) {
00321 parent = this;
00322 }
00323 const std::string fullname = nameTool( toolname, parent );
00324
00325
00326
00327 ListTools::const_iterator it;
00328 for( it = m_instancesTools.begin(); it != m_instancesTools.end(); ++it ) {
00329 if( (*it)->name() == fullname ) {
00330 ON_DEBUG debug() << "Retrieved tool " << toolname << endmsg;
00331 itool = *it;
00332 break;
00333 }
00334 }
00335
00336 if ( 0 == itool ) {
00337
00338
00339 if( UNLIKELY(!createIf) ) {
00340 warning() << "Tool " << toolname
00341 << " not found and creation not requested" << endmsg;
00342 return sc;
00343 }
00344 else {
00345 sc = create( tooltype, toolname, parent, itool );
00346 if ( sc.isFailure() ) { return sc; }
00347 }
00348 }
00349
00350
00351 sc = itool->queryInterface( iid, (void**)&tool);
00352 if( UNLIKELY(sc.isFailure()) ) {
00353 error() << "Tool " << toolname
00354 << " either does not implement the correct interface, or its version is incompatible"
00355 << endmsg;
00356 return sc;
00357 }
00361 if (!m_observers.empty()) {
00362 std::for_each( m_observers.begin(),
00363 m_observers.end(),
00364 bl::bind(&IToolSvc::Observer::onRetrieve,
00365 bl::_1,
00366 itool));
00367 }
00368
00369 return sc;
00370 }
00371
00372 std::vector<std::string> ToolSvc::getInstances( const std::string& toolType )
00373
00374 {
00375
00376 std::vector<std::string> tools;
00377
00378 ListTools::const_iterator it;
00379 for (it = m_instancesTools.begin(); it != m_instancesTools.end(); ++it) {
00380 if ((*it)->type() == toolType) {
00381 tools.push_back( (*it)->name() );
00382 }
00383 }
00384
00385 return tools;
00386
00387 }
00388
00389 StatusCode ToolSvc::releaseTool( IAlgTool* tool )
00390
00391 {
00392 StatusCode sc(StatusCode::SUCCESS);
00393
00394 if ( m_instancesTools.rend() != std::find( m_instancesTools.rbegin(),
00395 m_instancesTools.rend(),
00396 tool ) ) {
00397 unsigned long count = refCountTool(tool);
00398 if ( count == 1 ) {
00399 MsgStream log( msgSvc(), name() );
00400
00401
00402 if ( Gaudi::StateMachine::OFFLINE == m_targetState ) {
00403
00404
00405 log << MSG::DEBUG << " Performing finalization of " << tool->name()
00406 << " (refCount " << count << ")" << endmsg;
00407
00408 log << MSG::DEBUG << " Performing deletion of " << tool->name() << endmsg;
00409 } else {
00410 log << MSG::DEBUG << "Performing finalization and deletion of " << tool->name() << endmsg;
00411 }
00412 sc = finalizeTool(tool);
00413
00414 m_instancesTools.remove(tool);
00415 }
00416 tool->release();
00417 }
00418
00419 return sc;
00420 }
00421
00422
00423 StatusCode ToolSvc::create(const std::string& tooltype,
00424 const IInterface* parent,
00425 IAlgTool*& tool)
00426
00427 {
00428 const std::string & toolname = tooltype;
00429 return create( tooltype, toolname, parent, tool);
00430 }
00431
00432 namespace {
00435 class ToolCreateGuard {
00436 public:
00437 ToolCreateGuard(ToolSvc::ListTools &listTools):
00438 m_list(listTools),
00439 m_tool(0)
00440 {}
00442 void set(IAlgTool* tool) {
00443 if (m_tool) {
00444 m_list.remove(m_tool);
00445 delete m_tool;
00446 }
00447 if (tool) {
00448 m_tool = tool;
00449 m_list.push_back(m_tool);
00450 }
00451 }
00452 ToolCreateGuard& operator=(IAlgTool* tool) {
00453 set(tool);
00454 return *this;
00455 }
00457 IAlgTool* get() {
00458 return m_tool;
00459 }
00460 IAlgTool* operator->() const {
00461 assert(m_tool != 0);
00462 return m_tool;
00463 }
00465 IAlgTool* release() {
00466 IAlgTool* tool = m_tool;
00467 m_tool = 0;
00468 return tool;
00469 }
00471 ~ToolCreateGuard(){
00472 set(0);
00473 }
00474 private:
00476 ToolSvc::ListTools& m_list;
00478 IAlgTool* m_tool;
00479 };
00480 }
00481
00482 StatusCode ToolSvc::create(const std::string& tooltype,
00483 const std::string& toolname,
00484 const IInterface* parent,
00485 IAlgTool*& tool)
00486
00487 {
00488
00489 if ( UNLIKELY(tooltype.empty()) ) {
00490 error() << "create(): No Tool Type given" << endmsg;
00491 return StatusCode::FAILURE;
00492 }
00493
00494
00495 if ( 0 == parent ) parent = this;
00496
00497 tool = 0;
00498
00499
00500 ToolCreateGuard toolguard(m_instancesTools);
00501
00502
00503 const std::string fullname = nameTool(toolname, parent);
00504 if( UNLIKELY(existsTool(fullname)) ) {
00505 error() << "Tool " << fullname << " already exists" << endmsg;
00506 return StatusCode::FAILURE;
00507 }
00508
00509 try {
00510 toolguard = PluginService::Create<IAlgTool*>(tooltype, tooltype, fullname, parent);
00511 if ( UNLIKELY(! toolguard.get()) ){
00512 error() << "Cannot create tool " << tooltype << " (No factory found)" << endmsg;
00513 return StatusCode::FAILURE;
00514 }
00515 }
00516 catch ( const GaudiException& Exception ) {
00517
00518 fatal() << "Exception with tag=" << Exception.tag()
00519 << " is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
00520
00521
00522 fatal() << Exception << endmsg;
00523 return StatusCode::FAILURE;
00524 }
00525 catch( const std::exception& Exception ) {
00526
00527 fatal() << "Standard std::exception is caught whilst instantiating tool '"
00528 << tooltype << "'" << endmsg;
00529
00530
00531 fatal() << Exception.what() << endmsg;
00532 return StatusCode::FAILURE;
00533 }
00534 catch(...) {
00535
00536 fatal() << "UNKNOWN Exception is caught whilst instantiating tool '"
00537 << tooltype << "'" << endmsg;
00538 return StatusCode::FAILURE;
00539 }
00540 ON_VERBOSE verbose() << "Created tool " << tooltype << "/" << fullname << endmsg;
00541
00542
00543
00544
00545 AlgTool* mytool = dynamic_cast<AlgTool*> (toolguard.get());
00546 if ( mytool != 0 ) {
00547 StatusCode sc = mytool->setProperties();
00548 if ( UNLIKELY(sc.isFailure()) ) {
00549 error() << "Error setting properties for tool '"
00550 << fullname << "'" << endmsg;
00551 return sc;
00552 }
00553 }
00554
00555
00556 StatusCode sc (StatusCode::FAILURE,true);
00557 try {
00558 sc = toolguard->sysInitialize();
00559 }
00560
00561 catch ( const GaudiException & Exception )
00562 {
00563 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 error()
00572 << "Standard std::exception caught whilst initializing tool '"
00573 << fullname << "'" << endmsg << Exception.what() << endmsg;
00574 return StatusCode::FAILURE;
00575 }
00576 catch (...)
00577 {
00578 error()
00579 << "UNKNOWN Exception caught whilst initializing tool '"
00580 << fullname << "'" << endmsg;
00581 return StatusCode::FAILURE;
00582 }
00583
00584
00585 if ( UNLIKELY(sc.isFailure()) ) {
00586 error() << "Error initializing tool '" << fullname << "'" << endmsg;
00587 return sc;
00588 }
00589
00590
00591 if (m_state == Gaudi::StateMachine::RUNNING) {
00592 sc = toolguard->sysStart();
00593
00594 if (UNLIKELY(sc.isFailure())) {
00595 error() << "Error starting tool '" << fullname << "'" << endmsg;
00596 return sc;
00597 }
00598 }
00599
00600
00601
00602
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
00616
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; }
00634
00635
00636 IInterface* cparent = const_cast<IInterface*>( parent ) ;
00637
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 ;
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
00672 const std::string toolName = itool->name();
00673 StatusCode sc;
00674
00675
00676 try {
00677 sc = itool->sysFinalize();
00678 }
00679
00680 catch ( const GaudiException & Exception )
00681 {
00682 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 error()
00691 << "Standard std::exception caught whilst finalizing tool '"
00692 << toolName << "'" << endmsg << Exception.what() << endmsg;
00693 sc = StatusCode::FAILURE;
00694 }
00695 catch (...)
00696 {
00697 error()
00698 << "UNKNOWN Exception caught whilst finalizing tool '"
00699 << toolName << "'" << endmsg;
00700 sc = StatusCode::FAILURE;
00701 }
00702
00703 return sc;
00704
00705 }
00706
00707
00708 unsigned long ToolSvc::totalToolRefCount( const ToolSvc::ListTools& toolList ) const
00709
00710 {
00711 unsigned long count = 0;
00712 for ( ListTools::const_iterator iTool = toolList.begin();
00713 iTool != toolList.end(); ++iTool ) {
00714 count += refCountTool( *iTool );
00715 }
00716 return count;
00717 }
00718
00719
00720 unsigned long ToolSvc::totalToolRefCount() const
00721
00722 {
00723 return totalToolRefCount( m_instancesTools );
00724 }
00725
00726 unsigned long ToolSvc::minimumToolRefCount() const
00727
00728 {
00729 unsigned long count = 0;
00730 if ( m_instancesTools.size() > 0 ) {
00731 ListTools::const_iterator iTool = m_instancesTools.begin();
00732
00733 count = refCountTool( *iTool );
00734
00735 for( ++iTool; iTool != m_instancesTools.end(); ++iTool ) {
00736 count = std::min( count, refCountTool( *iTool ) );
00737 }
00738 }
00739 return count;
00740 }
00741
00742 void ToolSvc::registerObserver(IToolSvc::Observer* obs) {
00743 if ( 0 == obs )
00744 throw GaudiException( "Received NULL pointer", this->name() + "::registerObserver", StatusCode::FAILURE );
00745 m_observers.push_back(obs);
00746 }
00747
00748 void ToolSvc::unRegisterObserver(IToolSvc::Observer* obs) {
00749 std::vector<IToolSvc::Observer*>::iterator i =
00750 find(m_observers.begin(),m_observers.end(),obs);
00751 if (i!=m_observers.end()) m_observers.erase(i);
00752 }
00753
00754
00755 StatusCode
00756 ToolSvc::start()
00757
00758 {
00759
00760 ON_DEBUG debug() << "START transition for AlgTools" << endmsg;
00761
00762 bool fail(false);
00763 for ( ListTools::const_iterator iTool = m_instancesTools.begin();
00764 iTool != m_instancesTools.end(); ++iTool ) {
00765 ON_VERBOSE verbose() << (*iTool)->name() << "::start()" << endmsg;
00766
00767 if (UNLIKELY(!(*iTool)->sysStart().isSuccess())) {
00768 fail = true;
00769 error() << (*iTool)->name() << " failed to start()" << endmsg;
00770 }
00771
00772 }
00773
00774 if (UNLIKELY(fail)) {
00775 error() << "One or more AlgTools failed to start()" << endmsg;
00776 return StatusCode::FAILURE;
00777 } else {
00778 return StatusCode::SUCCESS;
00779 }
00780
00781 }
00782
00783
00784 StatusCode
00785 ToolSvc::stop()
00786
00787 {
00788
00789 ON_DEBUG debug() << "STOP transition for AlgTools" << endmsg;
00790
00791 bool fail(false);
00792 for ( ListTools::const_iterator iTool = m_instancesTools.begin();
00793 iTool != m_instancesTools.end(); ++iTool ) {
00794 ON_VERBOSE verbose() << (*iTool)->name() << "::stop()" << endmsg;
00795
00796 if (UNLIKELY(!(*iTool)->sysStop().isSuccess())) {
00797 fail = true;
00798 error() << (*iTool)->name() << " failed to stop()" << endmsg;
00799 }
00800
00801 }
00802
00803 if (UNLIKELY(fail)) {
00804 error() << "One or more AlgTools failed to stop()" << endmsg;
00805 return StatusCode::FAILURE;
00806 } else {
00807 return StatusCode::SUCCESS;
00808 }
00809
00810 }