Gaudi Framework, version v22r0

Home   Generated: 9 Feb 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 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   // call finalize() for all services in reverse order
00420   ListSvc::reverse_iterator rit;
00421   for (rit = tmpList.rbegin(); rit != tmpList.rend(); ++rit ) {
00422     if (!rit->active) continue; // only act on active services
00423     const std::string& name = rit->service->name();
00424     // ignore the current state for the moment
00425     // if( Gaudi::StateMachine::INITIALIZED == rit->service->state() ) {
00426     debug() << "Finalizing service " << name << endmsg;
00427     if ( !(rit->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   ListSvc::iterator it;
00434   while (!tmpList.empty()) {
00435     it = tmpList.begin();
00436     const std::string& name = it->service->name(); 
00437     const unsigned long rc = it->service->refCount() - 1; // exclude the count due to the temporary list
00438     debug() << "---- " << name
00439             << " (refCount = " << rc << ")" << endmsg;
00440     if (rc < 1) {
00441       warning() << "Too low reference count for " << name
00442                 << " (should not go below 1 at this point)" << endmsg;
00443       it->service->addRef();
00444     }
00445     tmpList.pop_front();
00446   }
00447 
00448   // loop over all Active Services, removing them one by one.
00449   // They should be deleted because the reference counting goes to 0.
00450   it = m_listsvc.begin();
00451   while (it != m_listsvc.end()) {
00452     if (it->active) {
00453       it = m_listsvc.erase(it);
00454     } else {
00455       ++it;
00456     }
00457   }
00458   return sc ;
00459 }
00460 
00461 
00462 //------------------------------------------------------------------------------
00463 int
00464 ServiceManager::getPriority(const std::string& name) const {
00465 //------------------------------------------------------------------------------
00466   ListSvc::const_iterator it = find(name);
00467   return (it != m_listsvc.end()) ? it->priority: 0;
00468 }
00469 
00470 //------------------------------------------------------------------------------
00471 StatusCode
00472 ServiceManager::setPriority(const std::string& name, int prio) {
00473 //------------------------------------------------------------------------------
00474   ListSvc::iterator it = find(name);
00475   if (it != m_listsvc.end()) {
00476     it->priority = prio;
00477     return StatusCode::SUCCESS;
00478   }
00479   return StatusCode::FAILURE;
00480 }
00481 
00482 //------------------------------------------------------------------------------
00483 // Get the value of the initialization loop check flag.
00484 //------------------------------------------------------------------------------
00485 bool ServiceManager::loopCheckEnabled() const {
00486   return m_loopCheck;
00487 }
00488 //------------------------------------------------------------------------------
00489 // Set the value of the initialization loop check flag.
00490 //------------------------------------------------------------------------------
00491 void ServiceManager::setLoopCheckEnabled(bool en) {
00492   m_loopCheck = en;
00493 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Wed Feb 9 16:25:00 2011 for Gaudi Framework, version v22r0 by Doxygen version 1.6.2 written by Dimitri van Heesch, © 1997-2004