Gaudi Framework, version v25r2

Home   Generated: Wed Jun 4 2014
 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 
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
48 SmartIF<IService>& ServiceManager::createService(const Gaudi::Utils::TypeNameString& typeName)
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
110 StatusCode ServiceManager::addService(const Gaudi::Utils::TypeNameString& typeName, int prio)
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.
156 SmartIF<IService> &ServiceManager::service(const Gaudi::Utils::TypeNameString &typeName, const bool createIf) {
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 

Generated at Wed Jun 4 2014 14:48:56 for Gaudi Framework, version v25r2 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004