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