Gaudi Framework, version v22r1

Home   Generated: Mon Feb 28 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

Generated at Mon Feb 28 2011 18:27:18 for Gaudi Framework, version v22r1 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004