| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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"
4 #include "GaudiKernel/MsgStream.h"
5 #include "GaudiKernel/TypeNameString.h"
6 #include "GaudiKernel/System.h"
7 #include "GaudiKernel/Service.h"
8 #include "GaudiKernel/ObjectFactory.h"
9 #include "GaudiKernel/SmartIF.h"
10 #include "GaudiKernel/IIncidentSvc.h"
11 #include "GaudiKernel/IIncidentListener.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
27 ServiceManager::ServiceManager(IInterface* application):
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
39 ServiceManager::~ServiceManager() {
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
58 StatusCode rc = StatusCode::FAILURE;
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
95 StatusCode ServiceManager::addService(IService* svc, int prio)
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;
120 StatusCode sc = StatusCode(StatusCode::SUCCESS, true);
121 if (targetFSMState() >= Gaudi::StateMachine::INITIALIZED) {
122 sc = svc->sysInitialize();
123 if (sc.isSuccess() && targetFSMState() >= Gaudi::StateMachine::RUNNING) {
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 //------------------------------------------------------------------------------
210 StatusCode ServiceManager::removeService(IService* svc)
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 //------------------------------------------------------------------------------
222 StatusCode ServiceManager::removeService(const std::string& name)
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 //------------------------------------------------------------------------------
248 StatusCode ServiceManager::initialize()
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
256 StatusCode sc(StatusCode::SUCCESS, true);
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()) {
262 case Gaudi::StateMachine::INITIALIZED:
263 DEBMSG << "Service " << name << " already initialized" << endmsg;
264 break;
265 case Gaudi::StateMachine::OFFLINE:
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 //------------------------------------------------------------------------------
283 StatusCode ServiceManager::start()
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
291 StatusCode sc(StatusCode::SUCCESS, true);
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()) {
297 case Gaudi::StateMachine::RUNNING:
298 DEBMSG << "Service " << name
299 << " already started" << endmsg;
300 break;
301 case Gaudi::StateMachine::INITIALIZED:
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 //------------------------------------------------------------------------------
320 StatusCode ServiceManager::stop()
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
328 StatusCode sc(StatusCode::SUCCESS, true);
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()) {
335 case Gaudi::StateMachine::INITIALIZED:
336 DEBMSG << "Service " << name << " already stopped" << endmsg;
337 break;
338 case Gaudi::StateMachine::RUNNING:
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 //------------------------------------------------------------------------------
356 StatusCode ServiceManager::reinitialize()
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
364 StatusCode sc(StatusCode::SUCCESS, true);
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 //------------------------------------------------------------------------------
379 StatusCode ServiceManager::restart()
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
387 StatusCode sc(StatusCode::SUCCESS, true);
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 //------------------------------------------------------------------------------
402 StatusCode ServiceManager::finalize()
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
436 StatusCode sc(StatusCode::SUCCESS, true);
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 //------------------------------------------------------------------------------
501 StatusCode
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 //------------------------------------------------------------------------------
515 bool ServiceManager::loopCheckEnabled() const {
516 return m_loopCheck;
517 }
518 //------------------------------------------------------------------------------
519 // Set the value of the initialization loop check flag.
520 //------------------------------------------------------------------------------
521 void ServiceManager::setLoopCheckEnabled(bool en) {
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
559 DECLARE_OBJECT_FACTORY(ServiceManager)