| # Gaudi Framework, version v21r7p1 |

Home |  | Generated: 15 Feb 2010

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