The Gaudi Framework  master (82fdf313)
Loading...
Searching...
No Matches
ApplicationMgr.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11
12#include "ApplicationMgr.h"
13#include "AlgorithmManager.h"
14#include "DLLClassManager.h"
15#include "ServiceManager.h"
16#include <GAUDI_VERSION.h>
21#include <GaudiKernel/Message.h>
24#include <GaudiKernel/SmartIF.h>
26#include <GaudiKernel/System.h>
27#include <GaudiKernel/Time.h>
29#include <TError.h>
30#include <TROOT.h>
31#include <algorithm>
32#include <cassert>
33#include <limits>
34#include <sstream>
35
36using System::getEnv;
38
39#define ON_DEBUG if ( m_outputLevel <= MSG::DEBUG )
40#define ON_VERBOSE if ( m_outputLevel <= MSG::VERBOSE )
41
43
44namespace {
46 static IMessageSvc* s_messageSvcInstance{ nullptr };
48 static ErrorHandlerFunc_t s_originalRootErrorHandler{ nullptr };
49
51 void ROOTErrorHandlerAdapter( int level, Bool_t abort, const char* location, const char* msg ) {
52 if ( s_messageSvcInstance ) {
53 // we pass the message to MessageSvc only if it is not suppressed by ROOT itself
54 if ( level >= gErrorIgnoreLevel ) {
55 // # Map ROOT level to Gaudi level:
56 // ROOT levels go from 0 to 6000 in step of 1000,
57 // kInfo is 1000 while MSG::INFO is 3, so we aim for `level / 1000 + 2`,
58 // but we have to put a cap at MSG::FATAL.
59 int msgLevel = std::min<int>( level / 1000 + 2, MSG::FATAL );
60 if ( msgLevel >= s_messageSvcInstance->outputLevel( location ) ) {
61 s_messageSvcInstance->reportMessage( Message{ location, msgLevel, msg }, msgLevel );
62 }
63 }
64 } else {
65 // If a message is sent when we do not have an IMessageSvc, let's use something else
66 if ( s_originalRootErrorHandler ) {
67 // either the original handler (if any)
68 s_originalRootErrorHandler( level, abort, location, msg );
69 } else {
70 // or some minimalistic implementation from ROOT (just not to loose the message)
71 ROOT::Internal::MinimalErrorHandler( level, abort, location, msg );
72 }
73 }
74 }
75
76} // namespace
77
78// Implementation class for the Application Manager. In this way the
79// ApplicationMgr class is a fully insulated concrete class. Clients
80// (main programs) will not need to re-compile if there are changes
81// in the implementation
82
84 // IInterface initialization
85 addRef(); // Initial count set to 1
86
87 // Instantiate component managers
89
91
92 // Instantiate internal services
93 // SvcLocator/Factory HAS to be already instantiated
94 m_classManager = new DLLClassManager( this );
95
96 AlgorithmManager* algMgr = new AlgorithmManager( this );
98 // m_managers[IAlgorithm::interfaceID().id()] = new HiveAlgorithmManager(this);
99
100 // This property is not hosted in the ApplicationMgr instance
101 declareProperty( "AlgTypeAliases", algMgr->typeAliases(),
102 "Aliases of algorithm types, to replace an algorithm type for every instance" );
103
104 // ServiceMgr Initialization loop checking
106
107 m_svcMapping = { "EvtDataSvc/EventDataSvc",
108 "DetDataSvc/DetectorDataSvc",
109 "HistogramSvc/HistogramDataSvc",
110 "HbookCnv::PersSvc/HbookHistSvc",
111 "RootHistCnv::PersSvc/RootHistSvc",
112 "EvtPersistencySvc/EventPersistencySvc",
113 "DetPersistencySvc/DetectorPersistencySvc",
114 "HistogramPersistencySvc/HistogramPersistencySvc" };
115}
116
117void const* ApplicationMgr::i_cast( const InterfaceID& iid ) const {
118 // try our own interfaces
119 if ( auto output = base_class::i_cast( iid ) ) { return output; }
120 // delegate to other instances
121 if ( ISvcLocator::interfaceID().versionMatch( iid ) ) { return serviceLocator().get(); }
122 if ( ISvcManager::interfaceID().versionMatch( iid ) ) {
123 return const_cast<ApplicationMgr*>( this )->svcManager().get();
124 }
125 if ( IAlgManager::interfaceID().versionMatch( iid ) ) {
126 return const_cast<ApplicationMgr*>( this )->algManager().get();
127 }
128 if ( IClassManager::interfaceID().versionMatch( iid ) ) { return m_classManager.get(); }
129 if ( IMessageSvc::interfaceID().versionMatch( iid ) ) {
130 // Note that 0 can be a valid IMessageSvc pointer value (when used for
131 // MsgStream).
132 return m_messageSvc.get();
133 }
134 return nullptr;
135}
136
138 if ( !ppvi ) { return StatusCode::FAILURE; }
139
140 // try to find own/direct interfaces:
141 StatusCode sc = base_class::queryInterface( iid, ppvi );
142 if ( sc.isSuccess() ) return sc;
143
144 // find indirect interfaces :
145 if ( ISvcLocator::interfaceID().versionMatch( iid ) ) { return serviceLocator()->queryInterface( iid, ppvi ); }
146 if ( ISvcManager::interfaceID().versionMatch( iid ) ) { return svcManager()->queryInterface( iid, ppvi ); }
147 if ( IAlgManager::interfaceID().versionMatch( iid ) ) { return algManager()->queryInterface( iid, ppvi ); }
148 if ( IClassManager::interfaceID().versionMatch( iid ) ) { return m_classManager->queryInterface( iid, ppvi ); }
149 if ( IMessageSvc::interfaceID().versionMatch( iid ) ) {
150 *ppvi = m_messageSvc.get();
151 if ( m_messageSvc ) m_messageSvc->addRef();
152 // Note that 0 can be a valid IMessageSvc pointer value (when used for
153 // MsgStream).
154 return StatusCode::SUCCESS;
155 }
156 *ppvi = nullptr;
157 return StatusCode::FAILURE;
158}
159
161
162 StatusCode sc;
163
164 // declare factories in current module
165 m_classManager->loadModule( "" ).ignore();
166
167 // Note: we cannot use CommonMessaging methods here because MessageSvc is not there yet
168 MsgStream log( nullptr, name() );
169
170 // Create the Message service
171 auto msgsvc = svcManager()->createService( Gaudi::Utils::TypeNameString( "MessageSvc", m_messageSvcType ) );
172 if ( !msgsvc ) {
173 log << MSG::FATAL << "Error creating MessageSvc of type " << m_messageSvcType << endmsg;
174 return StatusCode::FAILURE;
175 }
176 // Get the useful interface from Message services
177 m_messageSvc = m_svcLocator->service( "MessageSvc" );
178 if ( !m_messageSvc ) {
179 log << MSG::FATAL << "Error retrieving MessageSvc." << endmsg;
180 return StatusCode::FAILURE;
181 }
182 sc = m_messageSvc.as<IProperty>()->setProperty( "OutputLevel", m_outputLevel );
183 if ( !sc ) {
184 log << MSG::FATAL << "Error setting OutputLevel option of MessageSvc" << endmsg;
185 return sc;
186 }
188 if ( gROOT ) {
189 // if ROOT is already initialized (usually it is the case) we redirect messages to MessageSvc.
190 s_messageSvcInstance = m_messageSvc.get();
191 s_originalRootErrorHandler = SetErrorHandler( ROOTErrorHandlerAdapter );
192 } else {
193 log << MSG::WARNING
194 << "ROOT not yet initialized, we cannot override the error handler are requested "
195 "(UseMessageSvcForROOTMessages==true)"
196 << endmsg;
197 }
198 }
199
200 auto jobsvc = svcManager()->createService( Gaudi::Utils::TypeNameString( "JobOptionsSvc", m_jobOptionsSvcType ) );
201 // Create the Job Options service
202 if ( !jobsvc ) {
203 log << MSG::FATAL << "Error creating JobOptionsSvc" << endmsg;
204 return StatusCode::FAILURE;
205 }
206
207 auto jobOptsIProp = jobsvc.as<IProperty>();
208 if ( !jobOptsIProp ) {
209 log << MSG::FATAL << "Error locating JobOptionsSvc" << endmsg;
210 return StatusCode::FAILURE;
211 }
212 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "TYPE", m_jobOptionsType ) );
213 if ( !sc.isSuccess() ) {
214 log << MSG::FATAL << "Error setting TYPE option in JobOptionsSvc" << endmsg;
215 return sc;
216 }
217
218 if ( !m_jobOptionsPreAction.empty() ) {
219 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PYTHONPARAMS", m_jobOptionsPreAction ) );
220 if ( !sc.isSuccess() ) {
221 log << MSG::FATAL << "Error setting JobOptionsPreAction option in JobOptionsSvc" << endmsg;
222 return sc;
223 }
224 }
225
226 if ( !m_jobOptionsPostAction.empty() ) {
227 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PYTHONACTION", m_jobOptionsPostAction ) );
228 if ( !sc.isSuccess() ) {
229 log << MSG::FATAL << "Error setting JobOptionsPostAction option in JobOptionsSvc" << endmsg;
230 return sc;
231 }
232 }
233
234 if ( !m_jobOptionsPath.empty() ) { // The command line takes precedence
235 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PATH", m_jobOptionsPath ) );
236 if ( !sc.isSuccess() ) {
237 log << MSG::FATAL << "Error setting PATH option in JobOptionsSvc" << endmsg;
238 return sc;
239 }
240 } else if ( isEnvSet( "JOBOPTPATH" ) ) { // Otherwise the Environment JOBOPTPATH
241 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PATH", getEnv( "JOBOPTPATH" ) ) );
242 if ( !sc.isSuccess() ) {
243 log << MSG::FATAL << "Error setting PATH option in JobOptionsSvc from env" << endmsg;
244 return sc;
245 }
246 } else { // Otherwise the default
247 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PATH", "../options/job.opts" ) );
248 if ( !sc.isSuccess() ) {
249 log << MSG::FATAL << "Error setting PATH option in JobOptionsSvc to default" << endmsg;
250 return sc;
251 }
252 }
253 jobOptsIProp.reset();
254
255 // Sets my default the Output Level of the Message service to be
256 // the same as this
257 auto msgSvcIProp = msgsvc.as<IProperty>();
258 msgSvcIProp->setProperty( Gaudi::Property<int>( "OutputLevel", m_outputLevel ) ).ignore();
259 msgSvcIProp.reset();
260
261 sc = jobsvc->sysInitialize();
262 if ( !sc.isSuccess() ) {
263 log << MSG::FATAL << "Error initializing JobOptionsSvc" << endmsg;
264 return sc;
265 }
266 sc = msgsvc->sysInitialize();
267 if ( !sc.isSuccess() ) {
268 log << MSG::FATAL << "Error initializing MessageSvc" << endmsg;
269 return sc;
270 }
271
272 // Make sure output level caches are up to date.
274
275 return sc;
276}
277
279
280 // Check if the state is compatible with the transition
281 MsgStream tlog( m_messageSvc, name() );
283 tlog << MSG::INFO << "Already Configured" << endmsg;
284 return StatusCode::SUCCESS;
285 }
287 tlog << MSG::FATAL << "configure: Invalid state \"" << m_state << "\"" << endmsg;
288 return StatusCode::FAILURE;
289 }
291
292 // Reset application return code.
294
295 StatusCode sc;
296 sc = i_startup();
297 if ( !sc.isSuccess() ) { return sc; }
298
299 {
300 MsgStream log( m_messageSvc, name() );
301 // Get my own options using the Job options service
302 if ( log.level() <= MSG::DEBUG ) log << MSG::DEBUG << "Getting my own properties" << endmsg;
303 bindPropertiesTo( serviceLocator()->getOptsSvc() );
304 }
305
306 // Make sure that the OutputLevel is in sync
307 if ( m_outputLevel != MSG::NIL && m_messageSvc ) m_messageSvc->setOutputLevel( name(), m_outputLevel );
308 MsgStream log( m_messageSvc, name() );
309
310 // Check current outputLevel to eventually inform the MessageSvc
311 if ( m_outputLevel != MSG::NIL && !m_appName.empty() ) {
312 // Print a welcome message
313 log << MSG::ALWAYS << std::endl
314 << "=================================================================="
315 << "==================================================================" << std::endl
316 << " "
317 << " Welcome to " << m_appName.value();
318
319 if ( !m_appVersion.empty() ) {
320 log << MSG::ALWAYS << " version " << m_appVersion.value();
321 } else {
322 log << MSG::ALWAYS << " (GaudiCoreSvc "
323 << "v" << GAUDI_MAJOR_VERSION << "r" << GAUDI_MINOR_VERSION
324#if GAUDI_PATCH_VERSION
325 << "p" << GAUDI_PATCH_VERSION
326#endif
327 << ")";
328 }
329
330 // Add the host name and current time to the message
331 log << MSG::ALWAYS << std::endl
332 << " "
333 << " running on " << System::hostName() << " on " << Gaudi::Time::current().format( true ) << std::endl
334 << "=================================================================="
335 << "==================================================================" << endmsg;
336 }
337
338 // print all own properties if the options "PropertiesPrint" is set to true
339 if ( m_propertiesPrint ) {
340 const auto& properties = getProperties();
341 log << MSG::ALWAYS << "List of ALL properties of " << System::typeinfoName( typeid( *this ) ) << "/" << this->name()
342 << " #properties = " << properties.size() << endmsg;
343 for ( const auto& property : properties ) { log << "Property ['Name': Value] = " << *property << endmsg; }
344 }
345
346 // set the requested environment variables
347 for ( auto& var : m_environment ) {
348 const std::string& name = var.first;
349 const std::string& value = var.second;
350 std::string old = System::getEnv( name.c_str() );
351 const MSG::Level lvl = ( !old.empty() && ( old != "UNKNOWN" ) ) ? MSG::WARNING : MSG::DEBUG;
352 if ( m_outputLevel <= lvl ) log << lvl << "Setting " << name << " = " << value << endmsg;
353 System::setEnv( name, value );
354 }
355
356 // Declare Service Types
357 for ( auto& j : m_svcMapping ) {
359 if ( svcManager()->declareSvcType( itm.name(), itm.type() ).isFailure() ) {
360 log << MSG::ERROR << "configure: declaring svc type:'" << j << "' failed." << endmsg;
361 return StatusCode::FAILURE;
362 } else {
364 log << MSG::VERBOSE << "declared service " << j << endmsg;
365 }
366 }
367 for ( auto& j : m_svcOptMapping ) {
369 if ( svcManager()->declareSvcType( itm.name(), itm.type() ).isFailure() ) {
370 log << MSG::ERROR << "declaring svc type:'" << j << "' failed." << endmsg;
371 return StatusCode::FAILURE;
372 }
373 }
374
375 //--------------------------------------------------------------------------
376 // Declare other Services and Algorithms by loading DLL's
377 sc = decodeDllNameList();
378 if ( sc.isFailure() ) {
379 log << MSG::ERROR << "Failure loading declared DLL's" << endmsg;
380 return sc;
381 }
382
383 //--------------------------------------------------------------------------
384 // Deal with the services explicitly declared by the user.
386 if ( sc.isFailure() ) {
387 log << MSG::ERROR << "Failure during external service association" << endmsg;
388 return sc;
389 }
390
392 if ( sc.isFailure() ) {
393 log << MSG::ERROR << "Failure during external service creation" << endmsg;
394 return sc;
395 }
396
397 //--------------------------------------------------------------------------
398 // Retrieve intrinsic services. If needed configure them.
399 //--------------------------------------------------------------------------
400 const Gaudi::Utils::TypeNameString evtloop_item( m_eventLoopMgr );
401 sc = svcManager()->addService( evtloop_item, ServiceManager::DEFAULT_SVC_PRIORITY * 10 );
402 if ( !sc.isSuccess() ) {
403 log << MSG::FATAL << "Error adding :" << m_eventLoopMgr << endmsg;
404 return sc;
405 } else {
407 log << MSG::VERBOSE << "added service " << evtloop_item << endmsg;
408 }
409
411 if ( !m_runable ) {
412 log << MSG::FATAL << "Error retrieving Runable: " << m_runableType.value() << "\n Check option ApplicationMgr."
413 << m_runableType.name() << endmsg;
414 return sc;
415 }
416 m_processingMgr = m_svcLocator->service( evtloop_item );
417 if ( !m_processingMgr ) {
418 log << MSG::FATAL << "Error retrieving Processing manager: " << m_eventLoopMgr.value()
419 << "\n Check option ApplicationMgr." << m_eventLoopMgr.name() << "\n No events will be processed." << endmsg;
420 return sc;
421 }
422 // The IEventProcessor might also be an IQueueingEventProcessor
424
425 // Establish Update Handlers for ExtSvc and DLLs Properties
426 m_extSvcNameList.declareUpdateHandler( &ApplicationMgr::extSvcNameListHandler, this );
428 m_dllNameList.declareUpdateHandler( &ApplicationMgr::dllNameListHandler, this );
429
430 if ( m_actHistory ) {
431 // Create HistorySvc with a priority to ensure it's initialized last, finalized first
432 sc = svcManager()->addService( "HistorySvc", std::numeric_limits<int>::max() );
433 if ( sc.isFailure() ) {
434 log << MSG::FATAL << "Error adding HistorySvc" << endmsg;
435 return StatusCode::FAILURE;
436 }
437 }
438
439 log << MSG::INFO << "Application Manager Configured successfully" << endmsg;
441 return StatusCode::SUCCESS;
442}
443
445 StatusCode sc;
446
447 MsgStream log( m_messageSvc, name() );
448
449 // Make sure output level caches are up to date.
451
452 // I cannot add these services in configure() because they are coming from GaudiUtils
453 // and it messes up genconf when rebuilding it.
454 if ( m_stopOnSignal ) {
455 // Instantiate the service that schedules a stop when a signal is received
456 std::string svcname( "Gaudi::Utils::StopSignalHandler" );
457 sc = svcManager()->addService( svcname );
458 if ( sc.isFailure() ) {
459 log << MSG::INFO << "Cannot instantiate " << svcname << "signals will be ignored" << endmsg;
460 }
461 }
462
464 log << MSG::INFO << "Already Initialized!" << endmsg;
465 return StatusCode::SUCCESS;
466 }
468 log << MSG::FATAL << "initialize: Invalid state \"" << m_state << "\"" << endmsg;
469 return StatusCode::FAILURE;
470 }
472
473 //--------------------------------------------------------------------------
474 // Initialize the list of top Services
475 //--------------------------------------------------------------------------
476 sc = svcManager()->initialize();
477 if ( !sc.isSuccess() ) return sc;
478
479 sc = algManager()->initialize();
480 if ( !sc.isSuccess() ) return sc;
481
482 //--------------------------------------------------------------------------
483 // Final steps: Inform user and change internal state
484 //--------------------------------------------------------------------------
485 log << MSG::INFO << "Application Manager Initialized successfully" << endmsg;
487
489
490 return sc;
491}
492
494
495 MsgStream log( m_messageSvc, name() );
496
498 log << MSG::INFO << "Already Initialized!" << endmsg;
499 return StatusCode::SUCCESS;
500 }
502 log << MSG::FATAL << "start: Invalid state \"" << m_state << "\"" << endmsg;
503 return StatusCode::FAILURE;
504 }
506
507 //--------------------------------------------------------------------------
508 // Initialize the list of top Services
509 //--------------------------------------------------------------------------
510 return m_svcLocator->service( "JobOptionsSvc" )
511 ->sysStart()
512 .andThen( [&]() { return m_messageSvc.as<IService>()->sysStart(); } )
513 .andThen( [&]() { return svcManager()->start(); } )
514 .andThen( [&]() { return algManager()->start(); } )
515 .andThen( [&]() {
516 //--------------------------------------------------------------------------
517 // Final steps: Inform user and change internal state
518 //--------------------------------------------------------------------------
519 log << MSG::INFO << "Application Manager Started successfully" << endmsg;
521 } );
522}
523
526 MsgStream log( m_messageSvc, name() );
527 log << MSG::FATAL << "nextEvent: Invalid state \"" << m_state << "\"" << endmsg;
528 return StatusCode::FAILURE;
529 }
530 if ( !m_processingMgr ) {
531 MsgStream log( m_messageSvc, name() );
532 log << MSG::FATAL << "No event processing manager specified. Check option: " << m_eventLoopMgr.name() << endmsg;
533 return StatusCode::FAILURE;
534 }
535 return m_processingMgr->nextEvent( maxevt );
536}
537
539
540 MsgStream log( m_messageSvc, name() );
541
543 log << MSG::INFO << "Already Initialized!" << endmsg;
544 return StatusCode::SUCCESS;
545 }
547 log << MSG::FATAL << "stop: Invalid state \"" << m_state << "\"" << endmsg;
548 return StatusCode::FAILURE;
549 }
551
552 // Stop independently managed Algorithms
553 return algManager()
554 ->stop()
555 //--------------------------------------------------------------------------
556 // Stop the list of top Services
557 //--------------------------------------------------------------------------
558 .andThen( [&]() { return svcManager()->stop(); } )
559 .andThen( [&]() { return m_messageSvc.as<IService>()->sysStop(); } )
560 .andThen( [&]() { return m_svcLocator->service( "JobOptionsSvc" )->sysStop(); } )
561 //--------------------------------------------------------------------------
562 // Final steps: Inform user and change internal state
563 //--------------------------------------------------------------------------
564 .andThen( [&]() {
565 log << MSG::INFO << "Application Manager Stopped successfully" << endmsg;
567 } );
568}
569
570//============================================================================
571// IAppMgrUI implementation: ApplicationMgr::finalize()
572//============================================================================
574 MsgStream log( m_messageSvc, name() );
576 log << MSG::INFO << "Already Finalized" << endmsg;
577 return StatusCode::SUCCESS;
578 }
580 log << MSG::FATAL << "finalize: Invalid state \"" << m_state << "\"" << endmsg;
581 return StatusCode::FAILURE;
582 }
584
585 // disable message suppression in finalize
586 m_svcLocator->service<IProperty>( "MessageSvc" )
587 ->setProperty( Gaudi::Property<bool>( "enableSuppression", false ) )
588 .ignore();
589
590 // Finalize independently managed Algorithms
592 if ( sc.isFailure() ) {
593 log << MSG::WARNING << "Failed to finalize an algorithm." << endmsg;
595 }
596
597 // Finalize all Services
598 sc = svcManager()->finalize();
599 if ( sc.isFailure() ) {
600 log << MSG::WARNING << "Failed to finalize a service." << endmsg;
602 }
603
604 // svcManager()->removeService( (IService*) m_processingMgr.get() );
605 // svcManager()->removeService( (IService*) m_runable.get() );
606
607 if ( sc.isSuccess() ) {
608 log << MSG::INFO << "Application Manager Finalized successfully" << endmsg;
609 } else {
610 log << MSG::ERROR << "Application Manager failed to finalize" << endmsg;
611 }
612
614 return sc;
615}
616
618 MsgStream log( m_messageSvc, name() );
619
621 log << MSG::INFO << "Already Offline" << endmsg;
622 return StatusCode::SUCCESS;
623 }
625 log << MSG::FATAL << "terminate: Invalid state \"" << m_state << "\"" << endmsg;
626 return StatusCode::FAILURE;
627 }
628 // release all Services
630
631 if ( m_returnCode.value() == Gaudi::ReturnCode::Success ) {
632 log << MSG::INFO << "Application Manager Terminated successfully" << endmsg;
633 } else if ( m_returnCode.value() == Gaudi::ReturnCode::ScheduledStop ) {
634 log << MSG::INFO << "Application Manager Terminated successfully with a user requested ScheduledStop" << endmsg;
635 } else {
636 log << MSG::ERROR << "Application Manager Terminated with error code " << m_returnCode.value() << endmsg;
637 }
638
639 {
640 auto& opts = m_svcLocator->getOptsSvc();
641 // Force a disable the auditing of finalize for MessageSvc
642 opts.set( "MessageSvc.AuditFinalize", "false" );
643 // Force a disable the auditing of finalize for JobOptionsSvc
644 opts.set( "JobOptionsSvc.AuditFinalize", "false" );
645 }
646
647 // if we have overriden it, restore the original ROOT error handler
648 if ( s_originalRootErrorHandler ) {
649 SetErrorHandler( s_originalRootErrorHandler );
650 s_originalRootErrorHandler = nullptr;
651 }
652 // make sure ROOTErrorHandlerAdapter (if in use) does not try to use the MessageSvc we are about to delete
653 s_messageSvcInstance = nullptr;
654 // finalize MessageSvc
655 auto svc = m_messageSvc.as<IService>();
656 if ( !svc ) {
657 log << MSG::ERROR << "Could not get the IService interface of the MessageSvc" << endmsg;
658 } else {
659 svc->sysFinalize().ignore();
660 svcManager()->removeService( svc ).ignore();
661 }
662
663 // finalize JobOptionsSvc
664 svc = m_svcLocator->service( "JobOptionsSvc" );
665 if ( !svc ) {
666 log << MSG::ERROR << "Could not get the IService interface of the JobOptionsSvc" << endmsg;
667 } else {
668 svc->sysFinalize().ignore();
669 svcManager()->removeService( svc ).ignore();
670 }
671
673 return StatusCode::SUCCESS;
674}
675
678
679 switch ( state ) {
680
682 switch ( m_state ) {
684 return StatusCode::SUCCESS;
685 break;
687 return terminate();
688 break;
689 default: // Gaudi::StateMachine::INITIALIZED or Gaudi::StateMachine::RUNNING
691 if ( sc.isSuccess() ) { return terminate(); }
692 break;
693 }
694 break;
695
697 switch ( m_state ) {
699 return StatusCode::SUCCESS;
700 break;
702 return configure();
703 break;
705 return finalize();
706 break;
707 default: // Gaudi::StateMachine::RUNNING
709 if ( sc.isSuccess() ) { return finalize(); }
710 break;
711 }
712 break;
713
715 switch ( m_state ) {
717 return StatusCode::SUCCESS;
718 break;
720 return initialize();
721 break;
723 return stop();
724 break;
725 default: // Gaudi::StateMachine::OFFLINE
727 if ( sc.isSuccess() ) { return initialize(); }
728 break;
729 }
730 break;
731
733 switch ( m_state ) {
735 return StatusCode::SUCCESS;
736 break;
738 return start();
739 break;
740 default: // Gaudi::StateMachine::OFFLINE or Gaudi::StateMachine::CONFIGURED
742 if ( sc.isSuccess() ) { return start(); }
743 break;
744 }
745 break;
746 }
747
748 // If I get here, there has been a problem in the recursion
749
750 if ( ignoreFailures ) {
751 // force the new state
752 m_state = state;
753 return StatusCode::SUCCESS;
754 }
755
756 return sc;
757}
758
761
763 if ( sc.isSuccess() ) {
764 MsgStream log( m_messageSvc, name() );
765 if ( m_runable != 0 ) { // loop over the events
766 sc = m_runable->run();
767 if ( !sc.isSuccess() ) { log << MSG::FATAL << "Application execution failed. Ending the job." << endmsg; }
768 } else {
769 log << MSG::FATAL << "Application has no runable object. Check option:" << m_runableType.name() << endmsg;
770 }
771 }
772 if ( sc.isSuccess() ) { // try to close cleanly
774 }
775 // either the runable failed of the stut-down
776 if ( sc.isFailure() ) { // try to close anyway (but keep the StatusCode unchanged)
778 }
779 return sc;
780}
781
784 if ( m_processingMgr ) { return m_processingMgr->executeEvent( std::move( ctx ) ); }
785 }
786 MsgStream log( m_messageSvc, name() );
787 log << MSG::FATAL << "executeEvent: Invalid state \"" << FSMState() << "\"" << endmsg;
788 return StatusCode::FAILURE;
789}
790
795
799
800std::optional<Gaudi::Interfaces::IQueueingEventProcessor::ResultType> ApplicationMgr::pop() {
802}
803
806 if ( m_processingMgr ) { return m_processingMgr->createEventContext(); }
807 }
808 std::stringstream ss;
809 ss << "createEventContext: Invalid state \"" << FSMState() << '"';
810 throw GaudiException( ss.str(), name(), StatusCode::FAILURE );
811}
812
814 MsgStream log( m_messageSvc, name() );
816 if ( m_processingMgr ) { return m_processingMgr->executeRun( evtmax ); }
817 log << MSG::WARNING << "No EventLoop Manager specified " << endmsg;
818 return StatusCode::SUCCESS;
819 }
820 log << MSG::FATAL << "executeRun: Invalid state \"" << FSMState() << "\"" << endmsg;
821 return StatusCode::FAILURE;
822}
823
825 MsgStream log( m_messageSvc, name() );
827 if ( m_processingMgr ) { return m_processingMgr->stopRun(); }
828 log << MSG::WARNING << "No EventLoop Manager specified " << endmsg;
829 return StatusCode::SUCCESS;
830 }
831 log << MSG::FATAL << "stopRun: Invalid state \"" << FSMState() << "\"" << endmsg;
832 return StatusCode::FAILURE;
833}
834const std::string& ApplicationMgr::name() const { return m_name; }
835
838
840 MsgStream log( m_messageSvc, name() );
842 StatusCode sc;
844 throw GaudiException( "Cannot reinitialize application if not INITIALIZED or RUNNING",
845 "ApplicationMgr::reinitialize", StatusCode::FAILURE );
846 }
848 sc = svcManager()->reinitialize();
849 if ( sc.isFailure() ) retval = sc;
850 sc = algManager()->reinitialize();
851 if ( sc.isFailure() ) retval = sc;
852
854 if ( sc.isFailure() ) retval = sc;
855 sc = m_svcLocator->service( "JobOptionsSvc" )->sysReinitialize();
856 if ( sc.isFailure() ) retval = sc;
857
858 log << MSG::INFO << "Application Manager Reinitialized successfully" << endmsg;
859
860 return retval;
861}
862
865 StatusCode sc;
867 throw GaudiException( "Cannot restart application if not RUNNING", "ApplicationMgr::restart", StatusCode::FAILURE );
868 }
869
870 sc = svcManager()->restart();
871 if ( sc.isFailure() ) retval = sc;
872 sc = algManager()->restart();
873 if ( sc.isFailure() ) retval = sc;
874
875 sc = m_messageSvc.as<IService>()->sysRestart();
876 if ( sc.isFailure() ) retval = sc;
877 sc = m_svcLocator->service( "JobOptionsSvc" )->sysRestart();
878 if ( sc.isFailure() ) retval = sc;
879
880 return retval;
881}
882
884 if ( m_processingMgr ) {
885 auto props = m_processingMgr.as<IProperty>();
886 if ( props ) props->setProperty( p ).ignore();
887 }
888}
889
891 if ( !( decodeCreateSvcNameList() ).isSuccess() ) {
892 throw GaudiException( "Failed to create ext services", "MinimalEventLoopMgr::createSvcNameListHandler",
894 }
895}
898 const auto& theNames = m_createSvcNameList.value();
899 auto it = theNames.begin();
900 auto et = theNames.end();
901 while ( result.isSuccess() && it != et ) {
902 Gaudi::Utils::TypeNameString item( *it++ );
903 if ( ( result = svcManager()->addService( item, ServiceManager::DEFAULT_SVC_PRIORITY ) ).isFailure() ) {
905 log << MSG::ERROR << "decodeCreateSvcNameList: Cannot create service " << item.type() << "/" << item.name()
906 << endmsg;
907 } else {
908 ON_DEBUG {
910 log << MSG::DEBUG << "decodeCreateSvcNameList: Created service " << item.type() << "/" << item.name() << endmsg;
911 }
912 }
913 }
914 return result;
915}
916
918 if ( !( decodeExtSvcNameList() ).isSuccess() ) {
919 throw GaudiException( "Failed to declare ext services", "MinimalEventLoopMgr::extSvcNameListHandler",
921 }
922}
923
926
927 const auto& theNames = m_extSvcNameList.value();
928
929 auto it = theNames.begin();
930 auto et = theNames.end();
931 while ( result.isSuccess() && it != et ) {
932 Gaudi::Utils::TypeNameString item( *it++ );
933 if ( m_extSvcCreates ) {
934 if ( ( result = svcManager()->addService( item, ServiceManager::DEFAULT_SVC_PRIORITY ) ).isFailure() ) {
936 log << MSG::ERROR << "decodeExtSvcNameList: Cannot create service " << item.type() << "/" << item.name()
937 << endmsg;
938 }
939 } else {
940 if ( ( result = svcManager()->declareSvcType( item.name(), item.type() ) ).isFailure() ) {
942 log << MSG::ERROR << "decodeExtSvcNameList: Cannot declare service " << item.type() << "/" << item.name()
943 << endmsg;
944 }
945 }
946 }
947 return result;
948}
949
951 if ( !( decodeDllNameList() ).isSuccess() ) {
952 throw GaudiException( "Failed to load DLLs.", "MinimalEventLoopMgr::dllNameListHandler", StatusCode::FAILURE );
953 }
954}
955
957
960
961 // Clean up multiple entries from DLL list
962 std::vector<std::string> newList;
963 std::map<std::string, unsigned int> dllInList, duplicateList;
964 {
965 for ( const auto& it : m_dllNameList ) {
966 if ( 0 == dllInList[it] ) {
967 newList.push_back( it ); // first instance of this module
968 } else {
969 ++duplicateList[it];
970 } // module listed multiple times
971 ++dllInList[it]; // increment count for this module
972 }
973 }
974 // m_dllNameList = newList; // update primary list to new, filtered list (do not use the
975 // property itself otherwise we get called again infinitely)
976 // List modules that were in there twice..
977 ON_DEBUG if ( !duplicateList.empty() ) {
978 log << MSG::DEBUG << "Removed duplicate entries for modules : ";
979 for ( auto it = duplicateList.begin(); it != duplicateList.end(); ++it ) {
980 log << it->first << "(" << 1 + it->second << ")";
981 if ( it != --duplicateList.end() ) log << ", ";
982 }
983 log << endmsg;
984 }
985
986 const std::vector<std::string>& theNames = newList;
987
988 // only load the new dlls or previously failed dlls
989 ON_DEBUG log << MSG::DEBUG << "Loading declared DLL's" << endmsg;
990
991 std::vector<std::string> successNames, failNames;
992 for ( const auto& it : theNames ) {
993 if ( std::find( m_okDlls.rbegin(), m_okDlls.rend(), it ) == m_okDlls.rend() ) {
994 // found a new module name
995 StatusCode status = m_classManager->loadModule( it );
996 if ( status.isFailure() ) {
997 failNames.push_back( it );
998 result = StatusCode::FAILURE;
999 } else {
1000 successNames.push_back( it );
1001 }
1002 }
1003 }
1004
1005 // report back to the user and store the names of the succesfully loaded dlls
1006 if ( !successNames.empty() ) {
1007 log << MSG::INFO << "Successfully loaded modules : ";
1008 for ( auto it = successNames.begin(); it != successNames.end(); it++ ) {
1009 log << ( *it );
1010 if ( ( it + 1 ) != successNames.end() ) log << ", ";
1011 // save name
1012 m_okDlls.push_back( *it );
1013 }
1014 log << endmsg;
1015 }
1016
1017 if ( result == StatusCode::FAILURE ) {
1018 log << MSG::WARNING << "Failed to load modules: ";
1019 for ( auto it = failNames.begin(); it != failNames.end(); it++ ) {
1020 log << ( *it );
1021 if ( ( it + 1 ) != failNames.end() ) log << ", ";
1022 }
1023 log << endmsg;
1024 }
1025 return result;
1026}
1027
1030 for ( auto& mgrItem : m_managers ) { mgrItem.second->outputLevelUpdate(); }
1031}
1032
1033namespace {
1035 void printAlgsSequencesHelper( SmartIF<IAlgManager>& algmgr, const std::string& algname, MsgStream& log,
1036 int indent ) {
1038 log << MSG::ALWAYS;
1039 for ( int i = 0; i < indent; ++i ) log << " ";
1040 log << algname << endmsg;
1041 auto prop = algmgr->algorithm<IProperty>( algname, false );
1042 if ( prop ) {
1043 // Try to get the property Members
1044 Gaudi::Property<std::vector<std::string>> p( "Members", {} );
1045 if ( prop->getProperty( &p ).isSuccess() ) {
1046 for ( auto& subalgname : p.value() ) { printAlgsSequencesHelper( algmgr, subalgname, log, indent + 1 ); }
1047 }
1048 } else {
1049 log << MSG::WARNING << "Cannot get properties of " << algname << endmsg;
1050 }
1051 }
1052} // namespace
1053
1056 log << MSG::ALWAYS << "****************************** Algorithm Sequence ****************************" << endmsg;
1057 for ( auto& algname : m_topAlgNameList ) { printAlgsSequencesHelper( algManager(), algname, log, 0 ); }
1058 log << MSG::ALWAYS << "******************************************************************************" << endmsg;
1059}
GAUDI_API bool isEnvSet(const char *var)
Check if an environment variable is set or not.
Definition System.cpp:349
#define ON_VERBOSE
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition System.cpp:329
#define GAUDI_MAJOR_VERSION
#define GAUDI_MINOR_VERSION
#define GAUDI_PATCH_VERSION
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
#define DECLARE_OBJECT_FACTORY(x)
#define ON_DEBUG
The AlgorithmManager class is in charge of the creation of concrete instances of Algorithms.
AlgTypeAliasesMap & typeAliases()
The Application Manager class.
Gaudi::Property< std::string > m_jobOptionsType
std::string m_name
Name.
SmartIF< IRunable > m_runable
Reference to the runable object.
Gaudi::Property< bool > m_printAlgsSequence
SmartIF< IQueueingEventProcessor > m_queueingProcessor
Reference to a queueing processing manager object.
Gaudi::Property< int > m_returnCode
Property to record the error conditions occurring during the running.
Gaudi::Property< std::vector< std::string > > m_svcMapping
Gaudi::Property< bool > m_useMessageSvcForROOTMessages
std::optional< Gaudi::Interfaces::IQueueingEventProcessor::ResultType > pop() override
Gaudi::Property< std::vector< std::string > > m_dllNameList
Gaudi::StateMachine::State m_targetState
Internal State.
Gaudi::Property< std::string > m_runableType
Gaudi::Property< bool > m_actHistory
void createSvcNameListHandler(Gaudi::Details::PropertyBase &)
std::vector< std::string > m_okDlls
names of successfully loaded dlls
StatusCode GoToState(Gaudi::StateMachine::State state, bool ignoreFailures=false)
Reach a state from current state (whichever it is) going through the correct transitions.
Gaudi::Property< bool > m_propertiesPrint
SmartIF< ISvcLocator > m_svcLocator
Reference to its own service locator (must be instantiated prior to any service!)
StatusCode run() override
ApplicationMgr(IInterface *=nullptr)
StatusCode finalize() override
Gaudi::Property< std::vector< std::string > > m_extSvcNameList
StatusCode nextEvent(int maxevt) override
Gaudi::Property< std::string > m_jobOptionsPath
SmartIF< DLLClassManager > m_classManager
Reference to the class manager.
StatusCode terminate() override
StatusCode initialize() override
StatusCode stopRun() override
implementation of IEventProcessor::stopRun()
SmartIF< ISvcLocator > & serviceLocator() const override
Needed to locate the message service.
StatusCode sysStop() override
SmartIF< IMessageSvc > m_messageSvc
Reference to the message service.
Gaudi::Property< std::vector< std::string > > m_svcOptMapping
SmartIF< IAlgManager > & algManager()
StatusCode executeEvent(EventContext &&ctx) override
implementation of IEventProcessor::executeEvent(void*)
void const * i_cast(const InterfaceID &iid) const override
StatusCode queryInterface(const InterfaceID &iid, void **pinterface) override
void evtLoopPropertyHandler(Gaudi::Details::PropertyBase &theProp)
Gaudi::Property< std::string > m_eventLoopMgr
const std::string & name() const override
StatusCode sysRestart() override
Gaudi::Property< std::string > m_appVersion
StatusCode sysReinitialize() override
StatusCode decodeDllNameList()
Gaudi::Property< std::vector< std::string > > m_topAlgNameList
Gaudi::Property< bool > m_extSvcCreates
Gaudi::Property< std::vector< std::string > > m_createSvcNameList
Gaudi::Property< std::map< std::string, std::string > > m_environment
EventContext createEventContext() override
implementation of IEventProcessor::createEventContext()
Gaudi::Property< std::string > m_jobOptionsPreAction
StatusCode reinitialize() override
Gaudi::Property< bool > m_loopCheck
Gaudi::Property< std::string > m_appName
void extSvcNameListHandler(Gaudi::Details::PropertyBase &theProp)
Gaudi::StateMachine::State targetFSMState() const override
StatusCode restart() override
StatusCode stop() override
void printAlgsSequences()
Print the sequence of algorithms that have been loaded.
StatusCode executeRun(int evtmax) override
implementation of IEventProcessor::executeRun(int)
static auto i_delegateToEvtProc(SELF *self, PIMPL &member, std::string_view method_name, METHOD &&method, ARGS &&... args)
Helper to delegate calls to event processor implementation.
Gaudi::Property< bool > m_stopOnSignal
Property to enable/disable the "stop on signal" service.
Gaudi::StateMachine::State FSMState() const override
StatusCode i_startup()
Internal startup routine.
Gaudi::StateMachine::State m_state
Internal State.
StatusCode start() override
void outputLevelUpdate() override
Function to call to update the outputLevel of the components (after a change in MessageSvc).
StatusCode decodeExtSvcNameList()
Gaudi::Property< std::string > m_jobOptionsSvcType
void push(EventContext &&ctx) override
StatusCode decodeCreateSvcNameList()
void dllNameListHandler(Gaudi::Details::PropertyBase &theProp)
Gaudi::Property< int > m_outputLevel
ManagersMap m_managers
Map of known component managers.
bool empty() const override
StatusCode configure() override
StatusCode sysStart() override
SmartIF< ISvcManager > & svcManager()
SmartIF< IEventProcessor > m_processingMgr
Reference to processing manager object.
Gaudi::Property< std::string > m_jobOptionsPostAction
Gaudi::Property< std::string > m_messageSvcType
This class represents an entry point to all the event specific data.
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
Definition Time.cpp:157
static Time current()
Returns the current time.
Definition Time.cpp:43
Helper class to parse a string of format "type/name".
const std::string & type() const
const std::string & name() const
Define general base for Gaudi exception.
Definition of the basic interface.
Definition IInterface.h:225
virtual StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.
static const InterfaceID & interfaceID()
Return an instance of InterfaceID identifying the interface.
Definition IInterface.h:234
The IMessage is the interface implemented by the message service.
Definition IMessageSvc.h:34
The IProperty is the basic interface for all components which have properties that can be set or get.
Definition IProperty.h:32
StatusCode setProperty(const Gaudi::Details::PropertyBase &p)
Set the property from a property.
Definition IProperty.h:38
General service interface definition.
Definition IService.h:26
virtual StatusCode finalize()=0
Finalize (from INITIALIZED to CONFIGURED).
virtual StatusCode restart()=0
Initialization (from RUNNING to RUNNING, via INITIALIZED).
virtual StatusCode reinitialize()=0
Initialization (from INITIALIZED or RUNNING to INITIALIZED, via CONFIGURED).
virtual StatusCode start()=0
Start (from INITIALIZED to RUNNING).
virtual StatusCode stop()=0
Stop (from RUNNING to INITIALIZED).
virtual StatusCode initialize()=0
Initialization (from CONFIGURED to INITIALIZED).
virtual StatusCode removeService(IService *svc)=0
Remove a service from the "active" list of services of the factory.
virtual void setLoopCheckEnabled(bool en=true)=0
Set the value of the initialization loop check flag.
virtual SmartIF< IService > & createService(const Gaudi::Utils::TypeNameString &nametype)=0
Creates and instance of a service type that has been declared beforehand and assigns it a name.
virtual StatusCode addService(IService *svc, int prio=DEFAULT_SVC_PRIORITY)=0
Add a service to the "active" list of services of the factory.
Interface ID class.
Definition IInterface.h:38
constexpr unsigned long id() const
get the interface identifier
Definition IInterface.h:47
The Message class.
Definition Message.h:25
Definition of the MsgStream class used to transmit messages.
Definition MsgStream.h:29
The ServiceManager class is in charge of the creation of concrete instances of Services.
Small smart pointer class with automatic reference counting for IInterface.
Definition SmartIF.h:28
TYPE * get() const
Get interface pointer.
Definition SmartIF.h:82
SmartIF< IFace > as() const
return a new SmartIF instance to another interface
Definition SmartIF.h:110
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isFailure() const
Definition StatusCode.h:129
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition StatusCode.h:139
StatusCode andThen(F &&f, ARGS &&... args) const
Chain code blocks making the execution conditional a success result.
Definition StatusCode.h:163
bool isSuccess() const
Definition StatusCode.h:314
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
constexpr int ScheduledStop
constexpr int FinalizationFailure
Error codes for operation failures.
constexpr int Success
State
Allowed states for classes implementing the state machine (ApplicationMgr, Algorithm,...
@ NIL
Definition IMessageSvc.h:22
@ WARNING
Definition IMessageSvc.h:22
@ FATAL
Definition IMessageSvc.h:22
@ DEBUG
Definition IMessageSvc.h:22
@ ERROR
Definition IMessageSvc.h:22
@ ALWAYS
Definition IMessageSvc.h:22
@ INFO
Definition IMessageSvc.h:22
@ VERBOSE
Definition IMessageSvc.h:22
GAUDI_API bool isEnvSet(const char *var)
Check if an environment variable is set or not.
Definition System.cpp:349
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition System.cpp:260
GAUDI_API std::vector< std::string > getEnv()
get all environment variables
Definition System.cpp:356
GAUDI_API const std::string & hostName()
Host name.
Definition System.cpp:265
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition System.cpp:329
GAUDI_API int setEnv(const std::string &name, const std::string &value, int overwrite=1)
Set an environment variables.
Definition System.cpp:440
virtual std::optional< ResultType > pop()=0
Get the next available result.
virtual bool empty() const =0
Tell if the processor has events in the queues.
virtual void push(EventContext &&ctx)=0
Schedule the processing of an event.