ATLAS Offline Software
AppMgr.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 # File: AthenaCommon/share/AppMgr.py
4 # Author: Wim Lavrijsen (WLavrijsen@lbl.gov)
5 
6 """Application manager and other global Gaudi components."""
7 
8 import os
9 import sys
10 from AthenaCommon import ExitCodes
11 
12 from AthenaCommon import AlgSequence, Configurable, Logging
13 import GaudiCoreSvc.GaudiCoreSvcConf as GaudiCoreSvcConf
14 import GaudiCommonSvc.GaudiCommonSvcConf as GaudiCommonSvcConf
15 from PyUtils.Helpers import release_metadata
16 
17 
18 __version__ = '3.2.0'
19 __author__ = 'Wim Lavrijsen (WLavrijsen@lbl.gov)'
20 
21 __all__ = [ 'theApp', 'ServiceMgr', 'ToolSvc', 'theAuditorSvc',
22  'athMasterSeq',
23  'athCondSeq',
24  'athAlgSeq',
25  'athOutSeq',
26  ]
27 
28 
29 def iadd( self, tool ):
30 
31  if not type(tool) in (list,tuple):
32  tool = (tool,)
33 
34  # only add once (allow silently)
35  if not self._useGlobalInstances:
36  # But if duplicates may not be the same Configurable instances,
37  # need to force the owner to prevent errors about public tools
38  # not in ToolSvc when old configuration fragments are imported
39  # in new configurations.
40  dups = [t for t in tool if t in self.getChildren()]
41  for t in dups:
42  t.setParent (self.name())
43  tool = [t for t in tool if t not in self.getChildren()]
44  if len(tool)==0: return self
45 
46  # this is only allowed for new-style AlgTool
47  for t in tool:
48  if not isinstance( t, Configurable.ConfigurableAlgTool ):
49  raise TypeError( '"%s" is not an AlgTool' %
50  (hasattr(t,'name') and t.name() or "This configurable" ) )
51 
52  super( GaudiCoreSvcConf.ToolSvc, self ).__iadd__( tool )
53 
54  return self
55 
56 GaudiCoreSvcConf.ToolSvc.__iadd__ = iadd
57 del iadd
58 
59 # When adding tools to ToolSvc they are stil considered "private" and thus would
60 # be copied. Overwrite the copyChild method to avoid this.
61 GaudiCoreSvcConf.ToolSvc.copyChild = lambda self, child : child
62 
63 
65  def getHandle( self ):
66  return None
67 
68  def getGaudiType ( self ):
69  return 'ServiceManager'
70 
71  def getType( self ):
72  return ''
73 
74  def getDlls ( self ):
75  return None
76 
77  def setup( self ):
78  children = self.getChildren()
79  for svc in children:
80  svc.setup()
81 
82  def __iadd__( self, service ):
83  # only add once (allow silently)
84  if service in self.getChildren():
85  return self
86 
87  # this is only allowed for new-style Services
88  if not isinstance( service, Configurable.ConfigurableService ):
89  msg = 'attempt to add an %s (%s) to the ServiceManager' %\
90  (type(service).__name__, service.name())
91  Logging.log.error( msg )
92  raise TypeError( msg )
93 
94  super( AthServiceManager, self ).__iadd__( service )
95 
96  # make all names explicitly known
97  theApp.ExtSvc += [ service.getFullName() ]
98 
99  return self
100 
101 
102 from GaudiCoreSvc.GaudiCoreSvcConf import ApplicationMgr as AppMgr
103 class AthAppMgr( AppMgr ):
104  class State:
105  """Python equivalent of IService::State enum (kind of silly to load a whole
106  dictionary library for just this quartet of integers
107  """
108 
109  # for reference, the numbers below can also be obtained through a dictionary:
110  # import cppyy
111  # cppyy.gbl.Gaudi.StateMachine.OFFLINE, ...
112 
113  OFFLINE = 0
114  CONFIGURED = 1
115  INITIALIZED = 2
116  RUNNING = 3
117 
118  def __init__( self, name = "ApplicationMgr", **kw ):
119  kw['name'] = name
120  if 'outputLevel' not in kw: kw['outputLevel'] = 3
121  if 'jobOptions' not in kw : kw['jobOptions'] = None
122 
123  # some Atlas defaults
124  if 'JobOptionsPath' not in kw: kw['JobOptionsPath'] = ""
125  if 'JobOptionsType' not in kw: kw['JobOptionsType'] = "NONE"
126  if 'EventLoop' not in kw: kw['EventLoop']="AthenaEventLoopMgr"
127  if 'StatusCodeCheck' not in kw: kw['StatusCodeCheck'] = False
128 
129  # always the case in ATLAS (need early or ExtSvc should be a no-op, too)
130  kw['ExtSvcCreates'] = False
131 
132  super(AthAppMgr,self).__init__( **kw )
133  self.__dict__[ '_cppApp' ] = None # proxy to C++/App.
134  self.__dict__[ '_sequences' ] = []
135  self.__dict__[ '_streams' ] = AlgSequence.AlgSequence( "Streams" )
136  self.__dict__[ 'CreateSvc' ] = [] # block the property
137  # TopAlg and OutStream are not user-settable directly (see __setattr__)
138  self.__dict__[ 'TopAlg' ] = [ AlgSequence.AthSequencer( "AthMasterSeq" ).getFullName() ]
139  self.__dict__[ 'OutStream' ] = []
140  self.__dict__[ '_exitstate' ] = ExitCodes.ALL_OK
141 
142  self.__dict__['state'] = lambda : AthAppMgr.State.OFFLINE
143  self.__dict__['Dlls'] = []
144 
145  # install services
146  svcMgr = self.serviceMgr() # noqa: F841
147 
148  # external option (TODO: receive this cleanly; AthOptionsParser doesn't manage results, and
149  # can't be called directly due to transforms etc.)
150  self.__dict__[ '_opts' ] = None
151 
152  # figure out which release are we running, for logging purposes
153  d = release_metadata()
154  msg = Logging.log.info
155  msg( 'using release [%(project name)s-%(release)s] [%(platform)s] [%(nightly name)s/%(nightly release)s] -- built on [%(date)s]' % d )
156 
157  return
158 
159  def __setattr__( self, name, value ):
160  # required b/c the lookup is otherwise intercepted by iProperty
161  if name[0] == '_': # private properties
162  return object.__setattr__( self, name, value )
163  # in case the C++ app has already been instantiated...
164  if hasattr(self, '_cppApp') and self._cppApp and \
165  name in AthAppMgr.__slots__:
166  handle = self.getHandle()
167  return handle.__setattr__(name, value)
168  elif name == "TopAlg" and value:
169  raise RuntimeError("Setting theApp.TopAlg is not supported. "
170  "Add the algorithm to the default AlgSequence() instead.")
171  elif name == "Dlls": # block Dlls calls
172  return
173  elif name == "OutStream" and value:
174  raise RuntimeError("Setting theApp.OutStream is not supported. "
175  "Use theApp.addOutputStream instead.")
176  elif name == "CreateSvc": # for delaying creation of services
177  self.__dict__[ name ] = value
178  else:
179  return super( AppMgr, self ).__setattr__( name, value )
180 
181  def __getattribute__( self, name ):
182  if name[0] == '_':
183  return object.__getattribute__( self, name )
184  if hasattr(self, '_cppApp') and self._cppApp and \
185  name in AthAppMgr.__slots__:
186  return getattr(self._cppApp, name)
187  else:
188  if name == "Dlls": return [] # block Dlls calls
189  return super( AthAppMgr, self ).__getattribute__(name)
190 
192  """helper method to build the top-level AthSequencer from all bits and
193  pieces : AthMasterSeq, AthAlgSeq, AthOutSeq
194  """
195  from . import AlgSequence as _as
196  from AthenaServices.AthenaServicesConf import AthIncFirerAlg as IFA
197  from GaudiCoreSvc.GaudiCoreSvcConf import IncidentProcAlg as IPA
198 
199  def _build():
200  Logging.log.debug ("building master sequence...")
201  athMasterSeq = _as.AthSequencer ("AthMasterSeq",Sequential = True)
202  athBeginSeq = _as.AthSequencer ("AthBeginSeq",Sequential=True)
203  athCondSeq = _as.AthSequencer ("AthCondSeq", StopOverride=True)
204  athAlgSeq = _as.AthSequencer ("AthAlgSeq",IgnoreFilterPassed=True, StopOverride=True, ProcessDynamicDataDependencies=True, ExtraDataForDynamicConsumers=[])
205  athEndSeq = _as.AthSequencer ("AthEndSeq",Sequential=True)
206  athOutSeq = _as.AthSequencer ("AthOutSeq", StopOverride=True)
207  athAllAlgSeq = _as.AthSequencer ("AthAllAlgSeq", StopOverride=True)
208  athAlgEvtSeq = _as.AthSequencer ("AthAlgEvtSeq",Sequential = True, StopOverride=True)
209 
210  #Setup begin and end sequences
211  # Begin Sequence
212  # IFA->BeginEvent
213  # IPA
214  ifaBeg=IFA("BeginIncFiringAlg")
215  ifaBeg.Incidents=["BeginEvent"]
216  ifaBeg.FireSerial=False # we want serial incident to be fired as well
217  athBeginSeq += ifaBeg
218  ipa=IPA("IncidentProcAlg1")
219  athBeginSeq += ipa
220 
221  # EndSequence
222  # IFA->EndEvent
223  # IPA
224  ifaEnd=IFA("EndIncFiringAlg")
225  ifaEnd.Incidents=["EndEvent"]
226  ifaEnd.FireSerial=False # we want serial incident to be fired as well
227  athEndSeq += ifaEnd
228  ipa2=IPA("IncidentProcAlg2")
229  athEndSeq += ipa2
230 
231  # XXX: should we discard empty sequences ?
232  # might save some CPU and memory...
233 
234  # ensure that the CondInputLoader gets initialized after all
235  # other user Algorithms for MT so that base classes of data deps
236  # can be correctly determined. In MT, the order of execution
237  # is irrelevant (determined by data deps). But for serial, we
238  # need the CondAlgs to execute first, so the ordering changes.
239  from AthenaCommon.ConcurrencyFlags import jobproperties as jp
240  if ( jp.ConcurrencyFlags.NumThreads() > 0 ) :
241  athAllAlgSeq += athAlgSeq
242  athAllAlgSeq += athCondSeq
243  else:
244  athAllAlgSeq += athCondSeq
245  athAllAlgSeq += athAlgSeq
246 
247  athAlgEvtSeq += athBeginSeq
248  athAlgEvtSeq += athAllAlgSeq
249  athAlgEvtSeq += athEndSeq
250 
251  athMasterSeq += athAlgEvtSeq
252  athMasterSeq += athOutSeq
253 
254  # Should be after all other algorithms.
255  athMasterSeq += IFA('EndAlgorithmsFiringAlg',
256  Incidents = ['EndAlgorithms'],
257  FireSerial = False)
258  athMasterSeq += IPA('IncidentProcAlg3')
259 
260  if Logging.log.isEnabledFor(Logging.logging.DEBUG):
261  from AthenaCommon.AlgSequence import dumpSequence
262  dumpSequence(athMasterSeq)
263 
264  Logging.log.debug ("building master sequence... [done]")
265  return athMasterSeq
266  # prevent hysteresis effect
267  if not hasattr (self, '__master_seq_built'):
268  self.__master_seq_built = True
269  return _build()
270  return _as.AthSequencer ("AthMasterSeq")
271 
272  def algorithm( self, name ):
273  if self._cppApp:
274  return self.getHandle().algorithm( name )
275  # might be lucky...
276  return super( AppMgr, self ).algorithm( name )
277 
278  def service( self, name ):
279  if self._cppApp: return self._cppApp.service(name)
280  svcMgr = self.serviceMgr()
281  if not hasattr( svcMgr, name ):
282  from AthenaCommon import CfgMgr
283  svcMgr += getattr( CfgMgr, name )()
284  return getattr( svcMgr, name )
285 
286  def setOutputLevel( self, outputLevel ):
287  if outputLevel != -1 :
288  if self.state() == AthAppMgr.State.OFFLINE : # not yet configured
289  self.OutputLevel = outputLevel
290  svcMgr = self.serviceMgr()
291  if not hasattr( svcMgr, 'MessageSvc' ):
292  svcMgr += GaudiCoreSvcConf.MessageSvc()
293  svcMgr.MessageSvc.OutputLevel = outputLevel
294 
295  # explicit user calls
296  def addSequence( self, seq ):
297  if seq not in self._sequences:
298  self._sequences.append( seq )
299 
300  def removeSequence( self, seq ):
301  self._sequences.remove( seq )
302 
303  def addOutputStream( self, stream ):
304  if stream not in self._streams.getChildren():
305  self._streams += stream
306 
307  def getOutputStream( self, stream ):
308  athOutSeq = AlgSequence.AthSequencer( "AthOutSeq" )
309  for o in athOutSeq.getChildren():
310  if o.name() == stream:
311  return o
312  for o in self._streams.getChildren():
313  if o.name() == stream:
314  return o
315  return None
316 
317  def removeOutputStream( self, stream ):
318  self._streams.remove( stream )
319 
320  # override toolSvc to handle the transitional one
321  def toolSvc( self, name='ToolSvc' ):
322  if '_toolsvc' not in self.__dict__:
323  self.__dict__[ '_toolsvc' ] = GaudiCoreSvcConf.ToolSvc( name )
324  return self._toolsvc
325  toolsvc = toolSvc
326 
327  # same for serviceMgr
328  def serviceMgr( self ):
329  if '_servicemgr' not in self.__dict__:
330  self.__dict__[ '_servicemgr' ] = AthServiceManager( 'ServiceManager' )
331  return self._servicemgr
332  servicemgr = serviceMgr
333 
334  def bootProps(self):
335  props = {}
336  for k in self.getProperties().keys():
337  if k not in [ "Go", "Exit", "AuditInitialize", "AuditFinalize" ]:
338  props[k] = self.getDefaultProperty(k)
339  if hasattr(self, k):
340  props[k] = getattr(self, k)
341  props['Dlls'] = []
342  props['CreateSvc'] = []
343  return props
344 
345  def getHandle( self, selfOptions = {} ):
346  if not self._cppApp:
347  # temporarily store this list as it will be touched by the C++ app
348  # through the __getattribute__ method
349  _createSvc = self.__dict__['CreateSvc']
350  if not selfOptions:
351  selfOptions = self.bootProps()
352  for k,v in selfOptions.items(): setattr(self, k, v)
353  svcMgr = self.serviceMgr()
354  # prevent the loading of ConfigurableDb when no configuration is done
355  if self._opts and not self._opts.fromdb:
356  from AthenaCommon.ConfigurableDb import getConfigurable
357  if not hasattr(svcMgr, 'JobOptionsSvc'):
358  svcMgr += getConfigurable(self.JobOptionsSvcType)("JobOptionsSvc")
359  if not hasattr(svcMgr, 'MessageSvc'):
360  svcMgr += getConfigurable(self.MessageSvcType)("MessageSvc")
361 
362  from GaudiPython import AppMgr as GaudiAppMgr
363  self._cppApp = GaudiAppMgr( outputlevel = self.outputLevel,
364  joboptions = None,
365  selfoptions = selfOptions )
366  self.__dict__['state'] = self._cppApp.state
367  for k,v in selfOptions.items():
368  setattr(self._cppApp,k,v)
369  self.__dict__['CreateSvc'] = _createSvc
370  del _createSvc
371 
372  import GaudiPython # this module might have disappeared b/c of cleansing # noqa: F401
373  return self._cppApp
374 
375  @property
376  def _evtSeek(self):
377  """ retrieve a handle to the IEventSeek interface of the event loop mgr
378  """
379  import AthenaPython.PyAthena as PyAthena
380  return PyAthena.py_svc(self.EventLoop, iface='IEventSeek')
381 
382  @property
383  def _evtSize(self):
384  """ retrieve a handle to the ICollectionSize interface of the event loop mgr
385  """
386  import AthenaPython.PyAthena as PyAthena
387  return PyAthena.py_svc(self.EventLoop, iface='ICollectionSize')
388 
389  # Configurable call
390  def setup( self, recursive = False ):
391  if not recursive and (self._opts and (self._opts.drop_reload or self._opts.config_only)):
392  # store configuration on disk
393  if self._opts.config_only is True: # config-only but not storing to file
394  fn = None
395  elif self._opts.config_only:
396  fn = self._opts.config_only
397  else:
398  fn = 'TempAthenaConfig.' + str(os.getpid()) + '.pkl'
399 
400  if fn is not None:
401  Logging.log.info( "storing configuration in %s", fn )
402  from AthenaCommon import ConfigurationShelve
403  ConfigurationShelve.storeJobOptionsCatalogue( fn )
404  del ConfigurationShelve
405 
406  if self._opts.drop_reload:
407  # build the new set of options; replace the .py by the .pkl,
408  # and remove '-c arg'
409  del sys.argv[ sys.argv.index( '--drop-and-reload' ) ]
410  for arg in sys.argv[1:]:
411  if arg[-3:] == '.py':
412  del sys.argv[ sys.argv.index( arg ) ]
413 
414  elif arg == '-c':
415  idx = sys.argv.index( arg )
416  del sys.argv[ idx : idx + 2 ]
417 
418  # dump profiling
419  if self._opts.profile_python:
420  i = sys.argv.index( '--profile-python' )
421  del sys.argv[i:i+2] # delete argument and its value
422  from AthenaCommon.Debugging import dumpPythonProfile
423  dumpPythonProfile(self._opts.profile_python)
424 
425  # fire ourselves up anew
426  Logging.log.info( 'restarting athena.py from %s ... ', fn )
427  sys.argv.insert( 1, fn )
428  os.execvp( sys.argv[0], sys.argv )
429 
430  else:
431  # running config-only, so we're done
432  if self._opts.profile_python:
433  from AthenaCommon.Debugging import dumpPythonProfile
434  dumpPythonProfile(self._opts.profile_python)
435  Logging.log.info( "configuration complete, now exiting ... " )
436  os._exit( self._exitstate )
437 
438  # normal setup() (non drop-and-reload) continues here:
439 
440  # first we bring the real C++ application to life...
441  handle = self.getHandle()
442 
443  # temporarily disable GaudiAppMgr.Dlls and .CreateSvc calls
444  handle.__dict__['CreateSvc'] = self.__dict__.get('CreateSvc',
445  handle.CreateSvc)
446 
447  from GaudiPython import AppMgr as GaudiAppMgr
448 
449  # Likely the first (or at least the first important) place if we're
450  # running in compatibility mode where gaudimodule will be loaded. And
451  # even if not, still ok. Remove the GaudiPython exit handlers as to
452  # prevent them from clobbering Athena ones.
453  # Don't remove exit handlers for GaudiConfig2, or we can get spurious
454  # errors on exit.
455  import atexit
456  handler = None
457  if hasattr(atexit, '_exithandlers'):
458  for handler in atexit._exithandlers[:]:
459  if hasattr(handler[0], '__module__') and handler[0].__module__:
460  if 'audiPython' in handler[0].__module__: # removes GaudiPython handlers
461  #print ("removed ", handler[0].__module__)
462  atexit._exithandlers.remove( handler )
463  del handler, atexit
464 
465  def _setattr( self, n, v ):
466  if n == 'CreateSvc':
467  self.__dict__[n] = v
468  return
469  if n == 'Dlls':
470  return
471  return super( GaudiAppMgr, self ).__setattr__( n, v )
472  GaudiAppMgr_old_setattr = GaudiAppMgr.__setattr__
473  GaudiAppMgr.__setattr__ = _setattr
474  del _setattr
475 
476  def _getattr( self, n ):
477  if n == 'CreateSvc':
478  return self.__dict__[n]
479  return super( GaudiAppMgr, self ).__getattr__( n )
480  GaudiAppMgr_old_getattr = GaudiAppMgr.__getattr__
481  GaudiAppMgr.__getattr__ = _getattr
482  del _getattr
483 
484  # public tools (they're less likely to be instantiated early, and
485  # thus rely on job options load order)
486  self.toolSvc().setup()
487 
488  # new-style services (also sets up AuditorSvc)
489  self.serviceMgr().setup()
490 
491  # setup top-level job seq
492  master_seq = self.__build_master_sequence()
493  master_seq.setup()
494 
495  # tell self about the algs
496  handle.TopAlg = [ master_seq.getFullName() ]
497 
498  # setup output streams, and tell self about them
499  streams = self.__dict__[ '_streams' ]
500  streams.setup()
501  handle.OutStream = list(map( lambda x: x.getFullName(), streams.getChildren() ))
502 
503  # synchronize 'Dlls'
504  # note: we synchronize in the opposite direction wrt CreateSvc
505  super(AppMgr,self).__setattr__('Dlls', handle.Dlls)
506 
507  # synchronize 'CreateSvc'
508  svcMgr = self.serviceMgr()
509  _createSvc = handle.__dict__['CreateSvc']
510  if len(_createSvc) > 0 and \
511  _createSvc[0] != svcMgr.ToolSvc.getFullName():
512  _createSvc = [ svcMgr.ToolSvc.getFullName() ] + _createSvc
513 
514  if 'CreateSvc' in self.__dict__:
515  del self.__dict__['CreateSvc']
516  handle.__dict__['CreateSvc'] = [ s for s in _createSvc ]
517 
518  # reinstall old __?etattr__
519  del handle.__dict__['CreateSvc']
520  GaudiAppMgr.__getattr__ = GaudiAppMgr_old_getattr
521  GaudiAppMgr.__setattr__ = GaudiAppMgr_old_setattr
522 
523  # only now allow CreateSvc, so that there are no ordering problems
524  Logging.log.debug( 'Updating (C++) "CreateSvc" property...' )
525  handle.CreateSvc = _createSvc
526  Logging.log.debug( 'Updating (C++) "CreateSvc" property... [ok]' )
527 
528  # if requested, dump the current state of the configuration to an ASCII file
529  if self._opts and self._opts.config_dump_file:
530  import AthenaCommon.ConfigurationShelve as cs
531  cs.saveToAscii(self._opts.config_dump_file)
532 
533  return
534 
535  # redefines to take into acount setup of Configurables
536  def initialize( self ):
537  # Touch these types early, before dictionaries are loaded,
538  # to prevent spurious error messages from ROOT.
539  # See ATLASRECTS-3486.
540  from os import environ
541  environ['CLING_STANDARD_PCH'] = 'none' #See bug ROOT-10789
542  import cppyy
543  getattr(cppyy.gbl, 'vector<bool>')
544  getattr(cppyy.gbl, 'vector<float>')
545  getattr(cppyy.gbl, 'vector<unsigned short>')
546  getattr(cppyy.gbl, 'vector<short>')
547  getattr(cppyy.gbl, 'vector<unsigned long>')
548  getattr(cppyy.gbl, 'vector<ULong64_t>')
549  getattr(cppyy.gbl, 'map<string,string>')
550 
551  # build configuration
552  self.setup()
553 
554  # create C++-side AppMgr
555  from AthenaCommon.ConcurrencyFlags import jobproperties as jp
556  try:
557  # Set threaded flag to release the python GIL when we're in C++
558  is_threaded = jp.ConcurrencyFlags.NumThreads() > 0
559  self.getHandle()._appmgr.initialize.__release_gil__ = is_threaded
560  sc = self.getHandle().initialize()
561  if sc.isFailure():
562  self._exitstate = ExitCodes.INI_ALG_FAILURE
563  except Exception:
564  self._exitstate = ExitCodes.INI_ALG_EXCEPTION
565  raise
566  return sc
567 
568  def reinitialize( self ):
569  # since we're going to run python again, may have to re-enable to profiler
570  if self._opts and self._opts.profile_python:
571  import cProfile
572  cProfile._athena_python_profiler.enable()
573 
574  # first, rebuild configuration
575  self.setup()
576 
577  # ApplicationMgr::reinitialize does not reinit algorithms ...
578  for name in self.getHandle().TopAlg:
579  try:
580  parts = name.split('/')
581  algname = len(parts) == 2 and parts[1] or parts[0]
582  sc = self.algorithm( algname )._ialg.reinitialize()
583  if sc.isFailure() and not self._exitstate:
584  return sc
585  except AttributeError:
586  pass
587 
588  # normal reinitialize kicks services, tools left out ...
589  return self.getHandle().reinitialize()
590 
591  # redefine run to improve interface
592  def run( self, nEvt = None ):
593  # initialize as appropriate
594  if self.state() in ( AthAppMgr.State.OFFLINE,
595  AthAppMgr.State.CONFIGURED, ):
596  Logging.log.debug( 'Initializing application manager' )
597  sc = self.initialize()
598  else:
599  Logging.log.debug( 'Re-initializing application manager' )
600  sc = self.reinitialize()
601 
602  if sc.isFailure():
603  return sc
604 
605  sc = self.start()
606  if sc.isFailure():
607  return sc
608 
609  # determine number of events
610  if nEvt is None:
611  nEvt = self.EvtMax # late, as sequences may have changed it
612 
613  from AthenaCommon.Debugging import DbgStage
614  if DbgStage.value == "exec":
615  from .Debugging import hookDebugger
616  hookDebugger()
617 
618  # actual run (FIXME: capture beginRun() exceptions and failures, which is
619  # not currently supported by IEventProcessor interface)
620  from AthenaCommon.ConcurrencyFlags import jobproperties as jp
621  try:
622  # Set threaded flag to release the GIL on execution
623  executeRunMethod = self.getHandle()._evtpro.executeRun
624  executeRunMethod.__release_gil__ = jp.ConcurrencyFlags.NumThreads() > 0
625  sc = executeRunMethod(nEvt)
626  if sc.isFailure() and not self._exitstate:
627  self._exitstate = ExitCodes.EXE_ALG_FAILURE # likely, no guarantee
628  except Exception:
629  self._exitstate = ExitCodes.EXE_ALG_EXCEPTION # idem
630  raise
631 
632  sc = self.stop()
633  return sc
634 
635  def start( self ):
636  import GaudiPython
637  sc = GaudiPython.SUCCESS
638  if self.State.INITIALIZED == self.getHandle().FSMState():
639  Logging.log.debug( 'Starting application manager' )
640  sc = self.getHandle().start()
641  return sc
642 
643  def stop( self ):
644  import GaudiPython
645  sc = GaudiPython.SUCCESS
646  if self.State.RUNNING == self.getHandle().FSMState():
647  Logging.log.debug( 'Stopping application manager' )
648  sc = self.getHandle().stop()
649  return sc
650 
651  # forward call to underlying C++/app
652  def finalize( self ):
653  #stop theApp if not already done
654  sc = theApp.stop()
655  if sc.isFailure() and not self._exitstate:
656  self._exitstate = ExitCodes.FIN_ALG_FAILURE
657  try:
658  if not self._cppApp:
659  raise RuntimeError("C++ application not instantiated : Nothing to finalize !")
660  # Set threaded flag to release the GIL when finalizing in the c++
661  from AthenaCommon.ConcurrencyFlags import jobproperties as jp
662  finalizeMethod = self.getHandle()._appmgr.finalize
663  finalizeMethod.__release_gil__ = jp.ConcurrencyFlags.NumThreads() > 0
664  sc = finalizeMethod()
665  if sc.isFailure():
666  self._exitstate = ExitCodes.FIN_ALG_FAILURE
667  except Exception:
668  self._exitstate = ExitCodes.FIN_ALG_EXCEPTION
669  raise
670  return sc
671 
672  # convenience functions to move around events
673  def curEvent( self ):
674  try:
675  return self._evtSeek.curEvent()
676  except AttributeError:
677  raise TypeError( '%s does not support IEventSeek' % theApp.EventLoop )
678 
679  def seekEvent( self, n ):
680  try:
681  sc = self._evtSeek.seek( n )
682  # prevents any unchecked statuscode leftover
683  if not sc.isSuccess():
684  return sc
685  sc = self.nextEvent()
686  # prevents any unchecked statuscode leftover
687  if not sc.isSuccess():
688  return sc
689  return sc
690  except AttributeError:
691  raise TypeError( '%s does not support IEventSeek' % theApp.EventLoop )
692 
693  def seek( self, n ):
694  try:
695  sc = self._evtSeek.seek( n )
696  # prevents any unchecked statuscode leftover
697  if not sc.isSuccess():
698  return sc
699  return sc
700  except AttributeError:
701  raise TypeError( '%s does not support IEventSeek' % theApp.EventLoop )
702 
703  def nextEvent( self, nEvt = None ):
704  #start theApp if not already done
705  sc = theApp.start()
706  if sc.isFailure() and not self._exitstate:
707  self._exitstate = ExitCodes.INI_ALG_FAILURE
708 
709  if nEvt is None:
710  nEvt = self.curEvent() + 1
711 
712  try:
713  sc = self.getHandle()._evtpro.nextEvent( nEvt )
714  if sc.isFailure() and not self._exitstate:
715  self._exitstate = ExitCodes.EXE_ALG_FAILURE
716  except Exception:
717  self._exitstate = ExitCodes.EXE_ALG_EXCEPTION
718  raise
719 
720  return sc
721 
722  def size( self ):
723  try:
724  return self._evtSize.size()
725  except AttributeError:
726  raise TypeError( '%s does not support ICollectionSize' % theApp.EventLoop )
727 
728  def replacePFC(self):
729  """ if we have MP version of EventLoopMgr
730  replace PoolFileCatalog.xml by MP version"""
731  if (self.EventLoop == 'AthMpEventLoopMgr/EventLoopMgr'):
732  if os.path.exists("MP_PoolFileCatalog.xml"):
733  Logging.log.info ("replacing PoolFileCataloG.xml by MP version")
734  import shutil
735  shutil.copy2("MP_PoolFileCatalog.xml", "PoolFileCatalog.xml")
736 
737  def exit( self, code = None ):
738  """Terminate AppMgr and exit python"""
739  try:
740  if self.state() > AthAppMgr.State.CONFIGURED:
741  sc1 = self.finalize()
742  self.replacePFC() #only for AthenaMP -> replace pfc by mp version
743  sc2 = self.getHandle()._appmgr.terminate()
744  if ( sc1.isFailure() or sc2.isFailure() ) and not self._exitstate:
745  self._exitstate = ExitCodes.FIN_ALG_FAILURE
746  except Exception:
747  if not self._exitstate:
748  self._exitstate = ExitCodes.FIN_ALG_EXCEPTION
749  import traceback
750  traceback.print_exc() # no re-raise to allow sys.exit next
751 
752  if self._opts.profile_python:
753  from AthenaCommon.Debugging import dumpPythonProfile
754  dumpPythonProfile(self._opts.profile_python)
755 
756  if code is None:
757  code = self._exitstate
758 
759  # In interactive mode, where this functions is called within an atexit handler,
760  # we cannot call sys.exit as this raises SystemExit, which is not allowed in
761  # exit handlers. Unfortunately, this also means we cannot set an exit code.
762  # See also: https://bugs.python.org/issue27035
763  # https://github.com/python/cpython/issues/103512
764  if not os.environ.get('PYTHONINSPECT', ''):
765  Logging.log.info( 'leaving with code %d: "%s"', code, ExitCodes.what( code ) )
766  sys.exit( code )
767 
768 
769 
770 theApp = AthAppMgr(
771  outputLevel = Logging.AthenaLogger.mapLevelLoggingToGaudi( Logging.log.getEffectiveLevel() )
772  )
773 
774 ServiceMgr = theApp.serviceMgr()
775 ServiceMgr += theApp.toolSvc()
776 ToolSvc = ServiceMgr.ToolSvc
777 
778 # convenience customization to deal with "Auditors" property
779 def iadd( self, config ):
780  super( GaudiCommonSvcConf.AuditorSvc, self ).__iadd__( config )
781 
782  if isinstance( config, Configurable.ConfigurableAuditor ):
783  if not config.getName() in self.Auditors and \
784  not config.getFullName() in self.Auditors:
785  self.Auditors += [ config.getFullName() ]
786 
787  return self
788 
789 GaudiCommonSvcConf.AuditorSvc.__iadd__ =iadd
790 del iadd
791 
792 
793 def _delattr( self, attr ):
794  try:
795  c = getattr( self, attr )
796 
797  try:
798  self.Auditors.remove( c.getFullName() )
799  except ValueError:
800  pass
801 
802  try:
803  self.Auditors.remove( c.getName() )
804  except ValueError:
805  pass
806 
807  except AttributeError:
808  pass
809 
810  super( GaudiCommonSvcConf.AuditorSvc, self ).__delattr__( attr )
811 
812 GaudiCommonSvcConf.AuditorSvc.__delattr__ = _delattr
813 del _delattr
814 
815 
816 # AuditorSvc globals
817 ServiceMgr += GaudiCommonSvcConf.AuditorSvc()
818 theAuditorSvc = ServiceMgr.AuditorSvc
819 
820 
821 
837 athMasterSeq = AlgSequence.AthSequencer( "AthMasterSeq" )
838 athCondSeq = AlgSequence.AthSequencer( "AthCondSeq" )
839 athAlgSeq = AlgSequence.AthSequencer( "AthAlgSeq" )
840 athOutSeq = AlgSequence.AthSequencer( "AthOutSeq" )
841 athBeginSeq = AlgSequence.AthSequencer( "AthBeginSeq" )
842 athEndSeq = AlgSequence.AthSequencer( "AthEndSeq" )
python.AlgSequence.AlgSequence
Definition: PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AlgSequence.py:19
python.AppMgr.AthServiceManager.getDlls
def getDlls(self)
Definition: AppMgr.py:74
python.AppMgr.AthAppMgr._evtSize
def _evtSize(self)
Definition: AppMgr.py:383
python.AppMgr.AthAppMgr.removeSequence
def removeSequence(self, seq)
Definition: AppMgr.py:300
python.AppMgr.AthAppMgr.initialize
def initialize(self)
Definition: AppMgr.py:536
python.AppMgr.AthAppMgr.getOutputStream
def getOutputStream(self, stream)
Definition: AppMgr.py:307
python.Configurable.ConfigurableAuditor
Definition: Configurable.py:955
python.AppMgr.AthAppMgr._evtSeek
def _evtSeek(self)
Definition: AppMgr.py:376
python.ConfigurableDb.getConfigurable
def getConfigurable(className, requester='', assumeCxxClass=True)
Definition: ConfigurableDb.py:202
python.AppMgr.AthAppMgr.replacePFC
def replacePFC(self)
Definition: AppMgr.py:728
python.AppMgr.AthAppMgr.__build_master_sequence
def __build_master_sequence(self)
Definition: AppMgr.py:191
python.Configurable.ConfigurableAlgTool
Definition: Configurable.py:875
python.Helpers.release_metadata
def release_metadata()
Definition: Tools/PyUtils/python/Helpers.py:129
python.AppMgr.AthAppMgr.algorithm
def algorithm(self, name)
Definition: AppMgr.py:272
python.AppMgr.AthAppMgr.removeOutputStream
def removeOutputStream(self, stream)
Definition: AppMgr.py:317
python.Configurable.ConfigurableService
Definition: Configurable.py:842
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.AppMgr.AthAppMgr.OutputLevel
OutputLevel
Definition: AppMgr.py:289
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
python.Debugging.dumpPythonProfile
def dumpPythonProfile(filename)
Definition: Debugging.py:97
python.AppMgr.AthAppMgr._cppApp
_cppApp
Definition: AppMgr.py:363
python.AppMgr.AthAppMgr.seekEvent
def seekEvent(self, n)
Definition: AppMgr.py:679
python.AppMgr.AthAppMgr.serviceMgr
def serviceMgr(self)
Definition: AppMgr.py:328
python.AppMgr.AthAppMgr.finalize
def finalize(self)
Definition: AppMgr.py:652
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
python.AppMgr.AthAppMgr.reinitialize
def reinitialize(self)
Definition: AppMgr.py:568
python.AppMgr.AthAppMgr.start
def start(self)
Definition: AppMgr.py:635
python.AppMgr.AthServiceManager.__iadd__
def __iadd__(self, service)
Definition: AppMgr.py:82
python.AlgSequence.dumpSequence
def dumpSequence(seq, indent=0)
Definition: Control/AthenaCommon/python/AlgSequence.py:101
python.AppMgr.AthAppMgr.__init__
def __init__(self, name="ApplicationMgr", **kw)
Definition: AppMgr.py:118
python.AppMgr.AthAppMgr.State
Definition: AppMgr.py:104
python.AppMgr.iadd
def iadd(self, tool)
associator for public tools -------------------------------------------—
Definition: AppMgr.py:29
python.AppMgr.AthAppMgr.stop
def stop(self)
Definition: AppMgr.py:643
python.AppMgr.AthAppMgr._exitstate
_exitstate
Definition: AppMgr.py:562
python.AppMgr.AthAppMgr.setOutputLevel
def setOutputLevel(self, outputLevel)
Definition: AppMgr.py:286
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
python.AppMgr.AthServiceManager.getHandle
def getHandle(self)
Definition: AppMgr.py:65
python.AppMgr.AthAppMgr.getHandle
def getHandle(self, selfOptions={})
Definition: AppMgr.py:345
python.AppMgr.AthAppMgr.curEvent
def curEvent(self)
Definition: AppMgr.py:673
python.AppMgr.AthAppMgr.nextEvent
def nextEvent(self, nEvt=None)
Definition: AppMgr.py:703
python.AppMgr.AthAppMgr.__getattribute__
def __getattribute__(self, name)
Definition: AppMgr.py:181
python.Configurable.Configurable.getChildren
def getChildren(self)
Definition: Configurable.py:408
python.AppMgr.AthAppMgr.bootProps
def bootProps(self)
Definition: AppMgr.py:334
python.AppMgr.AthAppMgr.EventLoop
EventLoop
Definition: AppMgr.py:731
python.AppMgr.AthAppMgr.exit
def exit(self, code=None)
Definition: AppMgr.py:737
python.AppMgr.AthAppMgr.size
def size(self)
Definition: AppMgr.py:722
python.AppMgr.AthAppMgr.addSequence
def addSequence(self, seq)
Definition: AppMgr.py:296
python.AppMgr.AthAppMgr.service
def service(self, name)
Definition: AppMgr.py:278
python.Configurable.Configurable
Definition: Configurable.py:47
python.AppMgr.AthAppMgr.__setattr__
def __setattr__(self, name, value)
Definition: AppMgr.py:159
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:130
python.AppMgr.AthServiceManager
associator for services -----------------------------------------------—
Definition: AppMgr.py:64
python.AppMgr.AthAppMgr.seek
def seek(self, n)
Definition: AppMgr.py:693
python.AppMgr.AthAppMgr.__master_seq_built
__master_seq_built
Definition: AppMgr.py:268
str
Definition: BTagTrackIpAccessor.cxx:11
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:801
python.AppMgr.AthAppMgr.toolSvc
def toolSvc(self, name='ToolSvc')
Definition: AppMgr.py:321
python.AppMgr.AthServiceManager.getType
def getType(self)
Definition: AppMgr.py:71
python.AppMgr.AthServiceManager.setup
def setup(self)
Definition: AppMgr.py:77
python.AppMgr.AthServiceManager.getGaudiType
def getGaudiType(self)
Definition: AppMgr.py:68
python.Debugging.hookDebugger
def hookDebugger()
Definition: Debugging.py:22
python.AppMgr._delattr
def _delattr(self, attr)
Definition: AppMgr.py:793
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
python.AppMgr.AthAppMgr.setup
def setup(self, recursive=False)
Definition: AppMgr.py:390
python.AppMgr.AthAppMgr
Definition: AppMgr.py:103
python.AlgSequence.AthSequencer
sequence of Gaudi algorithms, to replace the generated configurable
Definition: Control/AthenaCommon/python/AlgSequence.py:23
python.AppMgr.AthAppMgr.run
def run(self, nEvt=None)
Definition: AppMgr.py:592
python.AppMgr.AthAppMgr.addOutputStream
def addOutputStream(self, stream)
Definition: AppMgr.py:303
MSVtxValidationAlgUtils::getChildren
std::vector< const xAOD::TruthParticle * > getChildren(const xAOD::TruthParticle *mother)
Definition: MuonSpectrometer/MuonValidation/MuonVertexValidation/src/Utils.cxx:38