Gaudi Framework, version v23r5

Home   Generated: Wed Nov 28 2012
 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"
7 #include "GaudiKernel/System.h"
8 #include "GaudiKernel/Service.h"
10 
11 #include <iostream>
12 #include <cassert>
13 
14 #define ON_DEBUG if (msgLevel(MSG::DEBUG))
15 #define ON_VERBOSE if (msgLevel(MSG::VERBOSE))
16 
17 #define DEBMSG ON_DEBUG debug()
18 #define VERMSG ON_VERBOSE verbose()
19 
20 using ROOT::Reflex::PluginService;
21 
24 
25 // constructor
27  base_class(application, IService::interfaceID()),
28  m_loopCheck(true),
29  m_appSvc(application)
30 {
31  // Set the service locator to myself
32  m_svcLocator = static_cast<ISvcLocator*>(this);
33 
34  addRef(); // Initial count set to 1
35 }
36 
37 // destructor
39  //-- inform the orphan services that I am gone....
40  for (ListSvc::iterator it = m_listsvc.begin(); it != m_listsvc.end(); it++ ) {
41  it->service->setServiceManager(0);
42  }
43 }
44 
45 //------------------------------------------------------------------------------
46 // Instantiate a service
47 SmartIF<IService>& ServiceManager::createService(const Gaudi::Utils::TypeNameString& typeName)
48 //------------------------------------------------------------------------------
49 {
50  // Check if the service is already existing
51  if(existsService(typeName.name())) {
52  // return an error because a service with that name already exists
53  return no_service;
54  }
55 
58  rc.setChecked(); //hack to avoid going into infinite recursion on ~StatusCode
59 
60  const std::string &name = typeName.name();
61  std::string type = typeName.type();
62  if (!typeName.haveType()) { // the type is not explicit
63  // see we have some specific type mapping for the name
64  MapType::iterator it = m_maptype.find(typeName.name());
65  if( it != m_maptype.end() ) {
66  type = (*it).second; // use the declared type
67  }
68  }
69 
72  if ( (ip = type.find("__")) != std::string::npos) {
73  type.erase(ip,type.length());
74  }
75 
76  IService* service = PluginService::Create<IService*>(type, name, static_cast<ISvcLocator*>(this)); // serviceLocator().get());
77  if ( !service ) {
78  service = PluginService::CreateWithId<IService*>(type, name, static_cast<ISvcLocator*>(this)); // serviceLocator().get());
79  }
80 
81  if ( service ) {
82  m_listsvc.push_back(service);
83  // Check the compatibility of the version of the interface obtained
84  if( !isValidInterface(service) ) {
85  fatal() << "Incompatible interface IService version for " << type << endmsg;
86  return no_service;
87  }
88  service->setServiceManager(this);
89  return m_listsvc.back().service;
90  }
91  fatal() << "No Service factory for " << type << " available." << endmsg;
92  return no_service;
93 }
94 
95 //------------------------------------------------------------------------------
96 // add a service to the managed list
98 //------------------------------------------------------------------------------
99 {
100  ListSvc::iterator it = find(svc);
101  if (it != m_listsvc.end()) {
102  it->priority = prio; // if the service is already known, it is equivalent to a setPriority
103  it->active = true; // and make it active
104  } else {
105  m_listsvc.push_back(ServiceItem(svc,prio,true));
106  }
107  return StatusCode::SUCCESS;
108 }
109 
110 //------------------------------------------------------------------------------
111 // add the service with the give type and name to the active list
112 StatusCode ServiceManager::addService(const Gaudi::Utils::TypeNameString& typeName, int prio)
113 //------------------------------------------------------------------------------
114 {
115  ListSvc::iterator it = find(typeName.name()); // try to find the service by name
116  if (it == m_listsvc.end()) { // not found
117  // If the service does not exist, we create it
118  SmartIF<IService> &svc = createService(typeName);
119  if (svc.isValid()) {
122  sc = svc->sysInitialize();
124  sc = svc->sysStart();
125  }
126  }
127  it = find(svc.get()); // now it is in the list because createService added it
128  if(sc.isFailure()) { // if initialization failed, remove it from the list
129  error() << "Unable to initialize service \"" << typeName.name() << "\""
130  << endmsg;
131  m_listsvc.erase(it);
132  // Note: removing it from the list + the SmartIF going out of scope should trigger the delete
133  // delete svc.get();
134  return sc;
135  } else { // initialization successful, we can work with the service
136  // Move the just initialized service to the back of the list
137  // (we care more about order of initialization than of creation)
138  m_listsvc.push_back(*it);
139  m_listsvc.erase(it);
140  it = --m_listsvc.end(); // last entry (the iterator was invalidated by erase)
141  }
142  } else {
143  return StatusCode::FAILURE;
144  }
145  }
146  // 'it' is defined because either we found the service or we created it
147  // Now we can activate the service
148  it->priority = prio; // if the service is already known, it is equivalent to a setPriority
149  it->active = true; // and make it active
150  return StatusCode(StatusCode::SUCCESS, true);
151 }
152 
153 //------------------------------------------------------------------------------
154 // Returns a smart pointer to a service.
155 SmartIF<IService> &ServiceManager::service(const Gaudi::Utils::TypeNameString &typeName, const bool createIf) {
156  const std::string &name = typeName.name();
157 
158  // Acquire the RAII lock to avoid simultaneous attempts from different threads to initialize a service
159  boost::lock_guard<boost::recursive_mutex> lck(m_svcinitmutex);
160 
161  ListSvc::iterator it = find(name);
162 
163  if (it != m_listsvc.end()) {
164  if (m_loopCheck &&
165  (createIf && it->service->FSMState() == Gaudi::StateMachine::CONFIGURED)) {
166  error()
167  << "Initialization loop detected when creating service \"" << name
168  << "\""
169  << endmsg;
170  return no_service;
171  }
172  return it->service;
173  } else {
174  // Service not found. The user may be interested in one of the interfaces
175  // of the application manager itself
176  if( name == "ApplicationMgr" ||
177  name == "APPMGR" ||
178  name == "" ) {
179  return m_appSvc;
180  } else if ( createIf ){
181  //last resort: we try to create the service
182  if (addService(typeName).isSuccess()){
183  return find(name)->service;
184  }
185  }
186  }
187  return no_service;
188 }
189 
190 //------------------------------------------------------------------------------
192 //------------------------------------------------------------------------------
193 {
195  for (ListSvc::const_iterator it = m_listsvc.begin(); it != m_listsvc.end(); ++it) {
196  m_listOfPtrs.push_back(const_cast<IService*>(it->service.get()));
197  }
198  return m_listOfPtrs;
199 }
200 
201 //------------------------------------------------------------------------------
203 //------------------------------------------------------------------------------
204 {
205  return find(name) != m_listsvc.end();
206 }
207 
208 //------------------------------------------------------------------------------
210 //------------------------------------------------------------------------------
211 {
212  ListSvc::iterator it = find(svc);
213  if (it != m_listsvc.end()) {
214  m_listsvc.erase(it);
215  return StatusCode(StatusCode::SUCCESS,true);
216  }
217  return StatusCode(StatusCode::FAILURE,true);
218 }
219 
220 //------------------------------------------------------------------------------
222 //------------------------------------------------------------------------------
223 {
224  ListSvc::iterator it = find(name);
225  if (it != m_listsvc.end()) {
226  m_listsvc.erase(it);
227  return StatusCode::SUCCESS;
228  }
229  return StatusCode::FAILURE;
230 }
231 
232 //------------------------------------------------------------------------------
234  const std::string& svctype )
235 //------------------------------------------------------------------------------
236 {
238  if( p.second == false) {
239  m_maptype.erase ( p.first );
240  p = m_maptype.insert(std::make_pair(svcname, svctype) );
241  if( p.second == false) return StatusCode::FAILURE;
242  }
243  return StatusCode::SUCCESS;
244 }
245 
246 //------------------------------------------------------------------------------
248 //------------------------------------------------------------------------------
249 {
250  m_listsvc.sort(); // ensure that the list is ordered by priority
251  // we work on a copy to avoid to operate twice on the services created on demand
252  // (which are already in the correct state.
253  ListSvc tmpList(m_listsvc);
254 
256  // call initialize() for all services
257  for (ListSvc::iterator it = tmpList.begin(); it != tmpList.end(); ++it ) {
258  if (!it->active) continue; // only act on active services
259  const std::string& name = it->service->name();
260  switch (it->service->FSMState()) {
262  DEBMSG << "Service " << name << " already initialized" << endmsg;
263  break;
265  DEBMSG << "Initializing service " << name << endmsg;
266  sc = it->service->sysInitialize();
267  if( !sc.isSuccess() ) {
268  error() << "Unable to initialize Service: " << name << endmsg;
269  return sc;
270  } break;
271  default:
272  error() << "Service " << name
273  << " not in the correct state to be initialized ("
274  << it->service->FSMState() << ")" << endmsg;
275  return StatusCode::FAILURE;
276  }
277  }
278  return StatusCode::SUCCESS;
279 }
280 
281 //------------------------------------------------------------------------------
283 //------------------------------------------------------------------------------
284 {
285  m_listsvc.sort(); // ensure that the list is ordered by priority
286  // we work on a copy to avoid to operate twice on the services created on demand
287  // (which are already in the correct state.
288  ListSvc tmpList(m_listsvc);
289 
291  // call initialize() for all services
292  for (ListSvc::iterator it = tmpList.begin(); it != tmpList.end(); ++it ) {
293  if (!it->active) continue; // only act on active services
294  const std::string& name = it->service->name();
295  switch (it->service->FSMState()) {
297  DEBMSG << "Service " << name
298  << " already started" << endmsg;
299  break;
301  DEBMSG << "Starting service " << name << endmsg;
302  sc = it->service->sysStart();
303  if( !sc.isSuccess() ) {
304  error() << "Unable to start Service: " << name << endmsg;
305  return sc;
306  } break;
307  default:
308  error() << "Service " << name
309  << " not in the correct state to be started ("
310  << it->service->FSMState() << ")" << endmsg;
311  return StatusCode::FAILURE;
312  }
313  }
314  return StatusCode::SUCCESS;
315 }
316 
317 
318 //------------------------------------------------------------------------------
320 //------------------------------------------------------------------------------
321 {
322  m_listsvc.sort(); // ensure that the list is ordered by priority
323  // we work on a copy to avoid to operate twice on the services created on demand
324  // (which are already in the correct state.
325  ListSvc tmpList(m_listsvc);
326 
329  // call stop() for all services
330  for (it = tmpList.rbegin(); it != tmpList.rend(); ++it ) {
331  if (!it->active) continue; // only act on active services
332  const std::string& name = it->service->name();
333  switch (it->service->FSMState()) {
335  DEBMSG << "Service " << name << " already stopped" << endmsg;
336  break;
338  DEBMSG << "Stopping service " << name << endmsg;
339  sc = it->service->sysStop();
340  if( !sc.isSuccess() ) {
341  error() << "Unable to stop Service: " << name << endmsg;
342  return sc;
343  } break;
344  default:
345  DEBMSG << "Service " << name
346  << " not in the correct state to be stopped ("
347  << it->service->FSMState() << ")" << endmsg;
348  return StatusCode::FAILURE;
349  }
350  }
351  return StatusCode::SUCCESS;
352 }
353 
354 //------------------------------------------------------------------------------
356 //------------------------------------------------------------------------------
357 {
358  m_listsvc.sort(); // ensure that the list is ordered by priority
359  // we work on a copy to avoid to operate twice on the services created on demand
360  // (which are already in the correct state.
361  ListSvc tmpList(m_listsvc);
362 
365  // Re-Initialize all services
366  for ( it = tmpList.begin(); it != tmpList.end(); ++it ) {
367  if (!it->active) continue; // only act on active services
368  sc = it->service->sysReinitialize();
369  if( !sc.isSuccess() ) {
370  error() << "Unable to re-initialize Service: " << it->service->name() << endmsg;
371  return StatusCode::FAILURE;
372  }
373  }
374  return StatusCode::SUCCESS;
375 }
376 
377 //------------------------------------------------------------------------------
379 //------------------------------------------------------------------------------
380 {
381  m_listsvc.sort(); // ensure that the list is ordered by priority
382  // we work on a copy to avoid to operate twice on the services created on demand
383  // (which are already in the correct state.
384  ListSvc tmpList(m_listsvc);
385 
388  // Re-Start all services
389  for ( it = tmpList.begin(); it != tmpList.end(); ++it ) {
390  if (!it->active) continue; // only act on active services
391  sc = it->service->sysRestart();
392  if( !sc.isSuccess() ) {
393  error() << "Unable to re-start Service: " << it->service->name() << endmsg;
394  return StatusCode::FAILURE;
395  }
396  }
397  return StatusCode::SUCCESS;
398 }
399 
400 //------------------------------------------------------------------------------
402 //------------------------------------------------------------------------------
403 {
404  // make sure that HistogramDataSvc and THistSvc get finalized after the
405  // ToolSvc, and StatusCodeSvc after that
406  int pri_tool = getPriority("ToolSvc");
407  if (pri_tool != 0) {
408  setPriority("THistSvc",pri_tool-1).ignore();
409  setPriority("ChronoStatSvc",pri_tool-2).ignore();
410  setPriority("AuditorSvc",pri_tool-3).ignore();
411  setPriority("NTupleSvc",pri_tool-1).ignore();
412  setPriority("HistogramDataSvc",pri_tool-1).ignore();
413  // Preserve the relative ordering between HistogramDataSvc and HistogramPersistencySvc
414  setPriority("HistogramPersistencySvc",pri_tool-2).ignore();
415  }
416 
417  // make sure the StatusCodeSvc gets finalized really late:
418  setPriority("StatusCodeSvc",-9999).ignore();
419 
420  m_listsvc.sort(); // ensure that the list is ordered by priority
421  // we work on a copy to avoid to operate twice on the services created on demand
422  // (which are already in the correct state).
423  ListSvc tmpList(m_listsvc);
424 
426  // call finalize() for all services in reverse order
428  for (rit = tmpList.rbegin(); rit != tmpList.rend(); ++rit ) {
429  if (!rit->active) continue; // only act on active services
430  const std::string& name = rit->service->name();
431  // ignore the current state for the moment
432  // if( Gaudi::StateMachine::INITIALIZED == rit->service->state() ) {
433  DEBMSG << "Finalizing service " << name << endmsg;
434  if ( !(rit->service->sysFinalize()).isSuccess() ) {
435  warning() << "Finalization of service " << name << " failed" << endmsg;
436  sc = StatusCode::FAILURE;
437  }
438  }
439  DEBMSG << "Service reference count check:" << endmsg;
441  while (!tmpList.empty()) {
442  it = tmpList.begin();
443  const std::string& name = it->service->name();
444  const unsigned long rc = it->service->refCount() - 1; // exclude the count due to the temporary list
445  DEBMSG << "---- " << name
446  << " (refCount = " << rc << ")" << endmsg;
447  if (rc < 1) {
448  warning() << "Too low reference count for " << name
449  << " (should not go below 1 at this point)" << endmsg;
450  it->service->addRef();
451  }
452  tmpList.pop_front();
453  }
454 
455  // loop over all Active Services, removing them one by one.
456  // They should be deleted because the reference counting goes to 0.
457  it = m_listsvc.begin();
458  while (it != m_listsvc.end()) {
459  if (it->active) {
460  it = m_listsvc.erase(it);
461  } else {
462  ++it;
463  }
464  }
465  return sc ;
466 }
467 
468 
469 //------------------------------------------------------------------------------
470 int
472 //------------------------------------------------------------------------------
473  ListSvc::const_iterator it = find(name);
474  return (it != m_listsvc.end()) ? it->priority: 0;
475 }
476 
477 //------------------------------------------------------------------------------
479 ServiceManager::setPriority(const std::string& name, int prio) {
480 //------------------------------------------------------------------------------
481  ListSvc::iterator it = find(name);
482  if (it != m_listsvc.end()) {
483  it->priority = prio;
484  return StatusCode::SUCCESS;
485  }
486  return StatusCode::FAILURE;
487 }
488 
489 //------------------------------------------------------------------------------
490 // Get the value of the initialization loop check flag.
491 //------------------------------------------------------------------------------
493  return m_loopCheck;
494 }
495 //------------------------------------------------------------------------------
496 // Set the value of the initialization loop check flag.
497 //------------------------------------------------------------------------------
499  m_loopCheck = en;
500 }
501 

Generated at Wed Nov 28 2012 12:17:11 for Gaudi Framework, version v23r5 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004