All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ServiceManager.cpp
Go to the documentation of this file.
1 // Include files
2 #include "ServiceManager.h"
3 #include "GaudiKernel/IService.h"
6 #include "GaudiKernel/System.h"
7 #include "GaudiKernel/Service.h"
9 #include "GaudiKernel/SmartIF.h"
12 #include "GaudiKernel/Incident.h"
13 
14 #include <iostream>
15 #include <cassert>
16 
17 #define ON_DEBUG if (msgLevel(MSG::DEBUG))
18 #define ON_VERBOSE if (msgLevel(MSG::VERBOSE))
19 
20 #define DEBMSG ON_DEBUG debug()
21 #define VERMSG ON_VERBOSE verbose()
22 
24 static SmartIF<IService> no_service;
25 
26 // constructor
28  base_class(application, IService::interfaceID()),
29  m_loopCheck(true),
30  m_appSvc(application)
31 {
32  // Set the service locator to myself
33  m_svcLocator = static_cast<ISvcLocator*>(this);
34 
35  addRef(); // Initial count set to 1
36 }
37 
38 // destructor
40  //-- inform the orphan services that I am gone....
41  for (ListSvc::iterator it = m_listsvc.begin(); it != m_listsvc.end(); it++ ) {
42  it->service->setServiceManager(0);
43  }
44 }
45 
46 //------------------------------------------------------------------------------
47 // Instantiate a service
49 //------------------------------------------------------------------------------
50 {
51  // Check if the service is already existing
52  if(existsService(typeName.name())) {
53  // return an error because a service with that name already exists
54  return no_service;
55  }
56 
59  rc.setChecked(); //hack to avoid going into infinite recursion on ~StatusCode
60 
61  const std::string &name = typeName.name();
62  std::string type = typeName.type();
63  if (!typeName.haveType()) { // the type is not explicit
64  // see we have some specific type mapping for the name
65  MapType::iterator it = m_maptype.find(typeName.name());
66  if( it != m_maptype.end() ) {
67  type = (*it).second; // use the declared type
68  }
69  }
70 
72  std::string::size_type ip;
73  if ( (ip = type.find("__")) != std::string::npos) {
74  type.erase(ip,type.length());
75  }
76 
77  IService* service = Service::Factory::create(type, name, static_cast<ISvcLocator*>(this)); // serviceLocator().get());
78 
79  if ( service ) {
80  m_listsvc.push_back(service);
81  // Check the compatibility of the version of the interface obtained
82  if( !isValidInterface(service) ) {
83  fatal() << "Incompatible interface IService version for " << type << endmsg;
84  return no_service;
85  }
86  service->setServiceManager(this);
87  return m_listsvc.back().service;
88  }
89  fatal() << "No Service factory for " << type << " available." << endmsg;
90  return no_service;
91 }
92 
93 //------------------------------------------------------------------------------
94 // add a service to the managed list
96 //------------------------------------------------------------------------------
97 {
98  ListSvc::iterator it = find(svc);
99  if (it != m_listsvc.end()) {
100  it->priority = prio; // if the service is already known, it is equivalent to a setPriority
101  it->active = true; // and make it active
102  } else {
103  m_listsvc.push_back(ServiceItem(svc,prio,true));
104  }
105  return StatusCode::SUCCESS;
106 }
107 
108 //------------------------------------------------------------------------------
109 // add the service with the give type and name to the active list
111 //------------------------------------------------------------------------------
112 {
113  ListSvc::iterator it = find(typeName.name()); // try to find the service by name
114  if (it == m_listsvc.end()) { // not found
115  // If the service does not exist, we create it
116  SmartIF<IService> &svc = createService(typeName);
117  if (svc.isValid()) {
118  it = find(svc.get()); // now it is in the list because createService added it
119  it->priority = prio;
122  sc = svc->sysInitialize();
124  sc = svc->sysStart();
125  }
126  }
127  if(sc.isFailure()) { // if initialization failed, remove it from the list
128  error() << "Unable to initialize service \"" << typeName.name() << "\""
129  << endmsg;
130  m_listsvc.erase(it);
131  // Note: removing it from the list + the SmartIF going out of scope should trigger the delete
132  // delete svc.get();
133  return sc;
134  } else { // initialization successful, we can work with the service
135  // Move the just initialized service to the back of the list
136  // (we care more about order of initialization than of creation)
137  m_listsvc.push_back(*it);
138  m_listsvc.erase(it);
139  it = --m_listsvc.end(); // last entry (the iterator was invalidated by erase)
140  }
141  } else {
142  return StatusCode::FAILURE;
143  }
144  } else {
145  // if the service is already known, it is equivalent to a setPriority
146  it->priority = prio;
147  }
148  // 'it' is defined because either we found the service or we created it
149  // Now we can activate the service
150  it->active = true; // and make it active
151  return StatusCode(StatusCode::SUCCESS, true);
152 }
153 
154 //------------------------------------------------------------------------------
155 // Returns a smart pointer to a service.
157  const std::string &name = typeName.name();
158 
159  // Acquire the RAII lock to avoid simultaneous attempts from different threads to initialize a service
160  boost::lock_guard<boost::recursive_mutex> lck(m_svcinitmutex);
161 
162  ListSvc::iterator it = find(name);
163 
164  if (it != m_listsvc.end()) {
165  if (m_loopCheck &&
166  (createIf && it->service->FSMState() == Gaudi::StateMachine::CONFIGURED)) {
167  error()
168  << "Initialization loop detected when creating service \"" << name
169  << "\""
170  << endmsg;
171  return no_service;
172  }
173  return it->service;
174  } else {
175  // Service not found. The user may be interested in one of the interfaces
176  // of the application manager itself
177  if( name == "ApplicationMgr" ||
178  name == "APPMGR" ||
179  name == "" ) {
180  return m_appSvc;
181  } else if ( createIf ){
182  //last resort: we try to create the service
183  if (addService(typeName).isSuccess()){
184  return find(name)->service;
185  }
186  }
187  }
188  return no_service;
189 }
190 
191 //------------------------------------------------------------------------------
192 const std::list<IService*>& ServiceManager::getServices( ) const
193 //------------------------------------------------------------------------------
194 {
195  m_listOfPtrs.clear();
196  for (ListSvc::const_iterator it = m_listsvc.begin(); it != m_listsvc.end(); ++it) {
197  m_listOfPtrs.push_back(const_cast<IService*>(it->service.get()));
198  }
199  return m_listOfPtrs;
200 }
201 
202 //------------------------------------------------------------------------------
203 bool ServiceManager::existsService( const std::string& name) const
204 //------------------------------------------------------------------------------
205 {
206  return find(name) != m_listsvc.end();
207 }
208 
209 //------------------------------------------------------------------------------
211 //------------------------------------------------------------------------------
212 {
213  ListSvc::iterator it = find(svc);
214  if (it != m_listsvc.end()) {
215  m_listsvc.erase(it);
216  return StatusCode(StatusCode::SUCCESS,true);
217  }
218  return StatusCode(StatusCode::FAILURE,true);
219 }
220 
221 //------------------------------------------------------------------------------
223 //------------------------------------------------------------------------------
224 {
225  ListSvc::iterator it = find(name);
226  if (it != m_listsvc.end()) {
227  m_listsvc.erase(it);
228  return StatusCode::SUCCESS;
229  }
230  return StatusCode::FAILURE;
231 }
232 
233 //------------------------------------------------------------------------------
234 StatusCode ServiceManager::declareSvcType( const std::string& svcname,
235  const std::string& svctype )
236 //------------------------------------------------------------------------------
237 {
238  std::pair<MapType::iterator, bool> p = m_maptype.insert(std::make_pair(svcname, svctype));
239  if( p.second == false) {
240  m_maptype.erase ( p.first );
241  p = m_maptype.insert(std::make_pair(svcname, svctype) );
242  if( p.second == false) return StatusCode::FAILURE;
243  }
244  return StatusCode::SUCCESS;
245 }
246 
247 //------------------------------------------------------------------------------
249 //------------------------------------------------------------------------------
250 {
251  m_listsvc.sort(); // ensure that the list is ordered by priority
252  // we work on a copy to avoid to operate twice on the services created on demand
253  // (which are already in the correct state.
254  ListSvc tmpList(m_listsvc);
255 
257  // call initialize() for all services
258  for (ListSvc::iterator it = tmpList.begin(); it != tmpList.end(); ++it ) {
259  if (!it->active) continue; // only act on active services
260  const std::string& name = it->service->name();
261  switch (it->service->FSMState()) {
263  DEBMSG << "Service " << name << " already initialized" << endmsg;
264  break;
266  DEBMSG << "Initializing service " << name << endmsg;
267  sc = it->service->sysInitialize();
268  if( !sc.isSuccess() ) {
269  error() << "Unable to initialize Service: " << name << endmsg;
270  return sc;
271  } break;
272  default:
273  error() << "Service " << name
274  << " not in the correct state to be initialized ("
275  << it->service->FSMState() << ")" << endmsg;
276  return StatusCode::FAILURE;
277  }
278  }
279  return StatusCode::SUCCESS;
280 }
281 
282 //------------------------------------------------------------------------------
284 //------------------------------------------------------------------------------
285 {
286  m_listsvc.sort(); // ensure that the list is ordered by priority
287  // we work on a copy to avoid to operate twice on the services created on demand
288  // (which are already in the correct state.
289  ListSvc tmpList(m_listsvc);
290 
292  // call initialize() for all services
293  for (ListSvc::iterator it = tmpList.begin(); it != tmpList.end(); ++it ) {
294  if (!it->active) continue; // only act on active services
295  const std::string& name = it->service->name();
296  switch (it->service->FSMState()) {
298  DEBMSG << "Service " << name
299  << " already started" << endmsg;
300  break;
302  DEBMSG << "Starting service " << name << endmsg;
303  sc = it->service->sysStart();
304  if( !sc.isSuccess() ) {
305  error() << "Unable to start Service: " << name << endmsg;
306  return sc;
307  } break;
308  default:
309  error() << "Service " << name
310  << " not in the correct state to be started ("
311  << it->service->FSMState() << ")" << endmsg;
312  return StatusCode::FAILURE;
313  }
314  }
315  return StatusCode::SUCCESS;
316 }
317 
318 
319 //------------------------------------------------------------------------------
321 //------------------------------------------------------------------------------
322 {
323  m_listsvc.sort(); // ensure that the list is ordered by priority
324  // we work on a copy to avoid to operate twice on the services created on demand
325  // (which are already in the correct state.
326  ListSvc tmpList(m_listsvc);
327 
329  ListSvc::reverse_iterator it;
330  // call stop() for all services
331  for (it = tmpList.rbegin(); it != tmpList.rend(); ++it ) {
332  if (!it->active) continue; // only act on active services
333  const std::string& name = it->service->name();
334  switch (it->service->FSMState()) {
336  DEBMSG << "Service " << name << " already stopped" << endmsg;
337  break;
339  DEBMSG << "Stopping service " << name << endmsg;
340  sc = it->service->sysStop();
341  if( !sc.isSuccess() ) {
342  error() << "Unable to stop Service: " << name << endmsg;
343  return sc;
344  } break;
345  default:
346  DEBMSG << "Service " << name
347  << " not in the correct state to be stopped ("
348  << it->service->FSMState() << ")" << endmsg;
349  return StatusCode::FAILURE;
350  }
351  }
352  return StatusCode::SUCCESS;
353 }
354 
355 //------------------------------------------------------------------------------
357 //------------------------------------------------------------------------------
358 {
359  m_listsvc.sort(); // ensure that the list is ordered by priority
360  // we work on a copy to avoid to operate twice on the services created on demand
361  // (which are already in the correct state.
362  ListSvc tmpList(m_listsvc);
363 
365  ListSvc::iterator it;
366  // Re-Initialize all services
367  for ( it = tmpList.begin(); it != tmpList.end(); ++it ) {
368  if (!it->active) continue; // only act on active services
369  sc = it->service->sysReinitialize();
370  if( !sc.isSuccess() ) {
371  error() << "Unable to re-initialize Service: " << it->service->name() << endmsg;
372  return StatusCode::FAILURE;
373  }
374  }
375  return StatusCode::SUCCESS;
376 }
377 
378 //------------------------------------------------------------------------------
380 //------------------------------------------------------------------------------
381 {
382  m_listsvc.sort(); // ensure that the list is ordered by priority
383  // we work on a copy to avoid to operate twice on the services created on demand
384  // (which are already in the correct state.
385  ListSvc tmpList(m_listsvc);
386 
388  ListSvc::iterator it;
389  // Re-Start all services
390  for ( it = tmpList.begin(); it != tmpList.end(); ++it ) {
391  if (!it->active) continue; // only act on active services
392  sc = it->service->sysRestart();
393  if( !sc.isSuccess() ) {
394  error() << "Unable to re-start Service: " << it->service->name() << endmsg;
395  return StatusCode::FAILURE;
396  }
397  }
398  return StatusCode::SUCCESS;
399 }
400 
401 //------------------------------------------------------------------------------
403 //------------------------------------------------------------------------------
404 {
405  // make sure that HistogramDataSvc and THistSvc get finalized after the
406  // ToolSvc, and the FileMgr and StatusCodeSvc after that
407  int pri_tool = getPriority("ToolSvc");
408  if (pri_tool != 0) {
409  setPriority("THistSvc",pri_tool-10).ignore();
410  setPriority("ChronoStatSvc",pri_tool-20).ignore();
411  setPriority("AuditorSvc",pri_tool-30).ignore();
412  setPriority("NTupleSvc",pri_tool-10).ignore();
413  setPriority("HistogramDataSvc",pri_tool-10).ignore();
414  // Preserve the relative ordering between HistogramDataSvc and HistogramPersistencySvc
415  setPriority("HistogramPersistencySvc",pri_tool-20).ignore();
416  setPriority("HistorySvc",pri_tool-30).ignore();
417  setPriority("FileMgr",pri_tool-40).ignore();
418  }
419 
420 
421  // get list of PostFinalize clients
422  std::vector<IIncidentListener*> postFinList;
423  {
424  SmartIF<IIncidentSvc> p_inc(service("IncidentSvc",false));
425  if (p_inc.isValid()) {
426  p_inc->getListeners(postFinList,IncidentType::SvcPostFinalize);
427  }
428  }
429 
430  // make sure the StatusCodeSvc gets finalized really late:
431  setPriority("StatusCodeSvc",-9999).ignore();
432 
433  m_listsvc.sort(); // ensure that the list is ordered by priority
434  // dump();
435 
437  {
438  // we work on a copy to avoid to operate twice on the services created on demand
439  // (which are already in the correct state).
440  ListSvc tmpList(m_listsvc);
441 
442  // call finalize() for all services in reverse order
443  ListSvc::reverse_iterator rit;
444  for (rit = tmpList.rbegin(); rit != tmpList.rend(); ++rit ) {
445  if (!rit->active) continue; // only act on active services
446  const std::string& name = rit->service->name();
447  // ignore the current state for the moment
448  // if( Gaudi::StateMachine::INITIALIZED == rit->service->state() ) {
449  DEBMSG << "Finalizing service " << name << endmsg;
450  if ( !(rit->service->sysFinalize()).isSuccess() ) {
451  warning() << "Finalization of service " << name << " failed" << endmsg;
452  sc = StatusCode::FAILURE;
453  }
454  }
455  }
456 
457  // call SvcPostFinalize on all clients
458  if (!postFinList.empty()) {
459  DEBMSG << "Will call SvcPostFinalize for " << postFinList.size() << " clients"
460  << endmsg;
461  Incident inc("ServiceManager", IncidentType::SvcPostFinalize);
462  std::vector<IIncidentListener*>::iterator itr;
463  for (itr = postFinList.begin(); itr != postFinList.end(); ++itr) {
464  (*itr)->handle(inc);
465  }
466  }
467 
468  // loop over all Active Services, removing them one by one.
469  // They should be deleted because the reference counting goes to 0.
470  DEBMSG << "Looping over all active services..." << endmsg;
471  ListSvc::iterator it = m_listsvc.begin();
472  while (it != m_listsvc.end()) {
473  DEBMSG << "---- " << it->service->name()
474  << " (refCount = " << it->service->refCount() << ")"
475  << endmsg;
476  if (it->service->refCount() < 1) {
477  warning() << "Too low reference count for " << it->service->name()
478  << " (should not go below 1 at this point)" << endmsg;
479  it->service->addRef();
480  }
481  if (it->active) {
482  it = m_listsvc.erase(it);
483  } else {
484  ++it;
485  }
486  }
487 
488  return sc;
489 }
490 
491 
492 //------------------------------------------------------------------------------
493 int
494 ServiceManager::getPriority(const std::string& name) const {
495 //------------------------------------------------------------------------------
496  ListSvc::const_iterator it = find(name);
497  return (it != m_listsvc.end()) ? it->priority: 0;
498 }
499 
500 //------------------------------------------------------------------------------
502 ServiceManager::setPriority(const std::string& name, int prio) {
503 //------------------------------------------------------------------------------
504  ListSvc::iterator it = find(name);
505  if (it != m_listsvc.end()) {
506  it->priority = prio;
507  return StatusCode::SUCCESS;
508  }
509  return StatusCode::FAILURE;
510 }
511 
512 //------------------------------------------------------------------------------
513 // Get the value of the initialization loop check flag.
514 //------------------------------------------------------------------------------
516  return m_loopCheck;
517 }
518 //------------------------------------------------------------------------------
519 // Set the value of the initialization loop check flag.
520 //------------------------------------------------------------------------------
522  m_loopCheck = en;
523 }
524 
525 
526 //------------------------------------------------------------------------------
527 // Dump out contents of service list
528 //------------------------------------------------------------------------------
529 void ServiceManager::dump() const {
530 
531  MsgStream log(msgSvc(),name());
532 
533  log << MSG::INFO << "\n"
534  << "===================== listing all services ===================\n"
535  << " prior ref name active\n";
536 
537  ListSvc::const_iterator it;
538  for (it=m_listsvc.begin(); it != m_listsvc.end(); ++it) {
539 
540  log.width(6);
541  log.flags(std::ios_base::right);
542  log << it->priority << " ";
543  log.width(5);
544  log << it->service->refCount() << " ";
545  log.width(30);
546  log.flags(std::ios_base::left);
547  log << it->service->name() << " ";
548  log.width(2);
549  log << it->active << std::endl;
550 
551  }
552 
553  log << "=================================================================\n";
554  log << endmsg;
555 
556 }
557 
558 
The ServiceManager class is in charge of the creation of concrete instances of Services.
std::list< IService * > m_listOfPtrs
List of pointers to the know services used to implement getServices()
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
SmartIF< IService > m_appSvc
Pointer to the application IService interface.
virtual Gaudi::StateMachine::State targetFSMState() const
When we are in the middle of a transition, get the state where the transition is leading us...
virtual StatusCode stop()
Stop (from RUNNING to INITIALIZED).
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:26
const std::string & name() const
Return the name of the manager (implementation of INamedInterface)
SmartIF< IMessageSvc > & msgSvc() const
The standard message service.
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:75
SmartIF< ISvcLocator > m_svcLocator
Service locator (needed to access the MessageSvc)
bool m_loopCheck
Check for service initialization loops.
virtual int getPriority(const std::string &name) const
manage priorities of services
ServiceManager(IInterface *application)
default creator
virtual const std::list< IService * > & getServices() const
Return the list of Services.
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
virtual StatusCode reinitialize()
Initialization (from INITIALIZED or RUNNING to INITIALIZED, via CONFIGURED).
bool isValidInterface(I *i)
Templated function that throws an exception if the version if the interface implemented by the object...
Definition: IInterface.h:257
const std::string SvcPostFinalize
ONLY For Services that need something after they've been finalized.
Definition: Incident.h:91
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:85
MapType m_maptype
Map of service name and service type.
void erase(iterator pos)
Definition: Map.h:173
std::pair< iterator, bool > insert(const value_type &val)
Definition: Map.h:165
iterator end()
Definition: Map.h:131
Helper class to parse a string of format "type/name".
Definition: TypeNameString.h:9
string type
Definition: gaudirun.py:126
bool isValid() const
Allow for check if smart pointer is valid.
Definition: SmartIF.h:51
void dump() const
virtual SmartIF< IService > & createService(const Gaudi::Utils::TypeNameString &nametype)
implementation of ISvcManager::createService
General service interface definition.
Definition: IService.h:19
virtual StatusCode addService(IService *svc, int prio=DEFAULT_SVC_PRIORITY)
implementation of ISvcManager::addService
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:30
Definition of the basic interface.
Definition: IInterface.h:160
virtual StatusCode initialize()
Initialization (from CONFIGURED to INITIALIZED).
virtual StatusCode setPriority(const std::string &name, int pri)
virtual void setLoopCheckEnabled(bool en)
Set the value of the initialization loop check flag.
#define DECLARE_OBJECT_FACTORY(x)
Definition: ObjectFactory.h:17
iterator find(const key_type &key)
Definition: Map.h:148
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:62
virtual StatusCode finalize()
Finalize (from INITIALIZED to CONFIGURED).
tuple rc
Definition: IOTest.py:92
virtual bool existsService(const std::string &name) const
implementation of ISvcLocation::existsService
virtual StatusCode declareSvcType(const std::string &svcname, const std::string &svctype)
implementation of ISvcManager::declareSvcType
virtual StatusCode removeService(IService *svc)
implementation of ISvcManager::removeService
long flags() const
IOS emulation.
Definition: MsgStream.h:177
virtual ~ServiceManager()
virtual destructor
const std::string & type() const
Base class for all Incidents (computing events).
Definition: Incident.h:16
int width() const
Definition: MsgStream.h:186
Templated class to add the standard messaging functionalities.
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
ListSvc::iterator find(const std::string &name)
virtual SmartIF< IService > & service(const Gaudi::Utils::TypeNameString &typeName, const bool createIf=true)
Returns a smart pointer to a service.
#define DEBMSG
const std::string & name() const
void ignore() const
Definition: StatusCode.h:107
virtual bool loopCheckEnabled() const
Get the value of the initialization loop check flag.
boost::recursive_mutex m_svcinitmutex
Mutex to synchronize shared service initialization between threads.
virtual StatusCode restart()
Initialization (from RUNNING to RUNNING, via INITIALIZED).
std::string typeName(const std::type_info &typ)
Definition: Dictionary.cpp:22
std::list< ServiceItem > ListSvc
ListSvc m_listsvc
List of service maintained by ServiceManager.
virtual void setServiceManager(ISvcManager *)=0
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
virtual StatusCode start()
Start (from INITIALIZED to RUNNING).
void setChecked() const
Ignore the checking code;.
Definition: StatusCode.h:104