The Gaudi Framework  master (bdbe7744)
Loading...
Searching...
No Matches
ApplicationMgr.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2026 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
139 StatusCode sc;
140
141 // declare factories in current module
142 m_classManager->loadModule( "" ).ignore();
143
144 // Note: we cannot use CommonMessaging methods here because MessageSvc is not there yet
145 MsgStream log( nullptr, name() );
146
147 // Enable ROOT thread safety
149 if ( gROOT ) {
150 ROOT::EnableThreadSafety();
151 } else {
152 log << MSG::WARNING
153 << "ROOT not yet initialized, we cannot enable thread safety "
154 "(EnableROOTThreadSafety==True)"
155 << endmsg;
156 }
157 }
158
159 // Create the Message service
160 auto msgsvc = svcManager()->createService( Gaudi::Utils::TypeNameString( "MessageSvc", m_messageSvcType ) );
161 if ( !msgsvc ) {
162 log << MSG::FATAL << "Error creating MessageSvc of type " << m_messageSvcType << endmsg;
163 return StatusCode::FAILURE;
164 }
165 // Get the useful interface from Message services
166 m_messageSvc = m_svcLocator->service( "MessageSvc" );
167 if ( !m_messageSvc ) {
168 log << MSG::FATAL << "Error retrieving MessageSvc." << endmsg;
169 return StatusCode::FAILURE;
170 }
171 sc = m_messageSvc.as<IProperty>()->setProperty( "OutputLevel", m_outputLevel );
172 if ( !sc ) {
173 log << MSG::FATAL << "Error setting OutputLevel option of MessageSvc" << endmsg;
174 return sc;
175 }
177 if ( gROOT ) {
178 // if ROOT is already initialized (usually it is the case) we redirect messages to MessageSvc.
179 s_messageSvcInstance = m_messageSvc.get();
180 s_originalRootErrorHandler = SetErrorHandler( ROOTErrorHandlerAdapter );
181 } else {
182 log << MSG::WARNING
183 << "ROOT not yet initialized, we cannot override the error handler are requested "
184 "(UseMessageSvcForROOTMessages==true)"
185 << endmsg;
186 }
187 }
188
189 auto jobsvc = svcManager()->createService( Gaudi::Utils::TypeNameString( "JobOptionsSvc", m_jobOptionsSvcType ) );
190 // Create the Job Options service
191 if ( !jobsvc ) {
192 log << MSG::FATAL << "Error creating JobOptionsSvc" << endmsg;
193 return StatusCode::FAILURE;
194 }
195
196 auto jobOptsIProp = jobsvc.as<IProperty>();
197 if ( !jobOptsIProp ) {
198 log << MSG::FATAL << "Error locating JobOptionsSvc" << endmsg;
199 return StatusCode::FAILURE;
200 }
201 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "TYPE", m_jobOptionsType ) );
202 if ( !sc.isSuccess() ) {
203 log << MSG::FATAL << "Error setting TYPE option in JobOptionsSvc" << endmsg;
204 return sc;
205 }
206
207 if ( !m_jobOptionsPreAction.empty() ) {
208 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PYTHONPARAMS", m_jobOptionsPreAction ) );
209 if ( !sc.isSuccess() ) {
210 log << MSG::FATAL << "Error setting JobOptionsPreAction option in JobOptionsSvc" << endmsg;
211 return sc;
212 }
213 }
214
215 if ( !m_jobOptionsPostAction.empty() ) {
216 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PYTHONACTION", m_jobOptionsPostAction ) );
217 if ( !sc.isSuccess() ) {
218 log << MSG::FATAL << "Error setting JobOptionsPostAction option in JobOptionsSvc" << endmsg;
219 return sc;
220 }
221 }
222
223 if ( !m_jobOptionsPath.empty() ) { // The command line takes precedence
224 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PATH", m_jobOptionsPath ) );
225 if ( !sc.isSuccess() ) {
226 log << MSG::FATAL << "Error setting PATH option in JobOptionsSvc" << endmsg;
227 return sc;
228 }
229 } else if ( isEnvSet( "JOBOPTPATH" ) ) { // Otherwise the Environment JOBOPTPATH
230 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PATH", getEnv( "JOBOPTPATH" ) ) );
231 if ( !sc.isSuccess() ) {
232 log << MSG::FATAL << "Error setting PATH option in JobOptionsSvc from env" << endmsg;
233 return sc;
234 }
235 } else { // Otherwise the default
236 sc = jobOptsIProp->setProperty( Gaudi::Property<std::string>( "PATH", "../options/job.opts" ) );
237 if ( !sc.isSuccess() ) {
238 log << MSG::FATAL << "Error setting PATH option in JobOptionsSvc to default" << endmsg;
239 return sc;
240 }
241 }
242 jobOptsIProp.reset();
243
244 // Sets my default the Output Level of the Message service to be
245 // the same as this
246 auto msgSvcIProp = msgsvc.as<IProperty>();
247 msgSvcIProp->setProperty( Gaudi::Property<int>( "OutputLevel", m_outputLevel ) ).ignore();
248 msgSvcIProp.reset();
249
250 sc = jobsvc->sysInitialize();
251 if ( !sc.isSuccess() ) {
252 log << MSG::FATAL << "Error initializing JobOptionsSvc" << endmsg;
253 return sc;
254 }
255 sc = msgsvc->sysInitialize();
256 if ( !sc.isSuccess() ) {
257 log << MSG::FATAL << "Error initializing MessageSvc" << endmsg;
258 return sc;
259 }
260
261 // Make sure output level caches are up to date.
263
264 return sc;
265}
266
268
269 // Check if the state is compatible with the transition
270 MsgStream tlog( m_messageSvc, name() );
272 tlog << MSG::INFO << "Already Configured" << endmsg;
273 return StatusCode::SUCCESS;
274 }
276 tlog << MSG::FATAL << "configure: Invalid state \"" << m_state << "\"" << endmsg;
277 return StatusCode::FAILURE;
278 }
280
281 // Reset application return code.
283
284 StatusCode sc;
285 sc = i_startup();
286 if ( !sc.isSuccess() ) { return sc; }
287
288 {
289 MsgStream log( m_messageSvc, name() );
290 // Get my own options using the Job options service
291 if ( log.level() <= MSG::DEBUG ) log << MSG::DEBUG << "Getting my own properties" << endmsg;
292 bindPropertiesTo( serviceLocator()->getOptsSvc() );
293 }
294
295 // Make sure that the OutputLevel is in sync
296 if ( m_outputLevel != MSG::NIL && m_messageSvc ) m_messageSvc->setOutputLevel( name(), m_outputLevel );
297 MsgStream log( m_messageSvc, name() );
298
299 // Check current outputLevel to eventually inform the MessageSvc
300 if ( m_outputLevel != MSG::NIL && !m_appName.empty() ) {
301 // Print a welcome message
302 log << MSG::ALWAYS << std::endl
303 << "=================================================================="
304 << "==================================================================" << std::endl
305 << " "
306 << " Welcome to " << m_appName.value();
307
308 if ( !m_appVersion.empty() ) {
309 log << MSG::ALWAYS << " version " << m_appVersion.value();
310 } else {
311 log << MSG::ALWAYS << " (GaudiCoreSvc "
312 << "v" << GAUDI_MAJOR_VERSION << "r" << GAUDI_MINOR_VERSION
313#if GAUDI_PATCH_VERSION
314 << "p" << GAUDI_PATCH_VERSION
315#endif
316 << ")";
317 }
318
319 // Add the host name and current time to the message
320 log << MSG::ALWAYS << std::endl
321 << " "
322 << " running on " << System::hostName() << " on " << Gaudi::Time::current().format( true ) << std::endl
323 << "=================================================================="
324 << "==================================================================" << endmsg;
325 }
326
327 // print all own properties if the options "PropertiesPrint" is set to true
328 if ( m_propertiesPrint ) {
329 const auto& properties = getProperties();
330 log << MSG::ALWAYS << "List of ALL properties of " << System::typeinfoName( typeid( *this ) ) << "/" << this->name()
331 << " #properties = " << properties.size() << endmsg;
332 for ( const auto& property : properties ) { log << "Property ['Name': Value] = " << *property << endmsg; }
333 }
334
335 // set the requested environment variables
336 for ( auto& var : m_environment ) {
337 const std::string& name = var.first;
338 const std::string& value = var.second;
339 std::string old = System::getEnv( name.c_str() );
340 const MSG::Level lvl = ( !old.empty() && ( old != "UNKNOWN" ) ) ? MSG::WARNING : MSG::DEBUG;
341 if ( m_outputLevel <= lvl ) log << lvl << "Setting " << name << " = " << value << endmsg;
342 System::setEnv( name, value );
343 }
344
345 // Declare Service Types
346 for ( auto& j : m_svcMapping ) {
348 if ( svcManager()->declareSvcType( itm.name(), itm.type() ).isFailure() ) {
349 log << MSG::ERROR << "configure: declaring svc type:'" << j << "' failed." << endmsg;
350 return StatusCode::FAILURE;
351 } else {
353 log << MSG::VERBOSE << "declared service " << j << endmsg;
354 }
355 }
356 for ( auto& j : m_svcOptMapping ) {
358 if ( svcManager()->declareSvcType( itm.name(), itm.type() ).isFailure() ) {
359 log << MSG::ERROR << "declaring svc type:'" << j << "' failed." << endmsg;
360 return StatusCode::FAILURE;
361 }
362 }
363
364 //--------------------------------------------------------------------------
365 // Declare other Services and Algorithms by loading DLL's
366 sc = decodeDllNameList();
367 if ( sc.isFailure() ) {
368 log << MSG::ERROR << "Failure loading declared DLL's" << endmsg;
369 return sc;
370 }
371
372 //--------------------------------------------------------------------------
373 // Deal with the services explicitly declared by the user.
375 if ( sc.isFailure() ) {
376 log << MSG::ERROR << "Failure during external service association" << endmsg;
377 return sc;
378 }
379
381 if ( sc.isFailure() ) {
382 log << MSG::ERROR << "Failure during external service creation" << endmsg;
383 return sc;
384 }
385
386 //--------------------------------------------------------------------------
387 // Retrieve intrinsic services. If needed configure them.
388 //--------------------------------------------------------------------------
389 const Gaudi::Utils::TypeNameString evtloop_item( m_eventLoopMgr );
390 sc = svcManager()->addService( evtloop_item, ServiceManager::DEFAULT_SVC_PRIORITY * 10 );
391 if ( !sc.isSuccess() ) {
392 log << MSG::FATAL << "Error adding :" << m_eventLoopMgr << endmsg;
393 return sc;
394 } else {
396 log << MSG::VERBOSE << "added service " << evtloop_item << endmsg;
397 }
398
400 if ( !m_runable ) {
401 log << MSG::FATAL << "Error retrieving Runable: " << m_runableType.value() << "\n Check option ApplicationMgr."
402 << m_runableType.name() << endmsg;
403 return sc;
404 }
405 m_processingMgr = m_svcLocator->service( evtloop_item );
406 if ( !m_processingMgr ) {
407 log << MSG::FATAL << "Error retrieving Processing manager: " << m_eventLoopMgr.value()
408 << "\n Check option ApplicationMgr." << m_eventLoopMgr.name() << "\n No events will be processed." << endmsg;
409 return sc;
410 }
411 // The IEventProcessor might also be an IQueueingEventProcessor
413
414 // Establish Update Handlers for ExtSvc and DLLs Properties
415 m_extSvcNameList.declareUpdateHandler( &ApplicationMgr::extSvcNameListHandler, this );
417 m_dllNameList.declareUpdateHandler( &ApplicationMgr::dllNameListHandler, this );
418
419 if ( m_actHistory ) {
420 // Create HistorySvc with a priority to ensure it's initialized last, finalized first
421 sc = svcManager()->addService( "HistorySvc", std::numeric_limits<int>::max() );
422 if ( sc.isFailure() ) {
423 log << MSG::FATAL << "Error adding HistorySvc" << endmsg;
424 return StatusCode::FAILURE;
425 }
426 }
427
428 log << MSG::INFO << "Application Manager Configured successfully" << endmsg;
430 return StatusCode::SUCCESS;
431}
432
434 StatusCode sc;
435
436 MsgStream log( m_messageSvc, name() );
437
438 // Make sure output level caches are up to date.
440
441 // I cannot add these services in configure() because they are coming from GaudiUtils
442 // and it messes up genconf when rebuilding it.
443 if ( m_stopOnSignal ) {
444 // Instantiate the service that schedules a stop when a signal is received
445 std::string svcname( "Gaudi::Utils::StopSignalHandler" );
446 sc = svcManager()->addService( svcname );
447 if ( sc.isFailure() ) {
448 log << MSG::INFO << "Cannot instantiate " << svcname << "signals will be ignored" << endmsg;
449 }
450 }
451
453 log << MSG::INFO << "Already Initialized!" << endmsg;
454 return StatusCode::SUCCESS;
455 }
457 log << MSG::FATAL << "initialize: Invalid state \"" << m_state << "\"" << endmsg;
458 return StatusCode::FAILURE;
459 }
461
462 //--------------------------------------------------------------------------
463 // Initialize the list of top Services
464 //--------------------------------------------------------------------------
465 sc = svcManager()->initialize();
466 if ( !sc.isSuccess() ) return sc;
467
468 sc = algManager()->initialize();
469 if ( !sc.isSuccess() ) return sc;
470
471 //--------------------------------------------------------------------------
472 // Final steps: Inform user and change internal state
473 //--------------------------------------------------------------------------
474 log << MSG::INFO << "Application Manager Initialized successfully" << endmsg;
476
478
479 return sc;
480}
481
483
484 MsgStream log( m_messageSvc, name() );
485
487 log << MSG::INFO << "Already Initialized!" << endmsg;
488 return StatusCode::SUCCESS;
489 }
491 log << MSG::FATAL << "start: Invalid state \"" << m_state << "\"" << endmsg;
492 return StatusCode::FAILURE;
493 }
495
496 //--------------------------------------------------------------------------
497 // Initialize the list of top Services
498 //--------------------------------------------------------------------------
499 return m_svcLocator->service( "JobOptionsSvc" )
500 ->sysStart()
501 .andThen( [&]() { return m_messageSvc.as<IService>()->sysStart(); } )
502 .andThen( [&]() { return svcManager()->start(); } )
503 .andThen( [&]() { return algManager()->start(); } )
504 .andThen( [&]() {
505 //--------------------------------------------------------------------------
506 // Final steps: Inform user and change internal state
507 //--------------------------------------------------------------------------
508 log << MSG::INFO << "Application Manager Started successfully" << endmsg;
510 } );
511}
512
515 MsgStream log( m_messageSvc, name() );
516 log << MSG::FATAL << "nextEvent: Invalid state \"" << m_state << "\"" << endmsg;
517 return StatusCode::FAILURE;
518 }
519 if ( !m_processingMgr ) {
520 MsgStream log( m_messageSvc, name() );
521 log << MSG::FATAL << "No event processing manager specified. Check option: " << m_eventLoopMgr.name() << endmsg;
522 return StatusCode::FAILURE;
523 }
524 return m_processingMgr->nextEvent( maxevt );
525}
526
528
529 MsgStream log( m_messageSvc, name() );
530
532 log << MSG::INFO << "Already Initialized!" << endmsg;
533 return StatusCode::SUCCESS;
534 }
536 log << MSG::FATAL << "stop: Invalid state \"" << m_state << "\"" << endmsg;
537 return StatusCode::FAILURE;
538 }
540
541 // Stop independently managed Algorithms
542 return algManager()
543 ->stop()
544 //--------------------------------------------------------------------------
545 // Stop the list of top Services
546 //--------------------------------------------------------------------------
547 .andThen( [&]() { return svcManager()->stop(); } )
548 .andThen( [&]() { return m_messageSvc.as<IService>()->sysStop(); } )
549 .andThen( [&]() { return m_svcLocator->service( "JobOptionsSvc" )->sysStop(); } )
550 //--------------------------------------------------------------------------
551 // Final steps: Inform user and change internal state
552 //--------------------------------------------------------------------------
553 .andThen( [&]() {
554 log << MSG::INFO << "Application Manager Stopped successfully" << endmsg;
556 } );
557}
558
559//============================================================================
560// IAppMgrUI implementation: ApplicationMgr::finalize()
561//============================================================================
563 MsgStream log( m_messageSvc, name() );
565 log << MSG::INFO << "Already Finalized" << endmsg;
566 return StatusCode::SUCCESS;
567 }
569 log << MSG::FATAL << "finalize: Invalid state \"" << m_state << "\"" << endmsg;
570 return StatusCode::FAILURE;
571 }
573
574 // disable message suppression in finalize
575 m_svcLocator->service<IProperty>( "MessageSvc" )
576 ->setProperty( Gaudi::Property<bool>( "enableSuppression", false ) )
577 .ignore();
578
579 // Finalize independently managed Algorithms
581 if ( sc.isFailure() ) {
582 log << MSG::WARNING << "Failed to finalize an algorithm." << endmsg;
584 }
585
586 // Finalize all Services
587 sc = svcManager()->finalize();
588 if ( sc.isFailure() ) {
589 log << MSG::WARNING << "Failed to finalize a service." << endmsg;
591 }
592
593 // svcManager()->removeService( (IService*) m_processingMgr.get() );
594 // svcManager()->removeService( (IService*) m_runable.get() );
595
596 if ( sc.isSuccess() ) {
597 log << MSG::INFO << "Application Manager Finalized successfully" << endmsg;
598 } else {
599 log << MSG::ERROR << "Application Manager failed to finalize" << endmsg;
600 }
601
603 return sc;
604}
605
607 MsgStream log( m_messageSvc, name() );
608
610 log << MSG::INFO << "Already Offline" << endmsg;
611 return StatusCode::SUCCESS;
612 }
614 log << MSG::FATAL << "terminate: Invalid state \"" << m_state << "\"" << endmsg;
615 return StatusCode::FAILURE;
616 }
617 // release all Services
619
620 if ( m_returnCode.value() == Gaudi::ReturnCode::Success ) {
621 log << MSG::INFO << "Application Manager Terminated successfully" << endmsg;
622 } else if ( m_returnCode.value() == Gaudi::ReturnCode::ScheduledStop ) {
623 log << MSG::INFO << "Application Manager Terminated successfully with a user requested ScheduledStop" << endmsg;
624 } else {
625 log << MSG::ERROR << "Application Manager Terminated with error code " << m_returnCode.value() << endmsg;
626 }
627
628 {
629 auto& opts = m_svcLocator->getOptsSvc();
630 // Force a disable the auditing of finalize for MessageSvc
631 opts.set( "MessageSvc.AuditFinalize", "false" );
632 // Force a disable the auditing of finalize for JobOptionsSvc
633 opts.set( "JobOptionsSvc.AuditFinalize", "false" );
634 }
635
636 // if we have overriden it, restore the original ROOT error handler
637 if ( s_originalRootErrorHandler ) {
638 SetErrorHandler( s_originalRootErrorHandler );
639 s_originalRootErrorHandler = nullptr;
640 }
641 // make sure ROOTErrorHandlerAdapter (if in use) does not try to use the MessageSvc we are about to delete
642 s_messageSvcInstance = nullptr;
643 // finalize MessageSvc
644 auto svc = m_messageSvc.as<IService>();
645 if ( !svc ) {
646 log << MSG::ERROR << "Could not get the IService interface of the MessageSvc" << endmsg;
647 } else {
648 svc->sysFinalize().ignore();
649 svcManager()->removeService( svc ).ignore();
650 }
651
652 // finalize JobOptionsSvc
653 svc = m_svcLocator->service( "JobOptionsSvc" );
654 if ( !svc ) {
655 log << MSG::ERROR << "Could not get the IService interface of the JobOptionsSvc" << endmsg;
656 } else {
657 svc->sysFinalize().ignore();
658 svcManager()->removeService( svc ).ignore();
659 }
660
662 return StatusCode::SUCCESS;
663}
664
667
668 switch ( state ) {
669
671 switch ( m_state ) {
673 return StatusCode::SUCCESS;
674 break;
676 return terminate();
677 break;
678 default: // Gaudi::StateMachine::INITIALIZED or Gaudi::StateMachine::RUNNING
680 if ( sc.isSuccess() ) { return terminate(); }
681 break;
682 }
683 break;
684
686 switch ( m_state ) {
688 return StatusCode::SUCCESS;
689 break;
691 return configure();
692 break;
694 return finalize();
695 break;
696 default: // Gaudi::StateMachine::RUNNING
698 if ( sc.isSuccess() ) { return finalize(); }
699 break;
700 }
701 break;
702
704 switch ( m_state ) {
706 return StatusCode::SUCCESS;
707 break;
709 return initialize();
710 break;
712 return stop();
713 break;
714 default: // Gaudi::StateMachine::OFFLINE
716 if ( sc.isSuccess() ) { return initialize(); }
717 break;
718 }
719 break;
720
722 switch ( m_state ) {
724 return StatusCode::SUCCESS;
725 break;
727 return start();
728 break;
729 default: // Gaudi::StateMachine::OFFLINE or Gaudi::StateMachine::CONFIGURED
731 if ( sc.isSuccess() ) { return start(); }
732 break;
733 }
734 break;
735 }
736
737 // If I get here, there has been a problem in the recursion
738
739 if ( ignoreFailures ) {
740 // force the new state
741 m_state = state;
742 return StatusCode::SUCCESS;
743 }
744
745 return sc;
746}
747
750
752 if ( sc.isSuccess() ) {
753 MsgStream log( m_messageSvc, name() );
754 if ( m_runable != 0 ) { // loop over the events
755 sc = m_runable->run();
756 if ( !sc.isSuccess() ) { log << MSG::FATAL << "Application execution failed. Ending the job." << endmsg; }
757 } else {
758 log << MSG::FATAL << "Application has no runable object. Check option:" << m_runableType.name() << endmsg;
759 }
760 }
761 if ( sc.isSuccess() ) { // try to close cleanly
763 }
764 // either the runable failed of the stut-down
765 if ( sc.isFailure() ) { // try to close anyway (but keep the StatusCode unchanged)
767 }
768 return sc;
769}
770
773 if ( m_processingMgr ) { return m_processingMgr->executeEvent( std::move( ctx ) ); }
774 }
775 MsgStream log( m_messageSvc, name() );
776 log << MSG::FATAL << "executeEvent: Invalid state \"" << FSMState() << "\"" << endmsg;
777 return StatusCode::FAILURE;
778}
779
784
788
789std::optional<Gaudi::Interfaces::IQueueingEventProcessor::ResultType> ApplicationMgr::pop() {
791}
792
795 if ( m_processingMgr ) { return m_processingMgr->createEventContext(); }
796 }
797 std::stringstream ss;
798 ss << "createEventContext: Invalid state \"" << FSMState() << '"';
799 throw GaudiException( ss.str(), name(), StatusCode::FAILURE );
800}
801
803 MsgStream log( m_messageSvc, name() );
805 if ( m_processingMgr ) { return m_processingMgr->executeRun( evtmax ); }
806 log << MSG::WARNING << "No EventLoop Manager specified " << endmsg;
807 return StatusCode::SUCCESS;
808 }
809 log << MSG::FATAL << "executeRun: Invalid state \"" << FSMState() << "\"" << endmsg;
810 return StatusCode::FAILURE;
811}
812
814 MsgStream log( m_messageSvc, name() );
816 if ( m_processingMgr ) { return m_processingMgr->stopRun(); }
817 log << MSG::WARNING << "No EventLoop Manager specified " << endmsg;
818 return StatusCode::SUCCESS;
819 }
820 log << MSG::FATAL << "stopRun: Invalid state \"" << FSMState() << "\"" << endmsg;
821 return StatusCode::FAILURE;
822}
823const std::string& ApplicationMgr::name() const { return m_name; }
824
827
829 MsgStream log( m_messageSvc, name() );
831 StatusCode sc;
833 throw GaudiException( "Cannot reinitialize application if not INITIALIZED or RUNNING",
834 "ApplicationMgr::reinitialize", StatusCode::FAILURE );
835 }
837 sc = svcManager()->reinitialize();
838 if ( sc.isFailure() ) retval = sc;
839 sc = algManager()->reinitialize();
840 if ( sc.isFailure() ) retval = sc;
841
843 if ( sc.isFailure() ) retval = sc;
844 sc = m_svcLocator->service( "JobOptionsSvc" )->sysReinitialize();
845 if ( sc.isFailure() ) retval = sc;
846
847 log << MSG::INFO << "Application Manager Reinitialized successfully" << endmsg;
848
849 return retval;
850}
851
854 StatusCode sc;
856 throw GaudiException( "Cannot restart application if not RUNNING", "ApplicationMgr::restart", StatusCode::FAILURE );
857 }
858
859 sc = svcManager()->restart();
860 if ( sc.isFailure() ) retval = sc;
861 sc = algManager()->restart();
862 if ( sc.isFailure() ) retval = sc;
863
864 sc = m_messageSvc.as<IService>()->sysRestart();
865 if ( sc.isFailure() ) retval = sc;
866 sc = m_svcLocator->service( "JobOptionsSvc" )->sysRestart();
867 if ( sc.isFailure() ) retval = sc;
868
869 return retval;
870}
871
873 if ( m_processingMgr ) {
874 auto props = m_processingMgr.as<IProperty>();
875 if ( props ) props->setProperty( p ).ignore();
876 }
877}
878
880 if ( !( decodeCreateSvcNameList() ).isSuccess() ) {
881 throw GaudiException( "Failed to create ext services", "MinimalEventLoopMgr::createSvcNameListHandler",
883 }
884}
887 const auto& theNames = m_createSvcNameList.value();
888 auto it = theNames.begin();
889 auto et = theNames.end();
890 while ( result.isSuccess() && it != et ) {
891 Gaudi::Utils::TypeNameString item( *it++ );
892 if ( ( result = svcManager()->addService( item, ServiceManager::DEFAULT_SVC_PRIORITY ) ).isFailure() ) {
894 log << MSG::ERROR << "decodeCreateSvcNameList: Cannot create service " << item.type() << "/" << item.name()
895 << endmsg;
896 } else {
897 ON_DEBUG {
899 log << MSG::DEBUG << "decodeCreateSvcNameList: Created service " << item.type() << "/" << item.name() << endmsg;
900 }
901 }
902 }
903 return result;
904}
905
907 if ( !( decodeExtSvcNameList() ).isSuccess() ) {
908 throw GaudiException( "Failed to declare ext services", "MinimalEventLoopMgr::extSvcNameListHandler",
910 }
911}
912
915
916 const auto& theNames = m_extSvcNameList.value();
917
918 auto it = theNames.begin();
919 auto et = theNames.end();
920 while ( result.isSuccess() && it != et ) {
921 Gaudi::Utils::TypeNameString item( *it++ );
922 if ( m_extSvcCreates ) {
923 if ( ( result = svcManager()->addService( item, ServiceManager::DEFAULT_SVC_PRIORITY ) ).isFailure() ) {
925 log << MSG::ERROR << "decodeExtSvcNameList: Cannot create service " << item.type() << "/" << item.name()
926 << endmsg;
927 }
928 } else {
929 if ( ( result = svcManager()->declareSvcType( item.name(), item.type() ) ).isFailure() ) {
931 log << MSG::ERROR << "decodeExtSvcNameList: Cannot declare service " << item.type() << "/" << item.name()
932 << endmsg;
933 }
934 }
935 }
936 return result;
937}
938
940 if ( !( decodeDllNameList() ).isSuccess() ) {
941 throw GaudiException( "Failed to load DLLs.", "MinimalEventLoopMgr::dllNameListHandler", StatusCode::FAILURE );
942 }
943}
944
946
949
950 // Clean up multiple entries from DLL list
951 std::vector<std::string> newList;
952 std::map<std::string, unsigned int> dllInList, duplicateList;
953 {
954 for ( const auto& it : m_dllNameList ) {
955 if ( 0 == dllInList[it] ) {
956 newList.push_back( it ); // first instance of this module
957 } else {
958 ++duplicateList[it];
959 } // module listed multiple times
960 ++dllInList[it]; // increment count for this module
961 }
962 }
963 // m_dllNameList = newList; // update primary list to new, filtered list (do not use the
964 // property itself otherwise we get called again infinitely)
965 // List modules that were in there twice..
966 ON_DEBUG if ( !duplicateList.empty() ) {
967 log << MSG::DEBUG << "Removed duplicate entries for modules : ";
968 for ( auto it = duplicateList.begin(); it != duplicateList.end(); ++it ) {
969 log << it->first << "(" << 1 + it->second << ")";
970 if ( it != --duplicateList.end() ) log << ", ";
971 }
972 log << endmsg;
973 }
974
975 const std::vector<std::string>& theNames = newList;
976
977 // only load the new dlls or previously failed dlls
978 ON_DEBUG log << MSG::DEBUG << "Loading declared DLL's" << endmsg;
979
980 std::vector<std::string> successNames, failNames;
981 for ( const auto& it : theNames ) {
982 if ( std::find( m_okDlls.rbegin(), m_okDlls.rend(), it ) == m_okDlls.rend() ) {
983 // found a new module name
984 StatusCode status = m_classManager->loadModule( it );
985 if ( status.isFailure() ) {
986 failNames.push_back( it );
987 result = StatusCode::FAILURE;
988 } else {
989 successNames.push_back( it );
990 }
991 }
992 }
993
994 // report back to the user and store the names of the succesfully loaded dlls
995 if ( !successNames.empty() ) {
996 log << MSG::INFO << "Successfully loaded modules : ";
997 for ( auto it = successNames.begin(); it != successNames.end(); it++ ) {
998 log << ( *it );
999 if ( ( it + 1 ) != successNames.end() ) log << ", ";
1000 // save name
1001 m_okDlls.push_back( *it );
1002 }
1003 log << endmsg;
1004 }
1005
1006 if ( result == StatusCode::FAILURE ) {
1007 log << MSG::WARNING << "Failed to load modules: ";
1008 for ( auto it = failNames.begin(); it != failNames.end(); it++ ) {
1009 log << ( *it );
1010 if ( ( it + 1 ) != failNames.end() ) log << ", ";
1011 }
1012 log << endmsg;
1013 }
1014 return result;
1015}
1016
1019 for ( auto& mgrItem : m_managers ) { mgrItem.second->outputLevelUpdate(); }
1020}
1021
1022namespace {
1024 void printAlgsSequencesHelper( SmartIF<IAlgManager>& algmgr, const std::string& algname, MsgStream& log,
1025 int indent ) {
1027 log << MSG::ALWAYS;
1028 for ( int i = 0; i < indent; ++i ) log << " ";
1029 log << algname << endmsg;
1030 auto prop = algmgr->algorithm<IProperty>( algname, false );
1031 if ( prop ) {
1032 // Try to get the property Members
1033 Gaudi::Property<std::vector<std::string>> p( "Members", {} );
1034 if ( prop->getProperty( &p ).isSuccess() ) {
1035 for ( auto& subalgname : p.value() ) { printAlgsSequencesHelper( algmgr, subalgname, log, indent + 1 ); }
1036 }
1037 } else {
1038 log << MSG::WARNING << "Cannot get properties of " << algname << endmsg;
1039 }
1040 }
1041} // namespace
1042
1045 log << MSG::ALWAYS << "****************************** Algorithm Sequence ****************************" << endmsg;
1046 for ( auto& algname : m_topAlgNameList ) { printAlgsSequencesHelper( algManager(), algname, log, 0 ); }
1047 log << MSG::ALWAYS << "******************************************************************************" << endmsg;
1048}
GAUDI_API bool isEnvSet(const char *var)
Check if an environment variable is set or not.
Definition System.cpp:334
#define ON_VERBOSE
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition System.cpp:314
#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
Gaudi::Property< bool > m_enableROOTThreadSafety
SmartIF< IAlgManager > & algManager()
StatusCode executeEvent(EventContext &&ctx) override
implementation of IEventProcessor::executeEvent(void*)
void const * i_cast(const InterfaceID &iid) const 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 Property.h:35
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
Definition Time.cpp:155
static Time current()
Returns the current time.
Definition Time.cpp:41
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
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
virtual void reportMessage(const Message &msg, int outputLevel)=0
Report a message by sending a Message object to the message service.
virtual int outputLevel() const =0
Retrieve the current output level threshold.
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:118
StatusCode andThen(F &&f, ARGS &&... args) const
Chain code blocks making the execution conditional a success result.
Definition StatusCode.h:151
void ignore() const
Allow discarding a StatusCode without warning.
Definition StatusCode.h:128
bool isSuccess() const
Definition StatusCode.h:302
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:334
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition System.cpp:254
GAUDI_API std::vector< std::string > getEnv()
get all environment variables
Definition System.cpp:341
GAUDI_API const std::string & hostName()
Host name.
Definition System.cpp:259
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition System.cpp:314
GAUDI_API int setEnv(const std::string &name, const std::string &value, int overwrite=1)
Set an environment variables.
Definition System.cpp:425
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.