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()) fail = true;
00157
00158 finalizedTools.push_back(pTool);
00159 } else {
00160
00161
00162 ON_DEBUG debug() << " Delaying finalization of " << toolName
00163 << " (refCount " << count << ")" << endmsg;
00164 m_instancesTools.push_front(pTool);
00165 }
00166 }
00167 toolCount = m_instancesTools.size();
00168 endRefCount = totalToolRefCount();
00169 endMinRefCount = minimumToolRefCount();
00170 };
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 ON_DEBUG debug() << "Deleting " << finalizedTools.size() << " finalized tools" << endmsg;
00185 unsigned long maxLoop = totalToolRefCount( finalizedTools ) + 1;
00186 while ( --maxLoop > 0 && finalizedTools.size() > 0 ) {
00187 IAlgTool* pTool = finalizedTools.front();
00188 finalizedTools.pop_front();
00189 unsigned long count = refCountTool( pTool );
00190 if ( count == 1 ) {
00191 ON_DEBUG debug() << " Performing deletion of " << pTool->name() << endmsg;
00192 } else {
00193 ON_VERBOSE verbose() << " Delaying deletion of " << pTool->name()
00194 << " (refCount " << count << ")" << endmsg;
00195
00196 finalizedTools.push_back(pTool);
00197 }
00198
00199 pTool->release();
00200 }
00201
00202
00203 if ( !m_instancesTools.empty() ) {
00204 error() << "Unable to finalize and delete the following tools : ";
00205 for ( ListTools::const_iterator iTool = m_instancesTools.begin();
00206 iTool != m_instancesTools.end(); ++iTool ) {
00207 error() << (*iTool)->name() << ": " << refCountTool( *iTool ) << " ";
00208 }
00209 error() << endmsg;
00210 }
00211
00212
00213 if ( finalizedTools.size() > 0 ) {
00214 error() << "Failed to delete the following " << finalizedTools.size()
00215 << " finalized tools. Bug in ToolSvc::finalize()?: ";
00216 for ( ListTools::const_iterator iTool = finalizedTools.begin();
00217 iTool != finalizedTools.end(); ++iTool ) {
00218 error() << (*iTool)->name() << ": " << refCountTool( *iTool ) << " ";
00219 }
00220 error() << endmsg;
00221 }
00222
00223 if ( 0 != m_pHistorySvc ) {
00224 m_pHistorySvc->release();
00225 }
00226
00227
00228 if (! Service::finalize().isSuccess() || fail) {
00229 return StatusCode::FAILURE;
00230 } else {
00231 return StatusCode::SUCCESS;
00232 }
00233
00234
00235 }
00236
00237
00241
00242 namespace
00243 {
00244 const std::string s_PUBLIC = ":PUBLIC" ;
00245 }
00246
00247
00248 StatusCode ToolSvc::retrieve ( const std::string& tooltype ,
00249 const InterfaceID& iid ,
00250 IAlgTool*& tool ,
00251 const IInterface* parent ,
00252 bool createIf )
00253
00254 {
00255
00256
00257 if ( tooltype.empty() ) {
00258 error() << "retrieve(): No Tool Type/Name given" << endmsg;
00259 return StatusCode::FAILURE;
00260 }
00261
00262 {
00263
00264 const std::string::size_type pos = tooltype.find ( s_PUBLIC ) ;
00265 if ( std::string::npos != pos )
00266 {
00267
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 }
00278 const std::string newtype ( tooltype , 0 , pos ) ;
00279 const std::string newname ( tooltype , pos + 1 , std::string::npos ) ;
00280 return retrieve ( newtype , newname , iid , tool , parent , createIf ) ;
00281 }
00282
00283
00284
00285
00286 StatusCode ToolSvc::retrieve ( const std::string& tooltype ,
00287 const std::string& toolname ,
00288 const InterfaceID& iid ,
00289 IAlgTool*& tool ,
00290 const IInterface* parent ,
00291 bool createIf )
00292
00293 {
00294
00295
00296 if( toolname.empty() || (std::string::npos != tooltype.find('/')) )
00297 { return retrieve ( tooltype , iid , tool , parent , createIf ) ; }
00298
00299 {
00300
00301 const std::string::size_type pos = toolname.find ( s_PUBLIC ) ;
00302 if ( std::string::npos != pos )
00303 {
00304
00305 parent = this ;
00306 return retrieve ( tooltype , std::string( toolname , 0 , pos ) ,
00307 iid , tool , parent , createIf ) ;
00308 }
00309 }
00310
00311 IAlgTool* itool = 0;
00312 StatusCode sc(StatusCode::FAILURE);
00313
00314 tool = 0;
00315
00316
00317 if( 0 == parent ) {
00318 parent = this;
00319 }
00320 const std::string fullname = nameTool( toolname, parent );
00321
00322
00323
00324 ListTools::const_iterator it;
00325 for( it = m_instancesTools.begin(); it != m_instancesTools.end(); ++it ) {
00326 if( (*it)->name() == fullname ) {
00327 ON_DEBUG debug() << "Retrieved tool " << toolname << endmsg;
00328 itool = *it;
00329 break;
00330 }
00331 }
00332
00333 if ( 0 == itool ) {
00334
00335
00336 if( UNLIKELY(!createIf) ) {
00337 warning() << "Tool " << toolname
00338 << " not found and creation not requested" << endmsg;
00339 return sc;
00340 }
00341 else {
00342 sc = create( tooltype, toolname, parent, itool );
00343 if ( sc.isFailure() ) { return sc; }
00344 }
00345 }
00346
00347
00348 sc = itool->queryInterface( iid, (void**)&tool);
00349 if( UNLIKELY(sc.isFailure()) ) {
00350 error() << "Tool " << toolname
00351 << " either does not implement the correct interface, or its version is incompatible"
00352 << endmsg;
00353 return sc;
00354 }
00358 if (!m_observers.empty()) {
00359 std::for_each( m_observers.begin(),
00360 m_observers.end(),
00361 bl::bind(&IToolSvc::Observer::onRetrieve,
00362 bl::_1,
00363 itool));
00364 }
00365
00366 return sc;
00367 }
00368
00369 std::vector<std::string> ToolSvc::getInstances( const std::string& toolType )
00370
00371 {
00372
00373 std::vector<std::string> tools;
00374
00375 ListTools::const_iterator it;
00376 for (it = m_instancesTools.begin(); it != m_instancesTools.end(); ++it) {
00377 if ((*it)->type() == toolType) {
00378 tools.push_back( (*it)->name() );
00379 }
00380 }
00381
00382 return tools;
00383
00384 }
00385
00386 StatusCode ToolSvc::releaseTool( IAlgTool* tool )
00387
00388 {
00389 StatusCode sc(StatusCode::SUCCESS);
00390
00391 if ( m_instancesTools.rend() != std::find( m_instancesTools.rbegin(),
00392 m_instancesTools.rend(),
00393 tool ) ) {
00394 unsigned long count = refCountTool(tool);
00395 if ( count == 1 ) {
00396 MsgStream log( msgSvc(), name() );
00397
00398
00399 if ( Gaudi::StateMachine::OFFLINE == m_targetState ) {
00400
00401
00402 log << MSG::DEBUG << " Performing finalization of " << tool->name()
00403 << " (refCount " << count << ")" << endmsg;
00404
00405 log << MSG::DEBUG << " Performing deletion of " << tool->name() << endmsg;
00406 } else {
00407 log << MSG::DEBUG << "Performing finalization and deletion of " << tool->name() << endmsg;
00408 }
00409 sc = finalizeTool(tool);
00410
00411 m_instancesTools.remove(tool);
00412 }
00413 tool->release();
00414 }
00415
00416 return sc;
00417 }
00418
00419
00420 StatusCode ToolSvc::create(const std::string& tooltype,
00421 const IInterface* parent,
00422 IAlgTool*& tool)
00423
00424 {
00425 const std::string & toolname = tooltype;
00426 return create( tooltype, toolname, parent, tool);
00427 }
00428
00429 namespace {
00432 class ToolCreateGuard {
00433 public:
00434 ToolCreateGuard(ToolSvc::ListTools &listTools):
00435 m_list(listTools),
00436 m_tool(0)
00437 {}
00439 void set(IAlgTool* tool) {
00440 if (m_tool) {
00441 m_list.remove(m_tool);
00442 delete m_tool;
00443 }
00444 if (tool) {
00445 m_tool = tool;
00446 m_list.push_back(m_tool);
00447 }
00448 }
00449 ToolCreateGuard& operator=(IAlgTool* tool) {
00450 set(tool);
00451 return *this;
00452 }
00454 IAlgTool* get() {
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
00486 if ( UNLIKELY(tooltype.empty()) ) {
00487 error() << "create(): No Tool Type given" << endmsg;
00488 return StatusCode::FAILURE;
00489 }
00490
00491
00492 if ( 0 == parent ) parent = this;
00493
00494 tool = 0;
00495
00496
00497 ToolCreateGuard toolguard(m_instancesTools);
00498
00499
00500 const std::string fullname = nameTool(toolname, parent);
00501 if( UNLIKELY(existsTool(fullname)) ) {
00502 error() << "Tool " << fullname << " already exists" << endmsg;
00503 return StatusCode::FAILURE;
00504 }
00505
00506 try {
00507 toolguard = PluginService::Create<IAlgTool*>(tooltype, tooltype, fullname, parent);
00508 if ( UNLIKELY(! toolguard.get()) ){
00509 error() << "Cannot create tool " << tooltype << " (No factory found)" << endmsg;
00510 return StatusCode::FAILURE;
00511 }
00512 }
00513 catch ( const GaudiException& Exception ) {
00514
00515 fatal() << "Exception with tag=" << Exception.tag()
00516 << " is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
00517
00518
00519 fatal() << Exception << endmsg;
00520 return StatusCode::FAILURE;
00521 }
00522 catch( const std::exception& Exception ) {
00523
00524 fatal() << "Standard std::exception is caught whilst instantiating tool '"
00525 << tooltype << "'" << endmsg;
00526
00527
00528 fatal() << Exception.what() << endmsg;
00529 return StatusCode::FAILURE;
00530 }
00531 catch(...) {
00532
00533 fatal() << "UNKNOWN Exception is caught whilst instantiating tool '"
00534 << tooltype << "'" << endmsg;
00535 return StatusCode::FAILURE;
00536 }
00537 ON_VERBOSE verbose() << "Created tool " << tooltype << "/" << fullname << endmsg;
00538
00539
00540
00541
00542 AlgTool* mytool = dynamic_cast<AlgTool*> (toolguard.get());
00543 if ( mytool != 0 ) {
00544 StatusCode sc = mytool->setProperties();
00545 if ( UNLIKELY(sc.isFailure()) ) {
00546 error() << "Error setting properties for tool '"
00547 << fullname << "'" << endmsg;
00548 return sc;
00549 }
00550 }
00551
00552
00553 StatusCode sc (StatusCode::FAILURE,true);
00554 try {
00555 sc = toolguard->sysInitialize();
00556 }
00557
00558 catch ( const GaudiException & Exception )
00559 {
00560 error()
00561 << "GaudiException with tag=" << Exception.tag()
00562 << " caught whilst initializing tool '" << fullname << "'" << endmsg
00563 << Exception << endmsg;
00564 return StatusCode::FAILURE;
00565 }
00566 catch( const std::exception & Exception )
00567 {
00568 error()
00569 << "Standard std::exception caught whilst initializing tool '"
00570 << fullname << "'" << endmsg << Exception.what() << endmsg;
00571 return StatusCode::FAILURE;
00572 }
00573 catch (...)
00574 {
00575 error()
00576 << "UNKNOWN Exception caught whilst initializing tool '"
00577 << fullname << "'" << endmsg;
00578 return StatusCode::FAILURE;
00579 }
00580
00581
00582 if ( UNLIKELY(sc.isFailure()) ) {
00583 error() << "Error initializing tool '" << fullname << "'" << endmsg;
00584 return sc;
00585 }
00586
00587
00588 if (m_state == Gaudi::StateMachine::RUNNING) {
00589 sc = toolguard->sysStart();
00590
00591 if (UNLIKELY(sc.isFailure())) {
00592 error() << "Error starting tool '" << fullname << "'" << endmsg;
00593 return sc;
00594 }
00595 }
00596
00597
00598
00599
00600 tool = toolguard.release();
00601
00605 if (!m_observers.empty()) {
00606 std::for_each( m_observers.begin(),
00607 m_observers.end(),
00608 bl::bind(&IToolSvc::Observer::onCreate,
00609 bl::_1,
00610 tool));
00611 }
00612
00613
00614 if (m_pHistorySvc != 0 ||
00615 service("HistorySvc",m_pHistorySvc,false).isSuccess() ) {
00616 m_pHistorySvc->registerAlgTool(*tool).ignore();
00617 }
00618
00619 return StatusCode::SUCCESS;
00620
00621 }
00622
00623
00624 std::string ToolSvc::nameTool( const std::string& toolname,
00625 const IInterface* parent )
00626
00627 {
00628
00629 std::string fullname = "";
00630 if ( parent == 0 ) { return this->name() + "." + toolname; }
00631
00632
00633 IInterface* cparent = const_cast<IInterface*>( parent ) ;
00634
00635 INamedInterface* _p = 0 ;
00636 StatusCode sc = cparent->queryInterface( INamedInterface::interfaceID() , pp_cast<void>(&_p) ) ;
00637 if ( sc.isSuccess() )
00638 {
00639 fullname = _p->name() + "." + toolname ;
00640 _p->release() ;
00641 return fullname ;
00642 }
00643
00644 MsgStream log ( msgSvc(), name() );
00645 log << MSG::ERROR
00646 << "Private Tools only allowed for components implementing INamedInterface"
00647 << endmsg;
00648
00649 return "." + toolname ;
00650 }
00651
00652
00653 bool ToolSvc::existsTool( const std::string& fullname) const
00654
00655 {
00656 for ( ListTools::const_iterator it = m_instancesTools.begin();
00657 it != m_instancesTools.end(); ++it ) {
00658 if ( (*it)->name() == fullname ) { return true; }
00659 }
00660 return false;
00661 }
00662
00663
00664 StatusCode ToolSvc::finalizeTool( IAlgTool* itool ) const
00665
00666 {
00667
00668
00669 const std::string toolName = itool->name();
00670 StatusCode sc;
00671
00672
00673 try {
00674 sc = itool->sysFinalize();
00675 }
00676
00677 catch ( const GaudiException & Exception )
00678 {
00679 error()
00680 << "GaudiException with tag=" << Exception.tag()
00681 << " caught whilst finalizing tool '" << toolName << "'" << endmsg
00682 << Exception << endmsg;
00683 sc = StatusCode::FAILURE;
00684 }
00685 catch( const std::exception & Exception )
00686 {
00687 error()
00688 << "Standard std::exception caught whilst finalizing tool '"
00689 << toolName << "'" << endmsg << Exception.what() << endmsg;
00690 sc = StatusCode::FAILURE;
00691 }
00692 catch (...)
00693 {
00694 error()
00695 << "UNKNOWN Exception caught whilst finalizing tool '"
00696 << toolName << "'" << endmsg;
00697 sc = StatusCode::FAILURE;
00698 }
00699
00700 return sc;
00701
00702 }
00703
00704
00705 unsigned long ToolSvc::totalToolRefCount( const ToolSvc::ListTools& toolList ) const
00706
00707 {
00708 unsigned long count = 0;
00709 for ( ListTools::const_iterator iTool = toolList.begin();
00710 iTool != toolList.end(); ++iTool ) {
00711 count += refCountTool( *iTool );
00712 }
00713 return count;
00714 }
00715
00716
00717 unsigned long ToolSvc::totalToolRefCount() const
00718
00719 {
00720 return totalToolRefCount( m_instancesTools );
00721 }
00722
00723 unsigned long ToolSvc::minimumToolRefCount() const
00724
00725 {
00726 unsigned long count = 0;
00727 if ( m_instancesTools.size() > 0 ) {
00728 ListTools::const_iterator iTool = m_instancesTools.begin();
00729
00730 count = refCountTool( *iTool );
00731
00732 for( ++iTool; iTool != m_instancesTools.end(); ++iTool ) {
00733 count = std::min( count, refCountTool( *iTool ) );
00734 }
00735 }
00736 return count;
00737 }
00738
00739 void ToolSvc::registerObserver(IToolSvc::Observer* obs) {
00740 if ( 0 == obs )
00741 throw GaudiException( "Received NULL pointer", this->name() + "::registerObserver", StatusCode::FAILURE );
00742 m_observers.push_back(obs);
00743 }
00744
00745 void ToolSvc::unRegisterObserver(IToolSvc::Observer* obs) {
00746 std::vector<IToolSvc::Observer*>::iterator i =
00747 find(m_observers.begin(),m_observers.end(),obs);
00748 if (i!=m_observers.end()) m_observers.erase(i);
00749 }
00750
00751
00752 StatusCode
00753 ToolSvc::start()
00754
00755 {
00756
00757 ON_DEBUG debug() << "START transition for AlgTools" << endmsg;
00758
00759 bool fail(false);
00760 for ( ListTools::const_iterator iTool = m_instancesTools.begin();
00761 iTool != m_instancesTools.end(); ++iTool ) {
00762 ON_VERBOSE verbose() << (*iTool)->name() << "::start()" << endmsg;
00763
00764 if (UNLIKELY(!(*iTool)->sysStart().isSuccess())) {
00765 fail = true;
00766 error() << (*iTool)->name() << " failed to start()" << endmsg;
00767 }
00768
00769 }
00770
00771 if (UNLIKELY(fail)) {
00772 error() << "One or more AlgTools failed to start()" << endmsg;
00773 return StatusCode::FAILURE;
00774 } else {
00775 return StatusCode::SUCCESS;
00776 }
00777
00778 }
00779
00780
00781 StatusCode
00782 ToolSvc::stop()
00783
00784 {
00785
00786 ON_DEBUG debug() << "STOP transition for AlgTools" << endmsg;
00787
00788 bool fail(false);
00789 for ( ListTools::const_iterator iTool = m_instancesTools.begin();
00790 iTool != m_instancesTools.end(); ++iTool ) {
00791 ON_VERBOSE verbose() << (*iTool)->name() << "::stop()" << endmsg;
00792
00793 if (UNLIKELY(!(*iTool)->sysStop().isSuccess())) {
00794 fail = true;
00795 error() << (*iTool)->name() << " failed to stop()" << endmsg;
00796 }
00797
00798 }
00799
00800 if (UNLIKELY(fail)) {
00801 error() << "One or more AlgTools failed to stop()" << endmsg;
00802 return StatusCode::FAILURE;
00803 } else {
00804 return StatusCode::SUCCESS;
00805 }
00806
00807 }