DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
MLTApplication.cpp
Go to the documentation of this file.
1
13
15
18// #include "confmodel/ReadoutGroup.hpp"
19// #include "confmodel/ReadoutInterface.hpp"
20// #include "confmodel/DetectorStream.hpp"
24#include "confmodel/Service.hpp"
25#include "confmodel/Session.hpp"
26
39#include "appmodel/MLTConf.hpp"
55
56#include "logging/Logging.hpp"
57
58#include <string>
59#include <vector>
60
61namespace dunedaq {
62namespace appmodel {
63
64
65std::vector<const confmodel::DaqModule*>
67{
68
69 std::vector<const confmodel::DaqModule*> modules;
70
71 ConfigObjectFactory obj_fac(this);
72
73 // auto mlt_conf = get_mlt_conf();
74 // auto mlt_class = mlt_conf->get_template_for();
75
76 auto tch_conf = get_trigger_inputs_handler();
77 auto tch_class = tch_conf->get_template_for();
78
79 auto mlt_conf = get_mlt_conf();
80 auto mlt_class = mlt_conf->get_template_for();
81 std::string handler_name(tch_conf->UID());
82
83 if (!mlt_conf) {
84 throw(BadConf(ERS_HERE, "No MLT configuration in MLTApplication given"));
85 }
86
87 // Queue descriptors
88 // Process the queue rules looking for inputs to our trigger handler modules
89 const QueueDescriptor* tc_inputq_desc = nullptr;
90 const QueueDescriptor* td_outputq_desc = nullptr;
91
92 for (auto rule : get_queue_rules()) {
93 auto destination_class = rule->get_destination_class();
94 auto data_type = rule->get_descriptor()->get_data_type();
95 if (destination_class == tch_class) {
96 tc_inputq_desc = rule->get_descriptor();
97 } else if (destination_class == mlt_class) {
98 td_outputq_desc = rule->get_descriptor();
99 }
100 }
101
102 if (tc_inputq_desc == nullptr) {
103 throw(BadConf(ERS_HERE, "No TC input queue descriptor given"));
104 }
105 if (td_outputq_desc == nullptr) {
106 throw(BadConf(ERS_HERE, "No TD output-input queue descriptor given"));
107 }
108
109 // Create queues
110 auto input_queue_obj = obj_fac.create_queue_obj(tc_inputq_desc);
111 auto output_queue_obj = obj_fac.create_queue_obj(td_outputq_desc);
112
113 // Net descriptors
114 const NetworkConnectionDescriptor* req_net_desc = nullptr;
115 const NetworkConnectionDescriptor* tc_net_desc = nullptr;
116 const NetworkConnectionDescriptor* ti_net_desc = nullptr;
117 const NetworkConnectionDescriptor* td_net_desc = nullptr;
118 const NetworkConnectionDescriptor* timesync_net_desc = nullptr;
119
120 for (auto rule : get_network_rules()) {
121 std::string data_type = rule->get_descriptor()->get_data_type();
122
123 // Network connections for the MLT
124 if (data_type == "TriggerInhibit") {
125 ti_net_desc = rule->get_descriptor();
126 }
127 if (data_type == "TriggerDecision") {
128 td_net_desc = rule->get_descriptor();
129 }
130 if (data_type == "TriggerCandidate") {
131 tc_net_desc = rule->get_descriptor();
132 }
133 if (data_type == "TimeSync") {
134 timesync_net_desc = rule->get_descriptor();
135 }
136 if (data_type == "DataRequest") {
137 req_net_desc = rule->get_descriptor();
138 }
139
140 TLOG_DEBUG(3) << "Endpoint class (currently not used in for networkconnections): data_type: " << data_type;
141 }
142
143 if (!td_net_desc) {
144 throw(BadConf(ERS_HERE, "No MLT network connection for the output TriggerDecision given"));
145 }
146 if (!ti_net_desc) {
147 throw(BadConf(ERS_HERE, "No MLT network connection for the output TriggerInhibit given"));
148 }
149 if (!tc_net_desc) {
150 throw(BadConf(ERS_HERE, "No MLT network connection for the Input of TriggerCandidates given"));
151 }
152 if (!req_net_desc) {
153 throw(BadConf(ERS_HERE, "No MLT network connection for the Input of DataRequests given"));
154 }
155 // Network connection for input TriggerInhibit, input TCs
156
157 conffwk::ConfigObject ti_net_obj =
158 obj_fac.create_net_obj(ti_net_desc, "");
159
160 conffwk::ConfigObject tc_net_obj =
161 obj_fac.create_net_obj(tc_net_desc, ".*");
162
163 // Network connection for output TriggerDecision
164 conffwk::ConfigObject td_net_obj =
165 obj_fac.create_net_obj(td_net_desc, "");
166
167 // Network conection for the input Data Requests
168 conffwk::ConfigObject dr_net_obj =
169 obj_fac.create_net_obj(req_net_desc, UID());
170
171 conffwk::ConfigObject timesync_net_obj;
172 if (timesync_net_desc != nullptr) {
173 timesync_net_obj =
174 obj_fac.create_net_obj(timesync_net_desc, ".*");
175 }
176
177 /**************************************************************
178 * Instantiate standalone TC generator modules (e.g. random TC generator)
179 **************************************************************/
180
181 auto standalone_TC_maker_confs = get_standalone_candidate_maker_confs();
182 std::vector<conffwk::ConfigObject> generated_tc_conns;
183 generated_tc_conns.reserve(standalone_TC_maker_confs.size());
184 for (auto gen_conf : standalone_TC_maker_confs) {
185 conffwk::ConfigObject gen_obj = obj_fac.create(gen_conf->get_template_for(),
186 gen_conf->UID());
187 gen_obj.set_obj("configuration", &(gen_conf->config_object()));
188 if (gen_conf->get_timestamp_method() == "kTimeSync" && !timesync_net_obj.is_null()) {
189 gen_obj.set_objs("inputs", { &timesync_net_obj });
190 }
191
192 auto tc_net_gen = obj_fac.create_net_obj(tc_net_desc, gen_conf->UID());
193 generated_tc_conns.push_back(tc_net_gen);
194
195 gen_obj.set_objs("outputs", { &generated_tc_conns.back() });
196 modules.push_back(obj_fac.get_dal<StandaloneTCMakerModule>(gen_conf->UID()));
197 }
198
199 /**************************************************************
200 * Create the Data Reader
201 **************************************************************/
202 auto rdr_conf = get_data_subscriber();
203 if (rdr_conf == nullptr) {
204 throw(BadConf(ERS_HERE, "No DataReaderModule configuration given"));
205 }
206
207 std::string reader_uid("data-reader-" + UID());
208 std::string reader_class = rdr_conf->get_template_for();
209 TLOG_DEBUG(7) << "creating OKS configuration object for Data subscriber class " << reader_class;
210 conffwk::ConfigObject reader_obj = obj_fac.create(reader_class, reader_uid);
211 reader_obj.set_objs("inputs", { &tc_net_obj });
212 reader_obj.set_objs("outputs", { &input_queue_obj });
213 reader_obj.set_obj("configuration", &rdr_conf->config_object());
214
215 modules.push_back(obj_fac.get_dal<DataSubscriberModule>(reader_uid));
216
217 /**************************************************************
218 * Create the readout map
219 **************************************************************/
220
221 std::vector<const dunedaq::confmodel::Application*> apps = session->get_enabled_applications();
222
223 std::vector<const conffwk::ConfigObject*> sourceIds;
224
225 for (auto app : apps) {
226 auto ro_app = app->cast<appmodel::ReadoutApplication>();
227 if (ro_app != nullptr) {
228 auto resources = ro_app->get_contains();
229 // Interate over all the readout groups
230 for (auto d2d_conn_res : resources) {
231 if (d2d_conn_res->disabled(*session)) {
232 TLOG_DEBUG(7) << "Ignoring disabled Detector2DaqConnection " << d2d_conn_res->UID();
233 continue;
234 }
235
236 auto d2d_conn = d2d_conn_res->cast<confmodel::DetectorToDaqConnection>();
237 if (d2d_conn == nullptr) {
238 throw(BadConf(
239 ERS_HERE,
240 "MLTApplication's detectordaq connections list contains something other than DetectorToDaqConnection"));
241 }
242 if (d2d_conn->get_contains().empty()) {
243 throw(BadConf(ERS_HERE, "DetectorToDaqConnection does not contain interfaces"));
244 }
245
246 // Interate over all the streams
247 for (auto stream : d2d_conn->get_streams()) {
248 if (stream == nullptr) {
249 throw(BadConf(ERS_HERE, "ReadoutInterface contains something other than DetectorStream"));
250 }
251 if (stream->disabled(*session)) {
252 TLOG_DEBUG(7) << "Ignoring disabled DetectorStream " << stream->UID();
253 continue;
254 }
255
256 // Create SourceIDConf object for the MLT
257 auto id = stream->get_source_id();
258 std::string sourceIdConfUID = "dro-mlt-stream-config-" + std::to_string(id);
260 obj_fac.create("SourceIDConf", sourceIdConfUID));
261 sourceIdConf->set_by_val<uint32_t>("sid", id);
262 // https://github.com/DUNE-DAQ/daqdataformats/blob/5b99506675a586c8a09123900e224f2371d96df9/include/daqdataformats/detail/SourceID.hxx#L108
263 sourceIdConf->set_by_val<std::string>("subsystem", "Detector_Readout");
264 sourceIds.push_back(sourceIdConf);
265 }
266 }
267 if (ro_app->get_tp_generation_enabled()) {
268 for (auto sid : ro_app->get_tp_source_ids()) {
269 sourceIds.push_back(&(sid->config_object()));
270 }
271 // conffwk::ConfigObject* tpSourceIdConf = new conffwk::ConfigObject();
272 // confdb->create(dbfile, "SourceIDConf", ro_app->UID()+"-"+ std::to_string(ro_app->get_tp_source_id()),
273 // *tpSourceIdConf); tpSourceIdConf->set_by_val<uint32_t>("sid", ro_app->get_tp_source_id());
274 // tpSourceIdConf->set_by_val<std::string>("subsystem", "Trigger");
275 // sourceIds.push_back(tpSourceIdConf);
276 }
277 }
278
279 auto tpreplay_app = app->cast<appmodel::TPReplayApplication>();
280 if (tpreplay_app != nullptr) {
281 for (auto sid : tpreplay_app->get_tp_source_ids()) {
282 sourceIds.push_back(&(sid->config_object()));
283 }
284 }
285
286 auto fd_app = app->cast<appmodel::FakeDataApplication>();
287 if (fd_app != nullptr) {
288
289 auto resources = fd_app->get_contains();
290 // Interate over all the FakeDataProd modules
291 for (auto stream_res : resources) {
292
293 if (stream_res->disabled(*session)) {
294 TLOG_DEBUG(7) << "Ignoring disabled FakeDataProdConf " << stream_res->UID();
295 continue;
296 }
297
298 auto stream = stream_res->cast<appmodel::FakeDataProdConf>();
299
300 // Create SourceIDConf object for the MLT
301 auto id = stream->get_source_id();
302 std::string sourceIdConfUID = "dro-mlt-stream-config-" + std::to_string(id);
304 obj_fac.create("SourceIDConf", sourceIdConfUID));
305 sourceIdConf->set_by_val<uint32_t>("sid", id);
306 // https://github.com/DUNE-DAQ/daqdataformats/blob/5b99506675a586c8a09123900e224f2371d96df9/include/daqdataformats/detail/SourceID.hxx#L108
307 sourceIdConf->set_by_val<std::string>("subsystem", "Detector_Readout");
308 sourceIds.push_back(sourceIdConf);
309 }
310 }
311
312 // SmartDaqApplication now has source_id member, might want to use that but make sure that it's actually a data
313 // source somehow...
314 auto trg_app = app->cast<appmodel::TriggerApplication>();
315 if (trg_app != nullptr && trg_app->get_source_id() != nullptr) {
316 conffwk::ConfigObject* tcSourceIdConf = new conffwk::ConfigObject(
317 obj_fac.create(
318 "SourceIDConf",
319 trg_app->UID() + "-" + std::to_string(trg_app->get_source_id()->get_sid())
320 ));
321 tcSourceIdConf->set_by_val<uint32_t>("sid", trg_app->get_source_id()->get_sid());
322 tcSourceIdConf->set_by_val<std::string>("subsystem", trg_app->get_source_id()->get_subsystem());
323 sourceIds.push_back(tcSourceIdConf);
324 }
325
326 // FIXME: add here same logics for HSI application(s)
327 //
328 auto hsi_app = app->cast<appmodel::FakeHSIApplication>();
329 if (hsi_app != nullptr && hsi_app->get_source_id() != nullptr) {
330 conffwk::ConfigObject* hsEventSourceIdConf = new conffwk::ConfigObject(
331 obj_fac.create(
332 "SourceIDConf",
333 hsi_app->UID() + "-" + std::to_string(hsi_app->get_source_id()->get_sid())));
334 hsEventSourceIdConf->set_by_val<uint32_t>("sid", hsi_app->get_source_id()->get_sid());
335 hsEventSourceIdConf->set_by_val<std::string>("subsystem", hsi_app->get_source_id()->get_subsystem());
336 sourceIds.push_back(hsEventSourceIdConf);
337 }
338
339 auto dts_hsi_app = app->cast<appmodel::DTSHSIApplication>();
340 if (dts_hsi_app != nullptr && dts_hsi_app->get_source_id() != nullptr) {
341 conffwk::ConfigObject* hsEventSourceIdConf = new conffwk::ConfigObject(
342 obj_fac.create(
343 "SourceIDConf",
344 dts_hsi_app->UID() + "-" + std::to_string(dts_hsi_app->get_source_id()->get_sid())
345 )
346 );
347 hsEventSourceIdConf->set_by_val<uint32_t>("sid", dts_hsi_app->get_source_id()->get_sid());
348 hsEventSourceIdConf->set_by_val<std::string>("subsystem", dts_hsi_app->get_source_id()->get_subsystem());
349 sourceIds.push_back(hsEventSourceIdConf);
350 }
351
352 auto ctb_app = app->cast<appmodel::CTBApplication>();
353 if (ctb_app) {
354 auto sources = ctb_app->get_sources();
355 for ( const auto & s : sources ) {
356 auto src_id_conf_ptr = new conffwk::ConfigObject( obj_fac.create("SourceIDConf",
357 ctb_app->UID() + "-" + s.first ) );
358 src_id_conf_ptr->set_by_val<uint32_t>("sid", s.second->get_sid());
359 src_id_conf_ptr->set_by_val<std::string>("subsystem", s.second->get_subsystem());
360 sourceIds.push_back(src_id_conf_ptr);
361 } // loop over CTB sources
362 } // CTB app
363
364 } // loop over applications
365
366 // Get mandatory links
367 std::vector<const conffwk::ConfigObject*> mandatory_sids;
368 const TCDataProcessor* tc_dp = tch_conf->get_data_processor()->cast<TCDataProcessor>();
369 if (tc_dp != nullptr) {
370 for (auto m : tc_dp->get_mandatory_links()) {
371 mandatory_sids.push_back(&m->config_object());
372 }
373 }
374
375 /**************************************************************
376 * Create the TC handler
377 **************************************************************/
378
379 // Process special Network rules!
380 // Looking for Fragment rules from DFAppplications in current Session
381 auto sessionApps = session->get_enabled_applications();
382 std::vector<conffwk::ConfigObject> fragOutObjs;
383 for (auto app : sessionApps) {
384 auto dfapp = app->cast<appmodel::DFApplication>();
385 if (dfapp == nullptr)
386 continue;
387
388 auto dfNRules = dfapp->get_network_rules();
389 for (auto rule : dfNRules) {
390 auto descriptor = rule->get_descriptor();
391 auto data_type = descriptor->get_data_type();
392 if (data_type == "Fragment") {
393 fragOutObjs.emplace_back(obj_fac.create_net_obj(descriptor, dfapp->UID()));
394 } // If network rule has TriggerDecision type of data
395 } // Loop over Apps network rules
396 } // loop over Session specific Apps
397
398 // build up the full list of outputs
399 std::vector<const conffwk::ConfigObject*> ti_output_objs;
400 for (auto& fNet : fragOutObjs) {
401 ti_output_objs.push_back(&fNet);
402 }
403 ti_output_objs.push_back(&output_queue_obj);
404
405 auto tch_conf_obj = tch_conf->config_object();
406 if (get_source_id() == nullptr) {
407 throw(BadConf(ERS_HERE, "No source_id associated with this TriggerApplication!"));
408 }
409 uint32_t source_id = get_source_id()->get_sid();
410 std::string ti_uid(handler_name + "-" + std::to_string(source_id));
411 conffwk::ConfigObject ti_obj = obj_fac.create(tch_class, ti_uid);
412 ti_obj.set_by_val<uint32_t>("source_id", source_id);
413 ti_obj.set_by_val<uint32_t>("detector_id", 1); // 1 == kDAQ
414 ti_obj.set_obj("module_configuration", &tch_conf_obj);
415 ti_obj.set_objs("enabled_source_ids", sourceIds);
416 ti_obj.set_objs("mandatory_source_ids", mandatory_sids);
417 ti_obj.set_objs("inputs", { &input_queue_obj, &dr_net_obj });
418 ti_obj.set_objs("outputs", ti_output_objs);
419
420 // Add to our list of modules to return
421 modules.push_back(obj_fac.get_dal<DataHandlerModule>(ti_uid));
422
423 /**************************************************************
424 * Instantiate the MLTModule module
425 **************************************************************/
426
427 conffwk::ConfigObject mlt_obj = obj_fac.create(mlt_conf->get_template_for(),
428 mlt_conf->UID());
429 mlt_obj.set_obj("configuration", &(mlt_conf->config_object()));
430 mlt_obj.set_objs("inputs", { &output_queue_obj, &ti_net_obj });
431 mlt_obj.set_objs("outputs", { &td_net_obj });
432 modules.push_back(obj_fac.get_dal<MLTModule>(mlt_conf->UID()));
433
434 return modules;
435}
436
437} // namespace appmodel
438} // namespace dunedaq
#define ERS_HERE
conffwk::ConfigObject create_net_obj(const NetworkConnectionDescriptor *ndesc, std::string uid) const
Helper function that gets a network connection config.
const T * get_dal(std::string uid) const
conffwk::ConfigObject create_queue_obj(const QueueDescriptor *qdesc, std::string uid="") const
conffwk::ConfigObject create(const std::string &class_name, const std::string &id) const
uint32_t get_source_id() const
Get "source_id" attribute value. The SourceID of this link.
const std::vector< const dunedaq::appmodel::StandaloneTCMakerConf * > & get_standalone_candidate_maker_confs() const
Get "standalone_candidate_maker_confs" relationship value.
const dunedaq::appmodel::MLTConf * get_mlt_conf() const
Get "mlt_conf" relationship value.
std::vector< const dunedaq::confmodel::DaqModule * > generate_modules(const confmodel::Session *) const override
const std::vector< const dunedaq::appmodel::NetworkConnectionRule * > & get_network_rules() const
Get "network_rules" relationship value.
const std::vector< const dunedaq::appmodel::QueueConnectionRule * > & get_queue_rules() const
Get "queue_rules" relationship value.
const dunedaq::appmodel::SourceIDConf * get_source_id() const
Get "source_id" relationship value.
uint32_t get_sid() const
Get "sid" attribute value.
const std::vector< const dunedaq::appmodel::SourceIDConf * > & get_mandatory_links() const
Get "mandatory_links" relationship value. Source Ids that will always be included in a trigger decisi...
const dunedaq::appmodel::DataHandlerConf * get_trigger_inputs_handler() const
Get "trigger_inputs_handler" relationship value.
const dunedaq::appmodel::DataReaderConf * get_data_subscriber() const
Get "data_subscriber" relationship value.
void set_by_val(const std::string &name, T value)
Set attribute value.
void set_objs(const std::string &name, const std::vector< const ConfigObject * > &o, bool skip_non_null_check=false)
Set relationship multi-value.
void set_obj(const std::string &name, const ConfigObject *o, bool skip_non_null_check=false)
Set relationship single-value.
bool is_null() const noexcept
Check if object's implementation points to null.
const TARGET * cast() const noexcept
Casts object to different class.
const std::string & UID() const noexcept
conffwk entry point
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
Including Qt Headers.