Gaudi Framework, version v23r4

Home   Generated: Mon Sep 17 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

Generated at Mon Sep 17 2012 13:49:28 for Gaudi Framework, version v23r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004