562 def run(self, maxEvents=None):
563 """
564 This follows the same pattern as PSC (Psc.cxx):
565 1. Create ApplicationMgr via BootstrapHelper
566 2. Set JobOptionsSvcType, JobOptionsType, JobOptionsPath
567 3. configure() -> initialize() -> prepareForStart() -> start() ->
568 hltUpdateAfterFork() -> run() -> stop() -> finalize() -> terminate()
569 """
570 from Gaudi.Main import BootstrapHelper
571
572
573 if self.job_options_type == "FILE" and self.properties is None:
574 with open(self.job_options_path, 'r') as f:
575 jocat = json.load(f)
576 self.properties = jocat.get('properties', {})
577
578 bsh = BootstrapHelper()
579 app = bsh.createApplicationMgr()
580 self._app = app
581
582
583 if self.job_options_type == "FILE" and self.properties:
584 app_props = self.properties.
get(
'ApplicationMgr', {})
585 for k, v in app_props.items():
586 if k not in ('JobOptionsSvcType', 'JobOptionsType', 'JobOptionsPath'):
587 log.debug("Setting ApplicationMgr.%s = %s", k, v)
588 app.setProperty(k, str(v) if not isinstance(v, str) else v)
589
590
591 log.info("Configuring TrigConf::JobOptionsSvc with TYPE=%s, PATH=%s",
592 self.job_options_type, self.job_options_path)
593 app.setProperty("JobOptionsSvcType", "TrigConf::JobOptionsSvc")
594 app.setProperty("JobOptionsType", self.job_options_type)
595 app.setProperty("JobOptionsPath", self.job_options_path)
596
597
598 app.configure()
599
600
601
602 if maxEvents is not None:
603 log.info("Setting EvtMax=%d (overriding DB value)", maxEvents)
604 app.setProperty('EvtMax', str(maxEvents))
605
606
607
608 from GaudiPython.Bindings import iProperty
609
610
611 if maxEvents is not None:
612 log.info("Setting EFInterfaceSvc.NumEvents=%d (overriding DB value)", maxEvents)
613 iProperty("EFInterfaceSvc").NumEvents = maxEvents
614
615
616 log.info("Setting threading: ThreadPoolSize=%d, NSlots=%d", self.num_threads, self.num_slots)
617 iProperty("AvalancheSchedulerSvc").ThreadPoolSize = self.num_threads
618 iProperty("EventDataSvc").NSlots = self.num_slots
619
620
621 if self.ef_files:
622 log.info("Setting EFInterfaceSvc.Files = %s", self.ef_files)
623 iProperty("EFInterfaceSvc").Files = self.ef_files
624
625
626
627 from TrigPSC import PscConfig
628 if PscConfig.forcePSK:
629 log.info("PscConfig.forcePSK is set - configuring HLTPrescaleCondAlg to read from DB instead of COOL")
630 iProperty("HLTPrescaleCondAlg").Source = "DB"
631
632
633
634 conditions_run = self.run_params.
get(
'conditions_run')
635 if conditions_run is not None:
636 log.info("Setting HltEventLoopMgr.forceRunNumber=%d for conditions lookup", conditions_run)
637 iProperty("HltEventLoopMgr").forceRunNumber = conditions_run
638
639
640 sc = app.initialize()
641 if not sc.isSuccess():
642 log.error("Failed to initialize AppMgr")
643 return sc
644
645
646 try:
647 from TrigServices.TrigServicesHelper import TrigServicesHelper
649 except ImportError as e:
650 log.error("TrigServicesHelper not available: %s", e)
651 log.error("Cannot proceed without TrigServicesHelper - required for HLTEventLoopMgr lifecycle")
652 raise RuntimeError("TrigServicesHelper not available") from e
653
654
655 try:
656 run_number = self.run_params['run_number']
657 det_mask = self.run_params['detector_mask']
658 sor_time = self.run_params['sor_time']
659 solenoid_current = self.run_params['solenoid_current']
660 toroids_current = self.run_params['toroids_current']
661
662 log.info("Calling prepareForStart with run=%d, det_mask=0x%s, sor_time=%s",
663 run_number, det_mask, sor_time)
664
665 success = helper.prepareForStart(
666 run_number=run_number,
667 det_mask=det_mask,
668 sor_time=sor_time,
669 solenoid_current=solenoid_current,
670 toroids_current=toroids_current
671 )
672 if not success:
673 log.error("prepareForStart failed")
674 raise RuntimeError("prepareForStart failed")
675 log.info("prepareForStart completed successfully")
676 except Exception as e:
677 log.error("Error calling prepareForStart: %s", e)
678 traceback.print_exc()
679 raise
680
681
682 sc = app.start()
683 if not sc.isSuccess():
684 log.error("Failed to start AppMgr")
685 return sc
686
687
688
689 try:
690 log.info("Calling prepareForRun to initialize COOL folder helper")
691 success = helper.prepareForRun()
692 if not success:
693 log.error("prepareForRun failed")
694 raise RuntimeError("prepareForRun failed")
695 log.info("prepareForRun completed successfully")
696 except Exception as e:
697 log.error("Error calling prepareForRun: %s", e)
698 traceback.print_exc()
699 raise
700
701
702
703 try:
704 log.info("Calling hltUpdateAfterFork to initialize scheduler (worker_id=1)")
705 success = helper.hltUpdateAfterFork(worker_id=1)
706 if not success:
707 log.error("hltUpdateAfterFork failed")
708 raise RuntimeError("hltUpdateAfterFork failed")
709 log.info("hltUpdateAfterFork completed successfully")
710 except Exception as e:
711 log.error("Error calling hltUpdateAfterFork: %s", e)
712 traceback.print_exc()
713 raise
714
715
716
717 nevt = maxEvents if maxEvents is not None else -1
718 sc = app.run(nevt)
719
720 if not sc.isSuccess():
721 log.error("Failure running application")
722 return sc
723
724
725 sc = app.stop()
726 if not sc.isSuccess():
727 log.error("Failed to stop AppMgr")
728 return sc
729
730
731 sc = app.finalize()
732 if not sc.isSuccess():
733 log.error("Failed to finalize AppMgr")
734 return sc
735
736
737 sc = app.terminate()
738 return sc
739
740
Helper class to call ITrigEventLoopMgr methods from Python.
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
int run(int argc, char *argv[])