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 sys, os
9 from AthenaCommon import ExitCodes
10 
11 from AthenaCommon import AlgSequence, Configurable, Logging
12 import GaudiCoreSvc.GaudiCoreSvcConf as GaudiCoreSvcConf
13 import GaudiCommonSvc.GaudiCommonSvcConf as GaudiCommonSvcConf
14 from PyUtils.Helpers import release_metadata
15 
16 
17 __version__ = '3.2.0'
18 __author__ = 'Wim Lavrijsen (WLavrijsen@lbl.gov)'
19 
20 __all__ = [ 'theApp', 'ServiceMgr', 'ToolSvc', 'theAuditorSvc',
21  'athMasterSeq',
22  'athCondSeq',
23  'athAlgSeq', 'topSequence',
24  'athOutSeq',
25  ]
26 
27 
28 def iadd( self, tool ):
29 
30  if not type(tool) in (list,tuple):
31  tool = (tool,)
32 
33  # only add once (allow silently)
34  if not self._useGlobalInstances:
35  # But if duplicates may not be the same Configurable instances,
36  # need to force the owner to prevent errors about public tools
37  # not in ToolSvc when old configuration fragments are imported
38  # in new configurations.
39  dups = [t for t in tool if t in self.getChildren()]
40  for t in dups:
41  t.setParent (self.name())
42  tool = [t for t in tool if t not in self.getChildren()]
43  if len(tool)==0: return self
44 
45  # this is only allowed for new-style AlgTool
46  for t in tool:
47  if not isinstance( t, Configurable.ConfigurableAlgTool ):
48  raise TypeError( '"%s" is not an AlgTool' %
49  (hasattr(t,'name') and t.name() or "This configurable" ) )
50 
51  super( GaudiCoreSvcConf.ToolSvc, self ).__iadd__( tool )
52 
53  return self
54 
55 GaudiCoreSvcConf.ToolSvc.__iadd__ = iadd
56 del iadd
57 
58 # When adding tools to ToolSvc they are stil considered "private" and thus would
59 # be copied. Overwrite the copyChild method to avoid this.
60 GaudiCoreSvcConf.ToolSvc.copyChild = lambda self, child : child
61 
62 
64  def getHandle( self ):
65  return None
66 
67  def getGaudiType ( self ):
68  return 'ServiceManager'
69 
70  def getType( self ):
71  return ''
72 
73  def getDlls ( self ):
74  return None
75 
76  def setup( self ):
77  children = self.getChildren()
78  for svc in children:
79  svc.setup()
80 
81  def __iadd__( self, service ):
82  # only add once (allow silently)
83  if service in self.getChildren():
84  return self
85 
86  # this is only allowed for new-style Services
87  if not isinstance( service, Configurable.ConfigurableService ):
88  msg = 'attempt to add an %s (%s) to the ServiceManager' %\
89  (type(service).__name__, service.name())
90  Logging.log.error( msg )
91  raise TypeError( msg )
92 
93  super( AthServiceManager, self ).__iadd__( service )
94 
95  # make all names explicitly known
96  global theApp
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  import os, sys
394 
395  if self._opts.config_only is True: # config-only but not storing to file
396  fn = None
397  elif self._opts.config_only:
398  fn = self._opts.config_only
399  else:
400  fn = 'TempAthenaConfig.' + str(os.getpid()) + '.pkl'
401 
402  if fn is not None:
403  Logging.log.info( "storing configuration in %s", fn )
404  from AthenaCommon import ConfigurationShelve
405  ConfigurationShelve.storeJobOptionsCatalogue( fn )
406  del ConfigurationShelve
407 
408  if self._opts.drop_reload:
409  # build the new set of options; replace the .py by the .pkl,
410  # and remove '-c arg'
411  del sys.argv[ sys.argv.index( '--drop-and-reload' ) ]
412  for arg in sys.argv[1:]:
413  if arg[-3:] == '.py':
414  del sys.argv[ sys.argv.index( arg ) ]
415 
416  elif arg == '-c':
417  idx = sys.argv.index( arg )
418  del sys.argv[ idx : idx + 2 ]
419 
420  # dump profiling
421  if self._opts.profile_python:
422  i = sys.argv.index( '--profile-python' )
423  del sys.argv[i:i+2] # delete argument and its value
424  from AthenaCommon.Debugging import dumpPythonProfile
425  dumpPythonProfile(self._opts.profile_python)
426 
427  # fire ourselves up anew
428  Logging.log.info( 'restarting athena.py from %s ... ', fn )
429  sys.argv.insert( 1, fn )
430  os.execvp( sys.argv[0], sys.argv )
431 
432  else:
433  # running config-only, so we're done
434  if self._opts.profile_python:
435  from AthenaCommon.Debugging import dumpPythonProfile
436  dumpPythonProfile(self._opts.profile_python)
437  Logging.log.info( "configuration complete, now exiting ... " )
438  os._exit( self._exitstate )
439 
440  # normal setup() (non drop-and-reload) continues here:
441 
442  # first we bring the real C++ application to life...
443  handle = self.getHandle()
444 
445  # temporarily disable GaudiAppMgr.Dlls and .CreateSvc calls
446  handle.__dict__['CreateSvc'] = self.__dict__.get('CreateSvc',
447  handle.CreateSvc)
448 
449  from GaudiPython import AppMgr as GaudiAppMgr
450 
451  # Likely the first (or at least the first important) place if we're
452  # running in compatibility mode where gaudimodule will be loaded. And
453  # even if not, still ok. Remove the GaudiPython exit handlers as to
454  # prevent them from clobbering Athena ones.
455  # Don't remove exit handlers for GaudiConfig2, or we can get spurious
456  # errors on exit.
457  import atexit
458  handler = None
459  if hasattr(atexit, '_exithandlers'):
460  for handler in atexit._exithandlers[:]:
461  if hasattr(handler[0], '__module__') and handler[0].__module__:
462  if 'audiPython' in handler[0].__module__: # removes GaudiPython handlers
463  #print ("removed ", handler[0].__module__)
464  atexit._exithandlers.remove( handler )
465  del handler, atexit
466 
467  def _setattr( self, n, v ):
468  if n == 'CreateSvc':
469  self.__dict__[n] = v
470  return
471  if n == 'Dlls':
472  return
473  return super( GaudiAppMgr, self ).__setattr__( n, v )
474  GaudiAppMgr_old_setattr = GaudiAppMgr.__setattr__
475  GaudiAppMgr.__setattr__ = _setattr
476  del _setattr
477 
478  def _getattr( self, n ):
479  if n == 'CreateSvc':
480  return self.__dict__[n]
481  return super( GaudiAppMgr, self ).__getattr__( n )
482  GaudiAppMgr_old_getattr = GaudiAppMgr.__getattr__
483  GaudiAppMgr.__getattr__ = _getattr
484  del _getattr
485 
486  # public tools (they're less likely to be instantiated early, and
487  # thus rely on job options load order)
488  self.toolSvc().setup()
489 
490  # new-style services (also sets up AuditorSvc)
491  self.serviceMgr().setup()
492 
493  # setup top-level job seq
494  master_seq = self.__build_master_sequence()
495  master_seq.setup()
496 
497  # tell self about the algs
498  handle.TopAlg = [ master_seq.getFullName() ]
499 
500  # setup output streams, and tell self about them
501  streams = self.__dict__[ '_streams' ]
502  streams.setup()
503  handle.OutStream = list(map( lambda x: x.getFullName(), streams.getChildren() ))
504 
505  # synchronize 'Dlls'
506  # note: we synchronize in the opposite direction wrt CreateSvc
507  super(AppMgr,self).__setattr__('Dlls', handle.Dlls)
508 
509  # synchronize 'CreateSvc'
510  svcMgr = self.serviceMgr()
511  _createSvc = handle.__dict__['CreateSvc']
512  if len(_createSvc) > 0 and \
513  _createSvc[0] != svcMgr.ToolSvc.getFullName():
514  _createSvc = [ svcMgr.ToolSvc.getFullName() ] + _createSvc
515 
516  if 'CreateSvc' in self.__dict__:
517  del self.__dict__['CreateSvc']
518  handle.__dict__['CreateSvc'] = [ s for s in _createSvc ]
519 
520  # reinstall old __?etattr__
521  del handle.__dict__['CreateSvc']
522  GaudiAppMgr.__getattr__ = GaudiAppMgr_old_getattr
523  GaudiAppMgr.__setattr__ = GaudiAppMgr_old_setattr
524 
525  # only now allow CreateSvc, so that there are no ordering problems
526  Logging.log.debug( 'Updating (C++) "CreateSvc" property...' )
527  handle.CreateSvc = _createSvc
528  Logging.log.debug( 'Updating (C++) "CreateSvc" property... [ok]' )
529 
530  # if requested, dump the current state of the configuration to an ASCII file
531  if self._opts and self._opts.config_dump_file:
532  import AthenaCommon.ConfigurationShelve as cs
533  cs.saveToAscii(self._opts.config_dump_file)
534 
535  return
536 
537  # redefines to take into acount setup of Configurables
538  def initialize( self ):
539  # Touch these types early, before dictionaries are loaded,
540  # to prevent spurious error messages from ROOT.
541  # See ATLASRECTS-3486.
542  from os import environ
543  environ['CLING_STANDARD_PCH'] = 'none' #See bug ROOT-10789
544  import cppyy
545  getattr(cppyy.gbl, 'vector<bool>')
546  getattr(cppyy.gbl, 'vector<float>')
547  getattr(cppyy.gbl, 'vector<unsigned short>')
548  getattr(cppyy.gbl, 'vector<short>')
549  getattr(cppyy.gbl, 'vector<unsigned long>')
550  getattr(cppyy.gbl, 'vector<ULong64_t>')
551  getattr(cppyy.gbl, 'map<string,string>')
552 
553  # build configuration
554  self.setup()
555 
556  # create C++-side AppMgr
557  from AthenaCommon.ConcurrencyFlags import jobproperties as jp
558  try:
559  # Set threaded flag to release the python GIL when we're in C++
560  is_threaded = jp.ConcurrencyFlags.NumThreads() > 0
561  self.getHandle()._appmgr.initialize.__release_gil__ = is_threaded
562  sc = self.getHandle().initialize()
563  if sc.isFailure():
564  self._exitstate = ExitCodes.INI_ALG_FAILURE
565  except Exception:
566  self._exitstate = ExitCodes.INI_ALG_EXCEPTION
567  raise
568  return sc
569 
570  def reinitialize( self ):
571  # since we're going to run python again, may have to re-enable to profiler
572  if self._opts and self._opts.profile_python:
573  import cProfile
574  cProfile._athena_python_profiler.enable()
575 
576  # first, rebuild configuration
577  self.setup()
578 
579  # ApplicationMgr::reinitialize does not reinit algorithms ...
580  for name in self.getHandle().TopAlg:
581  try:
582  parts = name.split('/')
583  algname = len(parts) == 2 and parts[1] or parts[0]
584  sc = self.algorithm( algname )._ialg.reinitialize()
585  if sc.isFailure() and not self._exitstate:
586  return sc
587  except AttributeError:
588  pass
589 
590  # normal reinitialize kicks services, tools left out ...
591  return self.getHandle().reinitialize()
592 
593  # redefine run to improve interface
594  def run( self, nEvt = None ):
595  # initialize as appropriate
596  if self.state() in ( AthAppMgr.State.OFFLINE,
597  AthAppMgr.State.CONFIGURED, ):
598  Logging.log.debug( 'Initializing application manager' )
599  sc = self.initialize()
600  else:
601  Logging.log.debug( 'Re-initializing application manager' )
602  sc = self.reinitialize()
603 
604  if sc.isFailure():
605  return sc
606 
607  sc = self.start()
608  if sc.isFailure():
609  return sc
610 
611  # determine number of events
612  if nEvt is None:
613  nEvt = self.EvtMax # late, as sequences may have changed it
614 
615  from AthenaCommon.Debugging import DbgStage
616  if DbgStage.value == "exec":
617  from .Debugging import hookDebugger
618  hookDebugger()
619 
620  # actual run (FIXME: capture beginRun() exceptions and failures, which is
621  # not currently supported by IEventProcessor interface)
622  from AthenaCommon.ConcurrencyFlags import jobproperties as jp
623  try:
624  # Set threaded flag to release the GIL on execution
625  executeRunMethod = self.getHandle()._evtpro.executeRun
626  executeRunMethod.__release_gil__ = jp.ConcurrencyFlags.NumThreads() > 0
627  sc = executeRunMethod(nEvt)
628  if sc.isFailure() and not self._exitstate:
629  self._exitstate = ExitCodes.EXE_ALG_FAILURE # likely, no guarantee
630  except Exception:
631  self._exitstate = ExitCodes.EXE_ALG_EXCEPTION # idem
632  raise
633 
634  sc = self.stop()
635  return sc
636 
637  def start( self ):
638  import GaudiPython
639  sc = GaudiPython.SUCCESS
640  if self.State.INITIALIZED == self.getHandle().FSMState():
641  Logging.log.debug( 'Starting application manager' )
642  sc = self.getHandle().start()
643  return sc
644 
645  def stop( self ):
646  import GaudiPython
647  sc = GaudiPython.SUCCESS
648  if self.State.RUNNING == self.getHandle().FSMState():
649  Logging.log.debug( 'Stopping application manager' )
650  sc = self.getHandle().stop()
651  return sc
652 
653  # forward call to underlying C++/app
654  def finalize( self ):
655  #stop theApp if not already done
656  sc = theApp.stop()
657  if sc.isFailure() and not self._exitstate:
658  self._exitstate = ExitCodes.FIN_ALG_FAILURE
659  try:
660  if not self._cppApp:
661  raise RuntimeError("C++ application not instantiated : Nothing to finalize !")
662  # Set threaded flag to release the GIL when finalizing in the c++
663  from AthenaCommon.ConcurrencyFlags import jobproperties as jp
664  finalizeMethod = self.getHandle()._appmgr.finalize
665  finalizeMethod.__release_gil__ = jp.ConcurrencyFlags.NumThreads() > 0
666  sc = finalizeMethod()
667  if sc.isFailure():
668  self._exitstate = ExitCodes.FIN_ALG_FAILURE
669  except Exception:
670  self._exitstate = ExitCodes.FIN_ALG_EXCEPTION
671  raise
672  return sc
673 
674  # convenience functions to move around events
675  def curEvent( self ):
676  try:
677  return self._evtSeek.curEvent()
678  except AttributeError:
679  raise TypeError( '%s does not support IEventSeek' % theApp.EventLoop )
680 
681  def seekEvent( self, n ):
682  try:
683  sc = self._evtSeek.seek( n )
684  # prevents any unchecked statuscode leftover
685  if not sc.isSuccess():
686  return sc
687  sc = self.nextEvent()
688  # prevents any unchecked statuscode leftover
689  if not sc.isSuccess():
690  return sc
691  return sc
692  except AttributeError:
693  raise TypeError( '%s does not support IEventSeek' % theApp.EventLoop )
694 
695  def seek( self, n ):
696  try:
697  sc = self._evtSeek.seek( n )
698  # prevents any unchecked statuscode leftover
699  if not sc.isSuccess():
700  return sc
701  return sc
702  except AttributeError:
703  raise TypeError( '%s does not support IEventSeek' % theApp.EventLoop )
704 
705  def nextEvent( self, nEvt = None ):
706  #start theApp if not already done
707  sc = theApp.start()
708  if sc.isFailure() and not self._exitstate:
709  self._exitstate = ExitCodes.INI_ALG_FAILURE
710 
711  if nEvt is None:
712  nEvt = self.curEvent() + 1
713 
714  try:
715  sc = self.getHandle()._evtpro.nextEvent( nEvt )
716  if sc.isFailure() and not self._exitstate:
717  self._exitstate = ExitCodes.EXE_ALG_FAILURE
718  except Exception:
719  self._exitstate = ExitCodes.EXE_ALG_EXCEPTION
720  raise
721 
722  return sc
723 
724  def size( self ):
725  try:
726  return self._evtSize.size()
727  except AttributeError:
728  raise TypeError( '%s does not support ICollectionSize' % theApp.EventLoop )
729 
730  def replacePFC(self):
731  """ if we have MP version of EventLoopMgr
732  replace PoolFileCatalog.xml by MP version"""
733  if (self.EventLoop == 'AthMpEventLoopMgr/EventLoopMgr'):
734  if os.path.exists("MP_PoolFileCatalog.xml"):
735  Logging.log.info ("replacing PoolFileCataloG.xml by MP version")
736  import shutil
737  shutil.copy2("MP_PoolFileCatalog.xml", "PoolFileCatalog.xml")
738 
739  # exit includes leaving python
740  def exit( self, code = None ):
741  try:
742  if self.state() > AthAppMgr.State.CONFIGURED:
743  sc1 = self.finalize()
744  self.replacePFC() #only for AthenaMP -> replace pfc by mp version
745  sc2 = self.getHandle()._appmgr.terminate()
746  if ( sc1.isFailure() or sc2.isFailure() ) and not self._exitstate:
747  self._exitstate = ExitCodes.FIN_ALG_FAILURE
748  except Exception:
749  if not self._exitstate:
750  self._exitstate = ExitCodes.FIN_ALG_EXCEPTION
751  import traceback
752  traceback.print_exc() # no re-raise to allow sys.exit next
753 
754  if self._opts.profile_python:
755  from AthenaCommon.Debugging import dumpPythonProfile
756  dumpPythonProfile(self._opts.profile_python)
757 
758  Logging.log.info( 'leaving with code %d: "%s"',
759  self._exitstate, ExitCodes.what( self._exitstate ) )
760  sys.exit( code is None and self._exitstate or code )
761 
762 
763 
764 theApp = AthAppMgr(
765  outputLevel = Logging.AthenaLogger.mapLevelLoggingToGaudi( Logging.log.getEffectiveLevel() )
766  )
767 
768 ServiceMgr = theApp.serviceMgr()
769 ServiceMgr += theApp.toolSvc()
770 ToolSvc = ServiceMgr.ToolSvc
771 
772 # convenience customization to deal with "Auditors" property
773 def iadd( self, config ):
774  super( GaudiCommonSvcConf.AuditorSvc, self ).__iadd__( config )
775 
776  if isinstance( config, Configurable.ConfigurableAuditor ):
777  if not config.getName() in self.Auditors and \
778  not config.getFullName() in self.Auditors:
779  self.Auditors += [ config.getFullName() ]
780 
781  return self
782 
783 GaudiCommonSvcConf.AuditorSvc.__iadd__ =iadd
784 del iadd
785 
786 
787 def _delattr( self, attr ):
788  try:
789  c = getattr( self, attr )
790 
791  try:
792  self.Auditors.remove( c.getFullName() )
793  except ValueError:
794  pass
795 
796  try:
797  self.Auditors.remove( c.getName() )
798  except ValueError:
799  pass
800 
801  except AttributeError:
802  pass
803 
804  super( GaudiCommonSvcConf.AuditorSvc, self ).__delattr__( attr )
805 
806 GaudiCommonSvcConf.AuditorSvc.__delattr__ = _delattr
807 del _delattr
808 
809 
810 # AuditorSvc globals
811 ServiceMgr += GaudiCommonSvcConf.AuditorSvc()
812 theAuditorSvc = ServiceMgr.AuditorSvc
813 
814 
815 
831 athMasterSeq = AlgSequence.AthSequencer( "AthMasterSeq" )
832 athCondSeq = AlgSequence.AthSequencer( "AthCondSeq" )
833 athAlgSeq = AlgSequence.AthSequencer( "AthAlgSeq" )
834 athOutSeq = AlgSequence.AthSequencer( "AthOutSeq" )
835 athBeginSeq = AlgSequence.AthSequencer( "AthBeginSeq" )
836 athEndSeq = AlgSequence.AthSequencer( "AthEndSeq" )
837 
838 topSequence = athAlgSeq # for backward compatibility
python.AlgSequence.AlgSequence
Definition: PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AlgSequence.py:19
python.AppMgr.AthServiceManager.getDlls
def getDlls(self)
Definition: AppMgr.py:73
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:538
python.AppMgr.AthAppMgr.getOutputStream
def getOutputStream(self, stream)
Definition: AppMgr.py:307
python.Configurable.ConfigurableAuditor
Definition: Configurable.py:957
python.AppMgr.AthAppMgr._evtSeek
def _evtSeek(self)
Definition: AppMgr.py:376
python.ConfigurableDb.getConfigurable
def getConfigurable(className, requester='', assumeCxxClass=True)
Definition: ConfigurableDb.py:208
python.AppMgr.AthAppMgr.replacePFC
def replacePFC(self)
Definition: AppMgr.py:730
python.AppMgr.AthAppMgr.__build_master_sequence
def __build_master_sequence(self)
Definition: AppMgr.py:191
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:272
python.AppMgr.AthAppMgr.removeOutputStream
def removeOutputStream(self, stream)
Definition: AppMgr.py:317
python.Configurable.ConfigurableService
Definition: Configurable.py:844
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.AppMgr.AthAppMgr.OutputLevel
OutputLevel
Definition: AppMgr.py:289
python.Debugging.dumpPythonProfile
def dumpPythonProfile(filename)
Definition: Debugging.py:94
python.AppMgr.AthAppMgr._cppApp
_cppApp
Definition: AppMgr.py:363
python.AppMgr.AthAppMgr.seekEvent
def seekEvent(self, n)
Definition: AppMgr.py:681
python.AppMgr.AthAppMgr.serviceMgr
def serviceMgr(self)
Definition: AppMgr.py:328
python.AppMgr.AthAppMgr.finalize
def finalize(self)
Definition: AppMgr.py:654
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
python.AppMgr.AthAppMgr.reinitialize
def reinitialize(self)
Definition: AppMgr.py:570
python.AppMgr.AthAppMgr.start
def start(self)
Definition: AppMgr.py:637
python.AppMgr.AthServiceManager.__iadd__
def __iadd__(self, service)
Definition: AppMgr.py:81
python.AlgSequence.dumpSequence
def dumpSequence(seq, indent=0)
Definition: Control/AthenaCommon/python/AlgSequence.py:144
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:28
python.AppMgr.AthAppMgr.stop
def stop(self)
Definition: AppMgr.py:645
python.AppMgr.AthAppMgr._exitstate
_exitstate
Definition: AppMgr.py:564
python.AppMgr.AthAppMgr.setOutputLevel
def setOutputLevel(self, outputLevel)
Definition: AppMgr.py:286
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:64
python.AppMgr.AthAppMgr.getHandle
def getHandle(self, selfOptions={})
Definition: AppMgr.py:345
python.AppMgr.AthAppMgr.curEvent
def curEvent(self)
Definition: AppMgr.py:675
python.AppMgr.AthAppMgr.nextEvent
def nextEvent(self, nEvt=None)
Definition: AppMgr.py:705
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:733
python.AppMgr.AthAppMgr.exit
def exit(self, code=None)
Definition: AppMgr.py:740
python.AppMgr.AthAppMgr.size
def size(self)
Definition: AppMgr.py:724
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.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:159
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:63
python.AppMgr.AthAppMgr.seek
def seek(self, n)
Definition: AppMgr.py:695
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:790
python.AppMgr.AthAppMgr.toolSvc
def toolSvc(self, name='ToolSvc')
Definition: AppMgr.py:321
python.AppMgr.AthServiceManager.getType
def getType(self)
Definition: AppMgr.py:70
python.AnaAlgSequence.getFullName
def getFullName(comp)
Definition: AnaAlgSequence.py:12
python.AppMgr.AthServiceManager.setup
def setup(self)
Definition: AppMgr.py:76
python.AppMgr.AthServiceManager.getGaudiType
def getGaudiType(self)
Definition: AppMgr.py:67
python.AppMgr._delattr
def _delattr(self, attr)
Definition: AppMgr.py:787
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:594
python.AppMgr.AthAppMgr.addOutputStream
def addOutputStream(self, stream)
Definition: AppMgr.py:303