| # Gaudi Framework, version v23r1 |

Home |  | Generated: Wed Feb 29 2012

# ServiceManager.cpp

Go to the documentation of this file.

    00001 // Include files
    00002 #include "ServiceManager.h"
    00003 #include "GaudiKernel/IService.h"
    00004 #include "GaudiKernel/SvcFactory.h"
    00005 #include "GaudiKernel/MsgStream.h"
    00006 #include "GaudiKernel/TypeNameString.h"
    00007 #include "GaudiKernel/System.h"
    00008 #include "GaudiKernel/Service.h"
    00009 #include "GaudiKernel/ObjectFactory.h"
    00010
    00011 #include <iostream>
    00012 #include <cassert>
    00013
    00014 #define ON_DEBUG if (msgLevel(MSG::DEBUG))
    00015 #define ON_VERBOSE if (msgLevel(MSG::VERBOSE))
    00016
    00017 #define DEBMSG ON_DEBUG debug()
    00018 #define VERMSG ON_VERBOSE verbose()
    00019
    00020 using ROOT::Reflex::PluginService;
    00021
    00023 static SmartIF<IService> no_service;
    00024
    00025 // constructor
    00026 ServiceManager::ServiceManager(IInterface* application):
    00027   base_class(application, IService::interfaceID()),
    00028   m_loopCheck(true),
    00029   m_appSvc(application)
    00030 {
    00031   // Set the service locator to myself
    00032   m_svcLocator = static_cast<ISvcLocator*>(this);
    00033
    00034   addRef(); // Initial count set to 1
    00035 }
    00036
    00037 // destructor
    00038 ServiceManager::~ServiceManager() {
    00039   //-- inform the orphan services that I am gone....
    00040   for (ListSvc::iterator it = m_listsvc.begin(); it != m_listsvc.end(); it++ ) {
    00041     it->service->setServiceManager(0);
    00042   }
    00043 }
    00044
    00045 //------------------------------------------------------------------------------
    00046 // Instantiate a service
    00047 SmartIF<IService>& ServiceManager::createService(const Gaudi::Utils::TypeNameString& typeName)
    00048 //------------------------------------------------------------------------------
    00049 {
    00050   // Check if the service is already existing
    00051   if(existsService(typeName.name())) {
    00052     // return an error because a service with that name already exists
    00053     return no_service;
    00054   }
    00055
    00057   StatusCode rc = StatusCode::FAILURE;
    00058   rc.setChecked(); //hack to avoid going into infinite recursion on ~StatusCode
    00059
    00060   const std::string &name = typeName.name();
    00061   std::string type = typeName.type();
    00062   if (!typeName.haveType()) { // the type is not explicit
    00063     // see we have some specific type mapping for the name
    00064     MapType::iterator it = m_maptype.find(typeName.name());
    00065     if( it != m_maptype.end() ) {
    00066       type = (*it).second; // use the declared type
    00067     }
    00068   }
    00069
    00071   std::string::size_type ip;
    00072   if ( (ip = type.find("__")) != std::string::npos) {
    00073     type.erase(ip,type.length());
    00074   }
    00075
    00076   IService* service = PluginService::Create<IService*>(type, name, static_cast<ISvcLocator*>(this)); // serviceLocator().get());
    00077   if ( !service ) {
    00078     service = PluginService::CreateWithId<IService*>(type, name, static_cast<ISvcLocator*>(this)); // serviceLocator().get());
    00079   }
    00080
    00081   if ( service ) {
    00082     m_listsvc.push_back(service);
    00083     // Check the compatibility of the version of the interface obtained
    00084     if( !isValidInterface(service) ) {
    00085       fatal() << "Incompatible interface IService version for " << type << endmsg;
    00086       return no_service;
    00087     }
    00088     service->setServiceManager(this);
    00089     return m_listsvc.back().service;
    00090   }
    00091   fatal() << "No Service factory for " << type << " available." << endmsg;
    00092   return no_service;
    00093 }
    00094
    00095 //------------------------------------------------------------------------------
    00096 // add a service to the managed list
    00097 StatusCode ServiceManager::addService(IService* svc, int prio)
    00098 //------------------------------------------------------------------------------
    00099 {
    00100   ListSvc::iterator it = find(svc);
    00101   if (it != m_listsvc.end()) {
    00102     it->priority = prio; // if the service is already known, it is equivalent to a setPriority
    00103     it->active = true;   // and make it active
    00104   } else {
    00105     m_listsvc.push_back(ServiceItem(svc,prio,true));
    00106   }
    00107   return StatusCode::SUCCESS;
    00108 }
    00109
    00110 //------------------------------------------------------------------------------
    00111 // add the service with the give type and name to the active list
    00112 StatusCode ServiceManager::addService(const Gaudi::Utils::TypeNameString& typeName, int prio)
    00113 //------------------------------------------------------------------------------
    00114 {
    00115   ListSvc::iterator it = find(typeName.name()); // try to find the service by name
    00116   if (it == m_listsvc.end()) { // not found
    00117     // If the service does not exist, we create it
    00118     SmartIF<IService> &svc = createService(typeName);
    00119     if (svc.isValid()) {
    00120       StatusCode sc = StatusCode(StatusCode::SUCCESS, true);
    00121       if (targetFSMState() >= Gaudi::StateMachine::INITIALIZED) {
    00122         sc = svc->sysInitialize();
    00123         if (sc.isSuccess() && targetFSMState() >= Gaudi::StateMachine::RUNNING) {
    00124           sc = svc->sysStart();
    00125         }
    00126       }
    00127       it = find(svc.get()); // now it is in the list because createService added it
    00128       if(sc.isFailure()) { // if initialization failed, remove it from the list
    00129         error() << "Unable to initialize service \"" << typeName.name() << "\""
    00130                 << endmsg;
    00131         m_listsvc.erase(it);
    00132         // Note: removing it from the list + the SmartIF going out of scope should trigger the delete
    00133         // delete svc.get();
    00134         return sc;
    00135       } else { // initialization successful, we can work with the service
    00136         // Move the just initialized service to the back of the list
    00137         // (we care more about order of initialization than of creation)
    00138         m_listsvc.push_back(*it);
    00139         m_listsvc.erase(it);
    00140         it = --m_listsvc.end(); // last entry (the iterator was invalidated by erase)
    00141       }
    00142     } else {
    00143       return StatusCode::FAILURE;
    00144     }
    00145   }
    00146   // 'it' is defined because either we found the service or we created it
    00147   // Now we can activate the service
    00148   it->priority = prio; // if the service is already known, it is equivalent to a setPriority
    00149   it->active = true;   // and make it active
    00150   return StatusCode(StatusCode::SUCCESS, true);
    00151 }
    00152
    00153 //------------------------------------------------------------------------------
    00154 // Returns a smart pointer to a service.
    00155 SmartIF<IService> &ServiceManager::service(const Gaudi::Utils::TypeNameString &typeName, const bool createIf) {
    00156   const std::string &name = typeName.name();
    00157
    00158   // Acquire the RAII lock to avoid simultaneous attempts from different threads to initialize a service
    00159   boost::lock_guard<boost::recursive_mutex> lck(m_svcinitmutex);
    00160
    00161   ListSvc::iterator it = find(name);
    00162
    00163   if (it !=  m_listsvc.end()) {
    00164     if (m_loopCheck &&
    00165         (createIf && it->service->FSMState() == Gaudi::StateMachine::CONFIGURED)) {
    00166       error()
    00167           << "Initialization loop detected when creating service \"" << name
    00168           << "\""
    00169           << endmsg;
    00170       return no_service;
    00171     }
    00172     return it->service;
    00173   } else {
    00174     // Service not found. The user may be interested in one of the interfaces
    00175     // of the application manager itself
    00176     if( name == "ApplicationMgr" ||
    00177         name == "APPMGR" ||
    00178         name == "" ) {
    00179       return m_appSvc;
    00180     } else if ( createIf ){
    00181       //last resort: we try to create the service
    00182       if (addService(typeName).isSuccess()){
    00183         return find(name)->service;
    00184       }
    00185     }
    00186   }
    00187   return no_service;
    00188 }
    00189
    00190 //------------------------------------------------------------------------------
    00191 const std::list<IService*>& ServiceManager::getServices( ) const
    00192 //------------------------------------------------------------------------------
    00193 {
    00194   m_listOfPtrs.clear();
    00195   for (ListSvc::const_iterator it = m_listsvc.begin(); it != m_listsvc.end(); ++it) {
    00196     m_listOfPtrs.push_back(const_cast<IService*>(it->service.get()));
    00197   }
    00198   return m_listOfPtrs;
    00199 }
    00200
    00201 //------------------------------------------------------------------------------
    00202 bool ServiceManager::existsService( const std::string& name) const
    00203 //------------------------------------------------------------------------------
    00204 {
    00205   return find(name) != m_listsvc.end();
    00206 }
    00207
    00208 //------------------------------------------------------------------------------
    00209 StatusCode ServiceManager::removeService(IService* svc)
    00210 //------------------------------------------------------------------------------
    00211 {
    00212   ListSvc::iterator it = find(svc);
    00213   if (it != m_listsvc.end()) {
    00214     m_listsvc.erase(it);
    00215     return StatusCode(StatusCode::SUCCESS,true);
    00216   }
    00217   return StatusCode(StatusCode::FAILURE,true);
    00218 }
    00219
    00220 //------------------------------------------------------------------------------
    00221 StatusCode ServiceManager::removeService(const std::string& name)
    00222 //------------------------------------------------------------------------------
    00223 {
    00224   ListSvc::iterator it = find(name);
    00225   if (it != m_listsvc.end()) {
    00226     m_listsvc.erase(it);
    00227     return StatusCode::SUCCESS;
    00228   }
    00229   return StatusCode::FAILURE;
    00230 }
    00231
    00232 //------------------------------------------------------------------------------
    00233 StatusCode ServiceManager::declareSvcType( const std::string& svcname,
    00234                                            const std::string& svctype )
    00235 //------------------------------------------------------------------------------
    00236 {
    00237   std::pair<MapType::iterator, bool> p = m_maptype.insert(std::make_pair(svcname, svctype));
    00238   if( p.second == false) {
    00239     m_maptype.erase ( p.first );
    00240     p = m_maptype.insert(std::make_pair(svcname, svctype) );
    00241     if( p.second == false) return StatusCode::FAILURE;
    00242   }
    00243   return StatusCode::SUCCESS;
    00244 }
    00245
    00246 //------------------------------------------------------------------------------
    00247 StatusCode ServiceManager::initialize()
    00248 //------------------------------------------------------------------------------
    00249 {
    00250   m_listsvc.sort(); // ensure that the list is ordered by priority
    00251   // we work on a copy to avoid to operate twice on the services created on demand
    00252   // (which are already in the correct state.
    00253   ListSvc tmpList(m_listsvc);
    00254
    00255   StatusCode sc(StatusCode::SUCCESS, true);
    00256   // call initialize() for all services
    00257   for (ListSvc::iterator it = tmpList.begin(); it != tmpList.end(); ++it ) {
    00258     if (!it->active) continue; // only act on active services
    00259     const std::string& name = it->service->name();
    00260     switch (it->service->FSMState()) {
    00261     case Gaudi::StateMachine::INITIALIZED:
    00262       DEBMSG << "Service " << name << " already initialized" << endmsg;
    00263       break;
    00264     case Gaudi::StateMachine::OFFLINE:
    00265       DEBMSG << "Initializing service " << name << endmsg;
    00266       sc = it->service->sysInitialize();
    00267       if( !sc.isSuccess() ) {
    00268         error() << "Unable to initialize Service: " << name << endmsg;
    00269         return sc;
    00270       } break;
    00271     default:
    00272       error() << "Service " << name
    00273           << " not in the correct state to be initialized ("
    00274           << it->service->FSMState() << ")" << endmsg;
    00275       return StatusCode::FAILURE;
    00276     }
    00277   }
    00278   return StatusCode::SUCCESS;
    00279 }
    00280
    00281 //------------------------------------------------------------------------------
    00282 StatusCode ServiceManager::start()
    00283 //------------------------------------------------------------------------------
    00284 {
    00285   m_listsvc.sort(); // ensure that the list is ordered by priority
    00286   // we work on a copy to avoid to operate twice on the services created on demand
    00287   // (which are already in the correct state.
    00288   ListSvc tmpList(m_listsvc);
    00289
    00290   StatusCode sc(StatusCode::SUCCESS, true);
    00291   // call initialize() for all services
    00292   for (ListSvc::iterator it = tmpList.begin(); it != tmpList.end(); ++it ) {
    00293     if (!it->active) continue; // only act on active services
    00294     const std::string& name = it->service->name();
    00295     switch (it->service->FSMState()) {
    00296     case Gaudi::StateMachine::RUNNING:
    00297       DEBMSG << "Service " << name
    00298           << " already started" << endmsg;
    00299       break;
    00300     case Gaudi::StateMachine::INITIALIZED:
    00301       DEBMSG << "Starting service " << name << endmsg;
    00302       sc = it->service->sysStart();
    00303       if( !sc.isSuccess() ) {
    00304         error() << "Unable to start Service: " << name << endmsg;
    00305         return sc;
    00306       } break;
    00307     default:
    00308       error() << "Service " << name
    00309           << " not in the correct state to be started ("
    00310           << it->service->FSMState() << ")" << endmsg;
    00311       return StatusCode::FAILURE;
    00312     }
    00313   }
    00314   return StatusCode::SUCCESS;
    00315 }
    00316
    00317
    00318 //------------------------------------------------------------------------------
    00319 StatusCode ServiceManager::stop()
    00320 //------------------------------------------------------------------------------
    00321 {
    00322   m_listsvc.sort(); // ensure that the list is ordered by priority
    00323   // we work on a copy to avoid to operate twice on the services created on demand
    00324   // (which are already in the correct state.
    00325   ListSvc tmpList(m_listsvc);
    00326
    00327   StatusCode sc(StatusCode::SUCCESS, true);
    00328   ListSvc::reverse_iterator it;
    00329   // call stop() for all services
    00330   for (it = tmpList.rbegin(); it != tmpList.rend(); ++it ) {
    00331     if (!it->active) continue; // only act on active services
    00332     const std::string& name = it->service->name();
    00333     switch (it->service->FSMState()) {
    00334     case Gaudi::StateMachine::INITIALIZED:
    00335       DEBMSG << "Service " << name << " already stopped" << endmsg;
    00336       break;
    00337     case Gaudi::StateMachine::RUNNING:
    00338       DEBMSG << "Stopping service " << name << endmsg;
    00339       sc = it->service->sysStop();
    00340       if( !sc.isSuccess() ) {
    00341         error() << "Unable to stop Service: " << name << endmsg;
    00342         return sc;
    00343       } break;
    00344     default:
    00345       DEBMSG << "Service " << name
    00346           << " not in the correct state to be stopped ("
    00347           << it->service->FSMState() << ")" << endmsg;
    00348       return StatusCode::FAILURE;
    00349     }
    00350   }
    00351   return StatusCode::SUCCESS;
    00352 }
    00353
    00354 //------------------------------------------------------------------------------
    00355 StatusCode ServiceManager::reinitialize()
    00356 //------------------------------------------------------------------------------
    00357 {
    00358   m_listsvc.sort(); // ensure that the list is ordered by priority
    00359   // we work on a copy to avoid to operate twice on the services created on demand
    00360   // (which are already in the correct state.
    00361   ListSvc tmpList(m_listsvc);
    00362
    00363   StatusCode sc(StatusCode::SUCCESS, true);
    00364   ListSvc::iterator it;
    00365   // Re-Initialize all services
    00366   for ( it = tmpList.begin(); it != tmpList.end(); ++it ) {
    00367     if (!it->active) continue; // only act on active services
    00368     sc = it->service->sysReinitialize();
    00369     if( !sc.isSuccess() ) {
    00370       error() << "Unable to re-initialize Service: " << it->service->name() << endmsg;
    00371       return StatusCode::FAILURE;
    00372     }
    00373   }
    00374   return StatusCode::SUCCESS;
    00375 }
    00376
    00377 //------------------------------------------------------------------------------
    00378 StatusCode ServiceManager::restart()
    00379 //------------------------------------------------------------------------------
    00380 {
    00381   m_listsvc.sort(); // ensure that the list is ordered by priority
    00382   // we work on a copy to avoid to operate twice on the services created on demand
    00383   // (which are already in the correct state.
    00384   ListSvc tmpList(m_listsvc);
    00385
    00386   StatusCode sc(StatusCode::SUCCESS, true);
    00387   ListSvc::iterator it;
    00388   // Re-Start all services
    00389   for ( it = tmpList.begin(); it != tmpList.end(); ++it ) {
    00390     if (!it->active) continue; // only act on active services
    00391     sc = it->service->sysRestart();
    00392     if( !sc.isSuccess() ) {
    00393       error() << "Unable to re-start Service: " << it->service->name() << endmsg;
    00394       return StatusCode::FAILURE;
    00395     }
    00396   }
    00397   return StatusCode::SUCCESS;
    00398 }
    00399
    00400 //------------------------------------------------------------------------------
    00401 StatusCode ServiceManager::finalize()
    00402 //------------------------------------------------------------------------------
    00403 {
    00404   // make sure that HistogramDataSvc and THistSvc get finalized after the
    00405   // ToolSvc, and StatusCodeSvc after that
    00406   int pri_tool = getPriority("ToolSvc");
    00407   if (pri_tool != 0) {
    00408     setPriority("THistSvc",pri_tool-1).ignore();
    00409     setPriority("ChronoStatSvc",pri_tool-2).ignore();
    00410     setPriority("AuditorSvc",pri_tool-3).ignore();
    00411     setPriority("NTupleSvc",pri_tool-1).ignore();
    00412     setPriority("HistogramDataSvc",pri_tool-1).ignore();
    00413     // Preserve the relative ordering between HistogramDataSvc and HistogramPersistencySvc
    00414     setPriority("HistogramPersistencySvc",pri_tool-2).ignore();
    00415   }
    00416
    00417   // make sure the StatusCodeSvc gets finalized really late:
    00418   setPriority("StatusCodeSvc",-9999).ignore();
    00419
    00420   m_listsvc.sort(); // ensure that the list is ordered by priority
    00421   // we work on a copy to avoid to operate twice on the services created on demand
    00422   // (which are already in the correct state).
    00423   ListSvc tmpList(m_listsvc);
    00424
    00425   StatusCode sc(StatusCode::SUCCESS, true);
    00426   // call finalize() for all services in reverse order
    00427   ListSvc::reverse_iterator rit;
    00428   for (rit = tmpList.rbegin(); rit != tmpList.rend(); ++rit ) {
    00429     if (!rit->active) continue; // only act on active services
    00430     const std::string& name = rit->service->name();
    00431     // ignore the current state for the moment
    00432     // if( Gaudi::StateMachine::INITIALIZED == rit->service->state() ) {
    00433     DEBMSG << "Finalizing service " << name << endmsg;
    00434     if ( !(rit->service->sysFinalize()).isSuccess() ) {
    00435       warning() << "Finalization of service " << name << " failed" << endmsg;
    00436       sc = StatusCode::FAILURE;
    00437     }
    00438   }
    00439   DEBMSG << "Service reference count check:" << endmsg;
    00440   ListSvc::iterator it;
    00441   while (!tmpList.empty()) {
    00442     it = tmpList.begin();
    00443     const std::string& name = it->service->name();
    00444     const unsigned long rc = it->service->refCount() - 1; // exclude the count due to the temporary list
    00445     DEBMSG << "---- " << name
    00446            << " (refCount = " << rc << ")" << endmsg;
    00447     if (rc < 1) {
    00448       warning() << "Too low reference count for " << name
    00449                 << " (should not go below 1 at this point)" << endmsg;
    00450       it->service->addRef();
    00451     }
    00452     tmpList.pop_front();
    00453   }
    00454
    00455   // loop over all Active Services, removing them one by one.
    00456   // They should be deleted because the reference counting goes to 0.
    00457   it = m_listsvc.begin();
    00458   while (it != m_listsvc.end()) {
    00459     if (it->active) {
    00460       it = m_listsvc.erase(it);
    00461     } else {
    00462       ++it;
    00463     }
    00464   }
    00465   return sc ;
    00466 }
    00467
    00468
    00469 //------------------------------------------------------------------------------
    00470 int
    00471 ServiceManager::getPriority(const std::string& name) const {
    00472 //------------------------------------------------------------------------------
    00473   ListSvc::const_iterator it = find(name);
    00474   return (it != m_listsvc.end()) ? it->priority: 0;
    00475 }
    00476
    00477 //------------------------------------------------------------------------------
    00478 StatusCode
    00479 ServiceManager::setPriority(const std::string& name, int prio) {
    00480 //------------------------------------------------------------------------------
    00481   ListSvc::iterator it = find(name);
    00482   if (it != m_listsvc.end()) {
    00483     it->priority = prio;
    00484     return StatusCode::SUCCESS;
    00485   }
    00486   return StatusCode::FAILURE;
    00487 }
    00488
    00489 //------------------------------------------------------------------------------
    00490 // Get the value of the initialization loop check flag.
    00491 //------------------------------------------------------------------------------
    00492 bool ServiceManager::loopCheckEnabled() const {
    00493   return m_loopCheck;
    00494 }
    00495 //------------------------------------------------------------------------------
    00496 // Set the value of the initialization loop check flag.
    00497 //------------------------------------------------------------------------------
    00498 void ServiceManager::setLoopCheckEnabled(bool en) {
    00499   m_loopCheck = en;
    00500 }
    00501
    00502 DECLARE_OBJECT_FACTORY(ServiceManager)

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines