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