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