ATLAS Offline Software
Loading...
Searching...
No Matches
TrigServicesHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
12
13#include <sstream>
14#include <string>
15#include <memory>
16#include <unistd.h> // for getpid()
17
18#include <boost/python.hpp>
19#include <boost/property_tree/ptree.hpp>
20
21#include "GaudiKernel/ISvcLocator.h"
22#include "GaudiKernel/IProperty.h"
23#include "GaudiKernel/SmartIF.h"
24#include "GaudiKernel/Bootstrap.h"
25#include "Gaudi/Interfaces/IOptionsSvc.h"
26
28
29namespace {
30
34boost::property_tree::ptree buildPrepareForStartPtree(
35 uint32_t run_number,
36 const std::string& det_mask,
37 const std::string& sor_time,
38 uint32_t lb_number,
39 uint32_t beam_type,
40 uint32_t beam_energy,
41 float toroids_current,
42 float solenoid_current,
43 const std::string& run_type,
44 uint32_t trigger_type,
45 bool recording_enabled)
46{
47 boost::property_tree::ptree pt;
48
49 // RunParams section
50 boost::property_tree::ptree& runParams = pt.add_child("RunParams", boost::property_tree::ptree());
51 runParams.put("run_number", run_number);
52 runParams.put("max_events", 0);
53 runParams.put("recording_enabled", recording_enabled ? 1 : 0);
54 runParams.put("trigger_type", trigger_type);
55 runParams.put("run_type", run_type);
56 runParams.put("det_mask", det_mask);
57 runParams.put("beam_type", beam_type);
58 runParams.put("beam_energy", beam_energy);
59 runParams.put("stream", "");
60 runParams.put("lumiblock", lb_number);
61 runParams.put("filename_tag", "");
62 runParams.put("T0_project_tag", "");
63 runParams.put("timeSOR", sor_time);
64 runParams.put("timeEOR", "1/1/70 01:00:00");
65 runParams.put("totalTime", 0);
66
67 // Magnets section
68 boost::property_tree::ptree& magnets = pt.add_child("Magnets", boost::property_tree::ptree());
69
70 boost::property_tree::ptree& toroidsCurrent = magnets.add_child("ToroidsCurrent", boost::property_tree::ptree());
71 toroidsCurrent.put("value", toroids_current);
72 toroidsCurrent.put("ts", sor_time);
73
74 boost::property_tree::ptree& solenoidCurrent = magnets.add_child("SolenoidCurrent", boost::property_tree::ptree());
75 solenoidCurrent.put("value", solenoid_current);
76 solenoidCurrent.put("ts", sor_time);
77
78 return pt;
79}
80
81} // anonymous namespace
82
83
89public:
90 TrigServicesHelper() = default;
92
108 uint32_t run_number,
109 const std::string& det_mask,
110 const std::string& sor_time,
111 uint32_t lb_number = 0,
112 uint32_t beam_type = 0,
113 uint32_t beam_energy = 0,
114 float toroids_current = 20400.0f,
115 float solenoid_current = 7730.0f,
116 const std::string& run_type = "Physics",
117 uint32_t trigger_type = 0,
118 bool recording_enabled = false,
119 const std::string& event_loop_name = "HltEventLoopMgr")
120 {
121 // Build the ptree directly
122 boost::property_tree::ptree pt = buildPrepareForStartPtree(
123 run_number, det_mask, sor_time, lb_number,
124 beam_type, beam_energy, toroids_current, solenoid_current,
125 run_type, trigger_type, recording_enabled);
126
127 // Get the service locator
128 ISvcLocator* svcLoc = Gaudi::svcLocator();
129 if (!svcLoc) {
130 std::cerr << "TrigServicesHelper: Failed to get ISvcLocator" << std::endl;
131 return false;
132 }
133
134 // Get the EventLoopMgr service (use template version that returns SmartIF directly)
135 auto evtLoopMgr = svcLoc->service<ITrigEventLoopMgr>(event_loop_name);
136 if (!evtLoopMgr) {
137 std::cerr << "TrigServicesHelper: Failed to retrieve ITrigEventLoopMgr '"
138 << event_loop_name << "'" << std::endl;
139 return false;
140 }
141
142 // Call prepareForStart
143 std::cout << "TrigServicesHelper: Calling prepareForStart on " << event_loop_name << std::endl;
144 StatusCode sc = evtLoopMgr->prepareForStart(pt);
145
146 if (sc.isFailure()) {
147 std::cerr << "TrigServicesHelper: prepareForStart failed" << std::endl;
148 return false;
149 }
150
151 std::cout << "TrigServicesHelper: prepareForStart completed successfully" << std::endl;
152 return true;
153 }
154
164 bool prepareForRun(const std::string& event_loop_name = "HltEventLoopMgr")
165 {
166 // Get the service locator
167 ISvcLocator* svcLoc = Gaudi::svcLocator();
168 if (!svcLoc) {
169 std::cerr << "TrigServicesHelper: Failed to get ISvcLocator" << std::endl;
170 return false;
171 }
172
173 // Get the EventLoopMgr service
174 auto evtLoopMgr = svcLoc->service<ITrigEventLoopMgr>(event_loop_name);
175 if (!evtLoopMgr) {
176 std::cerr << "TrigServicesHelper: Failed to retrieve ITrigEventLoopMgr '"
177 << event_loop_name << "'" << std::endl;
178 return false;
179 }
180
181 // Build an empty ptree (prepareForRun doesn't use it currently)
182 boost::property_tree::ptree pt;
183
184 // Call prepareForRun
185 std::cout << "TrigServicesHelper: Calling prepareForRun on " << event_loop_name << std::endl;
186 StatusCode sc = evtLoopMgr->prepareForRun(pt);
187
188 if (sc.isFailure()) {
189 std::cerr << "TrigServicesHelper: prepareForRun failed" << std::endl;
190 return false;
191 }
192
193 std::cout << "TrigServicesHelper: prepareForRun completed successfully" << std::endl;
194 return true;
195 }
196
209 bool hltUpdateAfterFork(int worker_id = 1,
210 int worker_pid = -1,
211 const std::string& event_loop_name = "HltEventLoopMgr")
212 {
213 // Use current PID if not specified
214 if (worker_pid < 0) {
215 worker_pid = getpid();
216 }
217
218 // Get the service locator
219 ISvcLocator* svcLoc = Gaudi::svcLocator();
220 if (!svcLoc) {
221 std::cerr << "TrigServicesHelper: Failed to get ISvcLocator" << std::endl;
222 return false;
223 }
224
225 // Set DataFlow properties via JobOptionsSvc so updateDFProps() can read them
226 // HltEventLoopMgr::updateDFProps() reads from "DataFlowConfig.DF_*" properties
227 auto jobOptSvc = svcLoc->service<Gaudi::Interfaces::IOptionsSvc>("JobOptionsSvc");
228 if (!jobOptSvc) {
229 std::cerr << "TrigServicesHelper: Failed to get JobOptionsSvc" << std::endl;
230 return false;
231 }
232
233 // Set worker ID > 0 to avoid mother process behavior in stop()
234 jobOptSvc->set("DataFlowConfig.DF_WorkerId", std::to_string(worker_id));
235 jobOptSvc->set("DataFlowConfig.DF_Pid", std::to_string(worker_pid));
236 jobOptSvc->set("DataFlowConfig.DF_ApplicationName", "athenaEF");
237
238 std::cout << "TrigServicesHelper: Set DataFlowConfig properties (WorkerId="
239 << worker_id << ", Pid=" << worker_pid << ")" << std::endl;
240
241 // Build an empty ptree - the actual values are read from JobOptionsSvc
242 boost::property_tree::ptree pt;
243
244 // Get the EventLoopMgr service
245 auto evtLoopMgr = svcLoc->service<ITrigEventLoopMgr>(event_loop_name);
246 if (!evtLoopMgr) {
247 std::cerr << "TrigServicesHelper: Failed to retrieve ITrigEventLoopMgr '"
248 << event_loop_name << "'" << std::endl;
249 return false;
250 }
251
252 // Call hltUpdateAfterFork
253 std::cout << "TrigServicesHelper: Calling hltUpdateAfterFork on " << event_loop_name << std::endl;
254 StatusCode sc = evtLoopMgr->hltUpdateAfterFork(pt);
255
256 if (sc.isFailure()) {
257 std::cerr << "TrigServicesHelper: hltUpdateAfterFork failed" << std::endl;
258 return false;
259 }
260
261 std::cout << "TrigServicesHelper: hltUpdateAfterFork completed successfully" << std::endl;
262 return true;
263 }
264};
265
266
267// Boost.Python module definition
268BOOST_PYTHON_MODULE(libTrigServicesHelper)
269{
270 using namespace boost::python;
271
272 class_<TrigServicesHelper>("TrigServicesHelper")
273 .def("prepareForStart", &TrigServicesHelper::prepareForStart,
274 (arg("run_number"),
275 arg("det_mask"),
276 arg("sor_time"),
277 arg("lb_number") = 0,
278 arg("beam_type") = 0,
279 arg("beam_energy") = 0,
280 arg("toroids_current") = 20400.0f,
281 arg("solenoid_current") = 7730.0f,
282 arg("run_type") = "Physics",
283 arg("trigger_type") = 0,
284 arg("recording_enabled") = false,
285 arg("event_loop_name") = "HltEventLoopMgr"),
286 "Call prepareForStart on HltEventLoopMgr with individual parameters")
287 .def("prepareForRun", &TrigServicesHelper::prepareForRun,
288 (arg("event_loop_name") = "HltEventLoopMgr"),
289 "Call prepareForRun on HltEventLoopMgr to initialize COOL folder helper and fire BeginRun incident. "
290 "Must be called after start() and before hltUpdateAfterFork().")
291 .def("hltUpdateAfterFork", &TrigServicesHelper::hltUpdateAfterFork,
292 (arg("worker_id") = 1,
293 arg("worker_pid") = -1,
294 arg("event_loop_name") = "HltEventLoopMgr"),
295 "Call hltUpdateAfterFork on HltEventLoopMgr to initialize the scheduler. "
296 "worker_id must be > 0 to avoid mother process behavior during stop().");
297}
static Double_t sc
BOOST_PYTHON_MODULE(libTrigServicesHelper)
EventLoopMgr interface implemented by the HLT event loop manager.
bool hltUpdateAfterFork(int worker_id=1, int worker_pid=-1, const std::string &event_loop_name="HltEventLoopMgr")
Call hltUpdateAfterFork on the HltEventLoopMgr.
bool prepareForStart(uint32_t run_number, const std::string &det_mask, const std::string &sor_time, uint32_t lb_number=0, uint32_t beam_type=0, uint32_t beam_energy=0, float toroids_current=20400.0f, float solenoid_current=7730.0f, const std::string &run_type="Physics", uint32_t trigger_type=0, bool recording_enabled=false, const std::string &event_loop_name="HltEventLoopMgr")
Call prepareForStart on the HltEventLoopMgr.
TrigServicesHelper()=default
~TrigServicesHelper()=default
bool prepareForRun(const std::string &event_loop_name="HltEventLoopMgr")
Call prepareForRun on the HltEventLoopMgr.