| # Gaudi Framework, version v22r2 |

Home |  | Generated: Tue May 10 2011

# ServiceManager.cpp

Go to the documentation of this file.

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

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