Gaudi Framework, version v24r2

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

Generated at Wed Dec 4 2013 14:33:08 for Gaudi Framework, version v24r2 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004