Gaudi Framework, version v22r4

Home   Generated: Fri Sep 2 2011

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   ListSvc::iterator it = find(name);
00158 
00159   if (it !=  m_listsvc.end()) {
00160     if (m_loopCheck &&
00161         (createIf && it->service->FSMState() == Gaudi::StateMachine::CONFIGURED)) {
00162       error()
00163           << "Initialization loop detected when creating service \"" << name
00164           << "\""
00165           << endmsg;
00166       return no_service;
00167     }
00168     return it->service;
00169   } else {
00170     // Service not found. The user may be interested in one of the interfaces
00171     // of the application manager itself
00172     if( name == "ApplicationMgr" ||
00173         name == "APPMGR" ||
00174         name == "" ) {
00175       return m_appSvc;
00176     } else if ( createIf ){
00177       //last resort: we try to create the service
00178       if (addService(typeName).isSuccess()){
00179         return find(name)->service;
00180       }
00181     }
00182   }
00183   return no_service;
00184 }
00185 
00186 //------------------------------------------------------------------------------
00187 const std::list<IService*>& ServiceManager::getServices( ) const
00188 //------------------------------------------------------------------------------
00189 {
00190   m_listOfPtrs.clear();
00191   for (ListSvc::const_iterator it = m_listsvc.begin(); it != m_listsvc.end(); ++it) {
00192     m_listOfPtrs.push_back(const_cast<IService*>(it->service.get()));
00193   }
00194   return m_listOfPtrs;
00195 }
00196 
00197 //------------------------------------------------------------------------------
00198 bool ServiceManager::existsService( const std::string& name) const
00199 //------------------------------------------------------------------------------
00200 {
00201   return find(name) != m_listsvc.end();
00202 }
00203 
00204 //------------------------------------------------------------------------------
00205 StatusCode ServiceManager::removeService(IService* svc)
00206 //------------------------------------------------------------------------------
00207 {
00208   ListSvc::iterator it = find(svc);
00209   if (it != m_listsvc.end()) {
00210     m_listsvc.erase(it);
00211     return StatusCode(StatusCode::SUCCESS,true);
00212   }
00213   return StatusCode(StatusCode::FAILURE,true);
00214 }
00215 
00216 //------------------------------------------------------------------------------
00217 StatusCode ServiceManager::removeService(const std::string& name)
00218 //------------------------------------------------------------------------------
00219 {
00220   ListSvc::iterator it = find(name);
00221   if (it != m_listsvc.end()) {
00222     m_listsvc.erase(it);
00223     return StatusCode::SUCCESS;
00224   }
00225   return StatusCode::FAILURE;
00226 }
00227 
00228 //------------------------------------------------------------------------------
00229 StatusCode ServiceManager::declareSvcType( const std::string& svcname,
00230                                            const std::string& svctype )
00231 //------------------------------------------------------------------------------
00232 {
00233   std::pair<MapType::iterator, bool> p = m_maptype.insert(std::make_pair(svcname, svctype));
00234   if( p.second == false) {
00235     m_maptype.erase ( p.first );
00236     p = m_maptype.insert(std::make_pair(svcname, svctype) );
00237     if( p.second == false) return StatusCode::FAILURE;
00238   }
00239   return StatusCode::SUCCESS;
00240 }
00241 
00242 //------------------------------------------------------------------------------
00243 StatusCode ServiceManager::initialize()
00244 //------------------------------------------------------------------------------
00245 {
00246   m_listsvc.sort(); // ensure that the list is ordered by priority
00247   // we work on a copy to avoid to operate twice on the services created on demand
00248   // (which are already in the correct state.
00249   ListSvc tmpList(m_listsvc);
00250 
00251   StatusCode sc(StatusCode::SUCCESS, true);
00252   // call initialize() for all services
00253   for (ListSvc::iterator it = tmpList.begin(); it != tmpList.end(); ++it ) {
00254     if (!it->active) continue; // only act on active services
00255     const std::string& name = it->service->name();
00256     switch (it->service->FSMState()) {
00257     case Gaudi::StateMachine::INITIALIZED:
00258       DEBMSG << "Service " << name << " already initialized" << endmsg;
00259       break;
00260     case Gaudi::StateMachine::OFFLINE:
00261       DEBMSG << "Initializing service " << name << endmsg;
00262       sc = it->service->sysInitialize();
00263       if( !sc.isSuccess() ) {
00264         error() << "Unable to initialize Service: " << name << endmsg;
00265         return sc;
00266       } break;
00267     default:
00268       error() << "Service " << name
00269           << " not in the correct state to be initialized ("
00270           << it->service->FSMState() << ")" << endmsg;
00271       return StatusCode::FAILURE;
00272     }
00273   }
00274   return StatusCode::SUCCESS;
00275 }
00276 
00277 //------------------------------------------------------------------------------
00278 StatusCode ServiceManager::start()
00279 //------------------------------------------------------------------------------
00280 {
00281   m_listsvc.sort(); // ensure that the list is ordered by priority
00282   // we work on a copy to avoid to operate twice on the services created on demand
00283   // (which are already in the correct state.
00284   ListSvc tmpList(m_listsvc);
00285 
00286   StatusCode sc(StatusCode::SUCCESS, true);
00287   // call initialize() for all services
00288   for (ListSvc::iterator it = tmpList.begin(); it != tmpList.end(); ++it ) {
00289     if (!it->active) continue; // only act on active services
00290     const std::string& name = it->service->name();
00291     switch (it->service->FSMState()) {
00292     case Gaudi::StateMachine::RUNNING:
00293       DEBMSG << "Service " << name
00294           << " already started" << endmsg;
00295       break;
00296     case Gaudi::StateMachine::INITIALIZED:
00297       DEBMSG << "Starting service " << name << endmsg;
00298       sc = it->service->sysStart();
00299       if( !sc.isSuccess() ) {
00300         error() << "Unable to start Service: " << name << endmsg;
00301         return sc;
00302       } break;
00303     default:
00304       error() << "Service " << name
00305           << " not in the correct state to be started ("
00306           << it->service->FSMState() << ")" << endmsg;
00307       return StatusCode::FAILURE;
00308     }
00309   }
00310   return StatusCode::SUCCESS;
00311 }
00312 
00313 
00314 //------------------------------------------------------------------------------
00315 StatusCode ServiceManager::stop()
00316 //------------------------------------------------------------------------------
00317 {
00318   m_listsvc.sort(); // ensure that the list is ordered by priority
00319   // we work on a copy to avoid to operate twice on the services created on demand
00320   // (which are already in the correct state.
00321   ListSvc tmpList(m_listsvc);
00322 
00323   StatusCode sc(StatusCode::SUCCESS, true);
00324   ListSvc::reverse_iterator it;
00325   // call stop() for all services
00326   for (it = tmpList.rbegin(); it != tmpList.rend(); ++it ) {
00327     if (!it->active) continue; // only act on active services
00328     const std::string& name = it->service->name();
00329     switch (it->service->FSMState()) {
00330     case Gaudi::StateMachine::INITIALIZED:
00331       DEBMSG << "Service " << name << " already stopped" << endmsg;
00332       break;
00333     case Gaudi::StateMachine::RUNNING:
00334       DEBMSG << "Stopping service " << name << endmsg;
00335       sc = it->service->sysStop();
00336       if( !sc.isSuccess() ) {
00337         error() << "Unable to stop Service: " << name << endmsg;
00338         return sc;
00339       } break;
00340     default:
00341       DEBMSG << "Service " << name
00342           << " not in the correct state to be stopped ("
00343           << it->service->FSMState() << ")" << endmsg;
00344       return StatusCode::FAILURE;
00345     }
00346   }
00347   return StatusCode::SUCCESS;
00348 }
00349 
00350 //------------------------------------------------------------------------------
00351 StatusCode ServiceManager::reinitialize()
00352 //------------------------------------------------------------------------------
00353 {
00354   m_listsvc.sort(); // ensure that the list is ordered by priority
00355   // we work on a copy to avoid to operate twice on the services created on demand
00356   // (which are already in the correct state.
00357   ListSvc tmpList(m_listsvc);
00358 
00359   StatusCode sc(StatusCode::SUCCESS, true);
00360   ListSvc::iterator it;
00361   // Re-Initialize all services
00362   for ( it = tmpList.begin(); it != tmpList.end(); ++it ) {
00363     if (!it->active) continue; // only act on active services
00364     sc = it->service->sysReinitialize();
00365     if( !sc.isSuccess() ) {
00366       error() << "Unable to re-initialize Service: " << it->service->name() << endmsg;
00367       return StatusCode::FAILURE;
00368     }
00369   }
00370   return StatusCode::SUCCESS;
00371 }
00372 
00373 //------------------------------------------------------------------------------
00374 StatusCode ServiceManager::restart()
00375 //------------------------------------------------------------------------------
00376 {
00377   m_listsvc.sort(); // ensure that the list is ordered by priority
00378   // we work on a copy to avoid to operate twice on the services created on demand
00379   // (which are already in the correct state.
00380   ListSvc tmpList(m_listsvc);
00381 
00382   StatusCode sc(StatusCode::SUCCESS, true);
00383   ListSvc::iterator it;
00384   // Re-Start all services
00385   for ( it = tmpList.begin(); it != tmpList.end(); ++it ) {
00386     if (!it->active) continue; // only act on active services
00387     sc = it->service->sysRestart();
00388     if( !sc.isSuccess() ) {
00389       error() << "Unable to re-start Service: " << it->service->name() << endmsg;
00390       return StatusCode::FAILURE;
00391     }
00392   }
00393   return StatusCode::SUCCESS;
00394 }
00395 
00396 //------------------------------------------------------------------------------
00397 StatusCode ServiceManager::finalize()
00398 //------------------------------------------------------------------------------
00399 {
00400   // make sure that HistogramDataSvc and THistSvc get finalized after the
00401   // ToolSvc, and StatusCodeSvc after that
00402   int pri_tool = getPriority("ToolSvc");
00403   if (pri_tool != 0) {
00404     setPriority("THistSvc",pri_tool-1).ignore();
00405     setPriority("ChronoStatSvc",pri_tool-2).ignore();
00406     setPriority("AuditorSvc",pri_tool-3).ignore();
00407     setPriority("NTupleSvc",pri_tool-1).ignore();
00408     setPriority("HistogramDataSvc",pri_tool-1).ignore();
00409     // Preserve the relative ordering between HistogramDataSvc and HistogramPersistencySvc
00410     setPriority("HistogramPersistencySvc",pri_tool-2).ignore();
00411   }
00412 
00413   // make sure the StatusCodeSvc gets finalized really late:
00414   setPriority("StatusCodeSvc",-9999).ignore();
00415 
00416   m_listsvc.sort(); // ensure that the list is ordered by priority
00417   // we work on a copy to avoid to operate twice on the services created on demand
00418   // (which are already in the correct state).
00419   ListSvc tmpList(m_listsvc);
00420 
00421   StatusCode sc(StatusCode::SUCCESS, true);
00422   // call finalize() for all services in reverse order
00423   ListSvc::reverse_iterator rit;
00424   for (rit = tmpList.rbegin(); rit != tmpList.rend(); ++rit ) {
00425     if (!rit->active) continue; // only act on active services
00426     const std::string& name = rit->service->name();
00427     // ignore the current state for the moment
00428     // if( Gaudi::StateMachine::INITIALIZED == rit->service->state() ) {
00429     DEBMSG << "Finalizing service " << name << endmsg;
00430     if ( !(rit->service->sysFinalize()).isSuccess() ) {
00431       warning() << "Finalization of service " << name << " failed" << endmsg;
00432       sc = StatusCode::FAILURE;
00433     }
00434   }
00435   DEBMSG << "Service reference count check:" << endmsg;
00436   ListSvc::iterator it;
00437   while (!tmpList.empty()) {
00438     it = tmpList.begin();
00439     const std::string& name = it->service->name();
00440     const unsigned long rc = it->service->refCount() - 1; // exclude the count due to the temporary list
00441     DEBMSG << "---- " << name
00442            << " (refCount = " << rc << ")" << endmsg;
00443     if (rc < 1) {
00444       warning() << "Too low reference count for " << name
00445                 << " (should not go below 1 at this point)" << endmsg;
00446       it->service->addRef();
00447     }
00448     tmpList.pop_front();
00449   }
00450 
00451   // loop over all Active Services, removing them one by one.
00452   // They should be deleted because the reference counting goes to 0.
00453   it = m_listsvc.begin();
00454   while (it != m_listsvc.end()) {
00455     if (it->active) {
00456       it = m_listsvc.erase(it);
00457     } else {
00458       ++it;
00459     }
00460   }
00461   return sc ;
00462 }
00463 
00464 
00465 //------------------------------------------------------------------------------
00466 int
00467 ServiceManager::getPriority(const std::string& name) const {
00468 //------------------------------------------------------------------------------
00469   ListSvc::const_iterator it = find(name);
00470   return (it != m_listsvc.end()) ? it->priority: 0;
00471 }
00472 
00473 //------------------------------------------------------------------------------
00474 StatusCode
00475 ServiceManager::setPriority(const std::string& name, int prio) {
00476 //------------------------------------------------------------------------------
00477   ListSvc::iterator it = find(name);
00478   if (it != m_listsvc.end()) {
00479     it->priority = prio;
00480     return StatusCode::SUCCESS;
00481   }
00482   return StatusCode::FAILURE;
00483 }
00484 
00485 //------------------------------------------------------------------------------
00486 // Get the value of the initialization loop check flag.
00487 //------------------------------------------------------------------------------
00488 bool ServiceManager::loopCheckEnabled() const {
00489   return m_loopCheck;
00490 }
00491 //------------------------------------------------------------------------------
00492 // Set the value of the initialization loop check flag.
00493 //------------------------------------------------------------------------------
00494 void ServiceManager::setLoopCheckEnabled(bool en) {
00495   m_loopCheck = en;
00496 }
00497 
00498 DECLARE_OBJECT_FACTORY(ServiceManager)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Fri Sep 2 2011 16:24:52 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004