19#include "eformat/ROBFragment.h"
27#include "GaudiKernel/Bootstrap.h"
28#include "GaudiKernel/IAppMgrUI.h"
29#include "GaudiKernel/IEventProcessor.h"
30#include "GaudiKernel/IProperty.h"
31#include "GaudiKernel/IService.h"
32#include "Gaudi/Interfaces/IOptionsSvc.h"
33#include "GaudiKernel/IAlgManager.h"
34#include "GaudiKernel/IAlgorithm.h"
35#include "GaudiKernel/ServiceHandle.h"
36#include "Gaudi/Property.h"
37#include "GaudiKernel/System.h"
47#include <boost/property_tree/xml_parser.hpp>
49using namespace boost::property_tree;
56 using T = ptree::key_type;
57 std::ostringstream oss;
58 xml_parser::write_xml(oss, p,
59 xml_parser::xml_writer_make_settings<T>(
' ', 2));
82 ROOT::EnableThreadSafety();
89 catch(
const std::exception& e)
96 ERS_LOG(
"---> Dump of config cache: \n" <<
m_config->dumpOptions() );
97 ERS_LOG(
"---> Pesa JobOptions file is = " <<
m_config->getOption(
"JOBOPTIONSPATH") );
102 ERS_DEBUG(1,
"---> Create Pesa Application Manager");
112 ERS_DEBUG(1,
"---> Configure Pesa Property Manager");
114 if( !propMgr.isValid() ) {
115 ERS_PSC_ERROR(
"Error retrieving IProperty interface of ApplicationMgr");
121 sc = propMgr->setProperty(
"JobOptionsSvcType",
m_config->getOption(
"JOBOPTIONSSVCTYPE"));
122 if (
sc.isFailure()) {
128 sc = propMgr->setProperty(
"JobOptionsType",
m_config->getOption(
"JOBOPTIONSTYPE"));
129 if (
sc.isFailure()) {
135 sc = propMgr->setProperty(
"JobOptionsPath",
m_config->getOption(
"JOBOPTIONSPATH") );
136 if (
sc.isFailure()) {
142 sc = propMgr->setProperty(
"MessageSvcType",
m_config->getOption(
"MESSAGESVCTYPE"));
143 if (
sc.isFailure()) {
152 bool jobOptConfig, needPython;
153 if (
m_config->getOption(
"JOBOPTIONSTYPE") ==
"NONE" ) {
154 jobOptConfig = needPython =
true;
156 else if (
m_config->getOption(
"JOBOPTIONSTYPE") ==
"DB" ||
157 m_config->getOption(
"JOBOPTIONSTYPE") ==
"FILE") {
158 jobOptConfig = needPython =
false;
159 if ( (
m_config->getOption(
"PRECOMMAND")!=
"") || (
m_config->getOption(
"POSTCOMMAND")!=
"") ) {
162 if (
m_config->didUserSetLogLevel()) {
167 ERS_PSC_ERROR(
"Unsupported configuration method \"" <<
m_config->getOption(
"JOBOPTIONSTYPE") <<
"\"");
172 if ( jobOptConfig || needPython ) {
178 if ( ! Py_IsInitialized() ) {
179 ERS_DEBUG(1,
"Initializing Python interpreter");
182 PyConfig_InitPythonConfig (&
config);
183 PyStatus status = PyConfig_SetBytesArgv (&
config, System::argc(), System::argv());
184 if (PyStatus_Exception (status)) {
189 status = Py_InitializeFromConfig (&
config);
190 if (PyStatus_Exception (status)) {
201 if ( ! Py_IsInitialized() ) {
208 ERS_DEBUG(1,
"Python interpreter already initialized");
213 PyObject* pModule = PyImport_ImportModule(
"TrigPSC.PscConfig");
215 PyObject* optmap = PyObject_GetAttrString(pModule,
"optmap");
217 std::map<std::string,std::string>::const_iterator iter;
219 PyObject* v = PyUnicode_FromString(iter->second.c_str());
220 std::vector<char> writable(iter->first.size() + 1);
221 std::copy(iter->first.begin(), iter->first.end(), writable.begin());
222 PyMapping_SetItemString(optmap, &writable[0], v);
227 ERS_DEBUG(1,
"Could not import TrigPSC.PscConfig.optmap");
233 if ( jobOptConfig ) {
235 std::string pyBasicFile =
m_config->getOption(
"PYTHONSETUPFILE") ;
242 if ( !jobOptConfig ) {
248 std::string cmd =
m_config->getOption(
"PRECOMMAND");
250 ERS_LOG(
"Running pre-configure command '" << cmd <<
"'");
258 ERS_DEBUG(1,
"Configure ApplicationMgr from database.");
260 if(
sc.isFailure() ) {
268 std::string pyBasicFile =
m_config->getOption(
"PYTHONSETUPFILE",
true) ;
269 if ( !pyBasicFile.empty() ) {
281 PyObject* pModule = PyImport_ImportModule(
"TrigPSC.PscConfig");
283 PyObject* pInteractive = PyObject_GetAttrString(pModule,
"interactive");
284 if ( pInteractive && PyBool_Check(pInteractive) ) {
286 ERS_DEBUG(1,
"TrigPSC.PscConfig.interactive = " <<
m_interactive);
287 Py_DECREF(pInteractive);
290 ERS_DEBUG(1,
"Could not read TrigPSC.PscConfig.interactive");
295 ERS_DEBUG(1,
"Could not import TrigPSC.PscConfig");
301 ERS_DEBUG(1,
"Configured ApplicationMgr in state: " <<
m_pesaAppMgr->FSMState());
304 SmartIF<IProperty> jos_propif{&(*jobOptionSvc)};
306 jos_propif->setProperty(
"OutputLevel",
m_config->getLogLevelAsNumStr()).ignore();
311 auto props = std::map<std::string,std::string>{
312 {
"DF_PartitionName",
"DF_PARTITION_NAME"},
313 {
"DF_ApplicationName",
"DF_APPLICATIONNAME"},
314 {
"DF_MachineName",
"DF_MACHINE_NAME"},
315 {
"DF_Ppid",
"DF_PPID"},
316 {
"DF_Pid",
"DF_PID"},
317 {
"DF_HostId",
"DF_HOST_ID"},
318 {
"DF_RandomSeed",
"DF_RANDOM_SEED"},
319 {
"DF_NumberOfWorkers",
"NPROCS"}
325 if (
m_config->enabled_robs.size() != 0 ) {
326 jobOptionSvc->set(
"DataFlowConfig.DF_Enabled_ROB_IDs",
327 Gaudi::Utils::toString<std::vector<uint32_t>>(
m_config->enabled_robs));
328 ERS_DEBUG(1,
"psc::Psc::configure: Wrote configuration for enabled ROBs in JobOptions Catalogue: "
329 <<
" number of ROB IDs read from OKS = " <<
m_config->enabled_robs.size());
333 if (
m_config->enabled_SubDets.size() != 0 ) {
334 jobOptionSvc->set(
"DataFlowConfig.DF_Enabled_SubDet_IDs",
335 Gaudi::Utils::toString<std::vector<uint32_t>>(
m_config->enabled_SubDets));
336 ERS_DEBUG(1,
"psc::Psc::configure: Wrote configuration for enabled sub detectors in JobOptions Catalogue: "
337 <<
" number of Sub Det IDs read from OKS = " <<
m_config->enabled_SubDets.size());
341 if (std::string opt =
m_config->getOption(
"MAXEVENTSIZEMB"); !opt.empty()) {
342 jobOptionSvc->set(
"DataFlowConfig.DF_MaxEventSizeMB", opt);
343 ERS_DEBUG(1,
"psc::Psc::configure: Wrote DF_MaxEventSizeMB=" << opt <<
" in JobOptions Catalogue");
347 if ( (
m_config->getOption(
"MUONCALBUFFERNAME") !=
"NONE") && (
m_config->getOption(
"MUONCALBUFFERNAME") !=
"") ) {
348 jobOptionSvc->set(
"MuonHltCalibrationConfig.MuonCalBufferName",
m_config->getOption(
"MUONCALBUFFERNAME"));
349 jobOptionSvc->set(
"MuonHltCalibrationConfig.MuonCalBufferSize",
m_config->getOption(
"MUONCALBUFFERSIZE"));
351 ERS_DEBUG(1,
"psc::Psc::configure: Wrote configuration for HLT Muon Calibration in JobOptions Catalogue: "
352 <<
" MuonCalBufferName = " <<
m_config->getOption(
"MUONCALBUFFERNAME")
353 <<
" MuonCalBufferSize = " <<
m_config->getOption(
"MUONCALBUFFERSIZE") );
359 if ( !jobOptConfig ) {
361 std::string cmd =
m_config->getOption(
"POSTCOMMAND");
363 ERS_LOG(
"Running post-configure command '" << cmd <<
"'");
383 ERS_DEBUG(1,
"Initialize ApplicationMgr : " <<
m_pesaAppMgr->FSMState() <<
384 ", Status = " <<
sc.getCode());
385 if(
sc.isFailure() ) {
386 ERS_PSC_ERROR(
"Error while initializing the ApplicationMgr");
398 if( !propMgr.isValid() ) {
399 ERS_PSC_ERROR(
"Error retrieving IProperty interface of ApplicationMgr");
405 sc = propMgr->getProperty(
"EventLoop", value );
406 if(
sc.isFailure() ) {
407 ERS_PSC_ERROR(
"Error while retrieving Property \'EventLoop\'.");
410 value.find_last_of(
"\"")-value.find_first_of(
"\"")-1) ;
440 ERS_DEBUG(1,
"psc::Psc::prepareForRun ptree:\n" <<
to_string(args));
445 m_run_number = args.get<uint32_t>(
"RunParams.run_number");
447 catch(
const ptree_bad_path & e)
449 ERS_PSC_ERROR(
"Bad ptree path: \"" << e.path<ptree::path_type>().dump()
450 <<
"\" - " << e.what())
453 catch(
const ptree_bad_data & e)
455 ERS_PSC_ERROR(
"Bad ptree data: \"" << e.data<ptree::data_type>() <<
"\" - "
462 "prepareForStart").isSuccess()) {
468 if( !
sc.isSuccess() ) {
469 ERS_PSC_ERROR(
"Error executing ApplicationMgr::start() command ");
483 if (ret.isSuccess()) {
484 return StatusCode (StatusCode::SUCCESS);
492 if ( Py_IsInitialized() ) {
495 ERS_DEBUG(1,
"Pre-fork initialization of Python interpreter");
519 if ( !
sc.isSuccess() ) {
520 ERS_PSC_ERROR(
"Error executing stop(void) for ApplicationMgr");
527 SmartIF<IService> histsvc =
m_svcLoc->service(
"THistSvc",
false);
528 if (histsvc.isValid()) {
529 ERS_LOG(
"Finalize THistSvc to save histograms");
530 if (histsvc->finalize().isFailure()) {
546 ERS_DEBUG(1,
"Finalize ApplicationMgr: " <<
m_pesaAppMgr->FSMState()
547 <<
". Status : " <<
sc.getCode());
549 if(
sc.isFailure() ) {
556 ERS_DEBUG(1,
"Terminate ApplicationMgr: " <<
m_pesaAppMgr->FSMState()
557 <<
". Status : " <<
sc.getCode());
559 if (
sc.isFailure() ) {
560 ERS_PSC_ERROR(
"Error while terminating the ApplicationMgr.");
565 Gaudi::setInstance(
static_cast<IAppMgrUI*
>(
nullptr));
611 ERS_DEBUG(1,
"psc::Psc::hltUserCommand ptree:\n" <<
to_string(args));
619 ERS_LOG(
"psc::Psc::doEventLoop: start of doEventLoop()");
624 auto exec = [](IEventProcessor * mgr)
625 {
return mgr->executeRun(-1);};
628 catch(
const ers::Issue& e)
630 ERS_PSC_ERROR(
"Caught an unexpected ers::Issue: '" << e.what() <<
"'");
631 sc = StatusCode::FAILURE;
633 catch(
const std::exception& e)
635 ERS_PSC_ERROR(
"Caught an unexpected std::exception: '" << e.what() <<
"'");
636 sc = StatusCode::FAILURE;
641 sc = StatusCode::FAILURE;
643 if (
sc.isFailure()) {
647 ERS_LOG(
"psc::Psc::doEventLoop: end of doEventLoop()");
655 ROOT::EnableThreadSafety();
656 if ( Py_IsInitialized() ) {
657 ERS_DEBUG(1,
"Post-fork initialization of Python interpreter");
658 PyOS_AfterFork_Child();
663 ERS_DEBUG(1,
"Releasing Python GIL");
669 ERS_LOG(
"Individualizing DF properties");
673 {
"DF_Ppid",
"DF_PPID"},
674 {
"DF_RandomSeed",
"DF_RANDOM_SEED"},
675 {
"DF_WorkerId",
"DF_WORKER_ID"},
676 {
"DF_NumberOfWorkers",
"DF_NUMBER_OF_WORKERS"},
677 {
"DF_ApplicationName",
"DF_APPLICATIONNAME"}})
682 {
return mgr->hltUpdateAfterFork(args);};
700 for(
const auto& prop : name_tr_table)
702 const auto& val =
m_config->getOption(prop.second);
703 jobOptionSvc->set(
"DataFlowConfig."+prop.first, val);
704 ERS_DEBUG(0,
"Wrote configuration for Data Flow in JobOptions Catalogue: "
705 << prop.first <<
" = " << val);
714 if (!propMgr.isValid()) {
715 ERS_PSC_ERROR(
"Error retrieving IProperty interface of ApplicationMgr");
718 std::string eventLoopMgrName;
719 if (propMgr->getProperty(
"EventLoop", eventLoopMgrName).isFailure()) {
720 ERS_PSC_ERROR(
"Error while retrieving the property ApplicationMgr.EventLoop");
727 std::string opt =
m_config->getOption(
"HARDTIMEOUT");
729 jobOptionSvc->set(eventLoopMgrName+
".HardTimeout", opt);
732 ERS_PSC_ERROR(
"Failed to get the HARDTIMEOUT property from the configuration tree");
736 opt =
m_config->getOption(
"SOFTTIMEOUTFRACTION");
738 jobOptionSvc->set(eventLoopMgrName+
".SoftTimeoutFraction", opt);
741 ERS_PSC_ERROR(
"Failed to get the SOFTTIMEOUTFRACTION property from the configuration tree");
749 opt =
m_config->getOption(
"NEVENTSLOTS");
751 jobOptionSvc->set(
"EventDataSvc.NSlots", opt);
754 ERS_PSC_ERROR(
"Failed to get the NEVENTSLOTS property from the configuration tree");
758 opt =
m_config->getOption(
"NTHREADS");
760 jobOptionSvc->set(
"AvalancheSchedulerSvc.ThreadPoolSize", opt);
763 ERS_PSC_ERROR(
"Failed to get the NTHREADS property from the configuration tree");
773 const std::string& name)
const
778 return StatusCode::FAILURE;
782 StatusCode
sc = func(processingMgr);
785 ERS_PSC_ERROR(
"Error executing " << name <<
" for EventLoopMgr = '"
Some helpers for the PSC.
boost::property_tree::ptree ptree
#define ERS_PSC_ERROR(message)
HLT Pesa Steering Controller.
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
EventLoopMgr interface implemented by the HLT event loop manager.
bool setAthenaProperties()
uint32_t m_run_number
(initial) run number to be used for this run
bool setDFProperties(const std::map< std::string, std::string > &name_tr_table)
virtual bool unconfigure(const boost::property_tree::ptree &args) override
Unconfigures the framework, releasing all acquired resources.
int m_workerID
worker ID (0=mother)
virtual ~Psc()
Virtual desctuctor.
virtual bool hltUserCommand(const boost::property_tree::ptree &args) override
Calls the HLT framework to notify it that a user command has arrived.
virtual bool configure(const boost::property_tree::ptree &config) override
Configures the framework.
bool m_interactive
Running in interactive mode (athenaHLT)
IAppMgrUI * m_pesaAppMgr
Application Manager.
bool doAppMgrFinalize()
Finalize the application manager.
bool doAppMgrInit()
Initialize the application manager.
virtual bool prepareWorker(const boost::property_tree::ptree &args) override
Method which can be called for a worker to perform the necessary steps to set unique worker IDs and a...
virtual bool disconnect(const boost::property_tree::ptree &args) override
Disconnects the framework.
virtual bool publishStatistics(const boost::property_tree::ptree &args) override
Calls the HLT framework to publish statistics, after the run has finished.
std::string m_nameEventLoopMgr
name of the event loop manager
virtual bool prepareForRun(const boost::property_tree::ptree &args) override
prepares the HLT framework for a run
virtual bool connect(const boost::property_tree::ptree &args) override
Connects the framework.
virtual bool stopRun(const boost::property_tree::ptree &args) override
stops the HLT framework without re-configuring
SmartIF< ISvcLocator > m_svcLoc
Service locator handle.
StatusCode callOnEventLoopMgr(std::function< StatusCode(T *)> func, const std::string &name) const
Utility method to call a method on the event loop manager.
virtual bool finalizeWorker(const boost::property_tree::ptree &args) override
Method which can be called for a worker to perform a cleanup before the worker gets killed.
virtual bool doEventLoop() override
Starts the HLT event loop.
std::unique_ptr< psc::Config > m_config
Config derived from ptree.
bool execFile(const std::string &pyFileName)
Execute a python file (via include or import)
bool execPython(const std::string &pyCmd)
Execute a python command in the python interpreter.