Line data Source code
1 : /**
2 : * @file DFApplication.cpp
3 : *
4 : * Implementation of DFApplication's generate_modules dal method
5 : *
6 : * This is part of the DUNE DAQ Software Suite, copyright 2023.
7 : * Licensing/copyright details are in the COPYING file that you should have
8 : * received with this code.
9 : */
10 :
11 :
12 : #include "ConfigObjectFactory.hpp"
13 : #include "appmodel/DFApplication.hpp"
14 : #include "appmodel/CTBApplication.hpp"
15 : #include "appmodel/DataStoreConf.hpp"
16 : #include "appmodel/DataWriterConf.hpp"
17 : #include "appmodel/DataWriterModule.hpp"
18 : #include "appmodel/FakeDataApplication.hpp"
19 : #include "appmodel/FakeDataProdConf.hpp"
20 : #include "appmodel/FilenameParams.hpp"
21 : #include "appmodel/NetworkConnectionDescriptor.hpp"
22 : #include "appmodel/NetworkConnectionRule.hpp"
23 : #include "appmodel/QueueConnectionRule.hpp"
24 : #include "appmodel/QueueDescriptor.hpp"
25 : #include "appmodel/ReadoutApplication.hpp"
26 : #include "appmodel/SourceIDConf.hpp"
27 : #include "appmodel/TPStreamConf.hpp"
28 : #include "appmodel/TRBConf.hpp"
29 : #include "appmodel/TRBModule.hpp"
30 : #include "appmodel/TPReplayModuleConf.hpp"
31 : #include "appmodel/TPReplayApplication.hpp"
32 : #include "appmodel/appmodelIssues.hpp"
33 :
34 : #include "conffwk/Configuration.hpp"
35 :
36 : #include "confmodel/Connection.hpp"
37 : #include "confmodel/DetectorStream.hpp"
38 : #include "confmodel/DetectorToDaqConnection.hpp"
39 : #include "confmodel/NetworkConnection.hpp"
40 : #include "confmodel/Service.hpp"
41 :
42 : #include "logging/Logging.hpp"
43 : #include "oks/kernel.hpp"
44 :
45 : #include <fmt/core.h>
46 : #include <string>
47 : #include <vector>
48 :
49 : namespace dunedaq {
50 : namespace appmodel {
51 :
52 :
53 : inline void
54 0 : fill_sourceid_object_from_app(const SmartDaqApplication* smartapp,
55 : const conffwk::ConfigObject* netConn,
56 : conffwk::ConfigObject& sidNetObj)
57 : {
58 0 : sidNetObj.set_obj("netconn", netConn);
59 0 : sidNetObj.set_objs("source_ids", { &smartapp->get_source_id()->config_object() });
60 0 : }
61 :
62 :
63 : inline void
64 0 : fill_sourceid_object_from_app(const ConfigObjectFactory& obj_fac,
65 : const TPReplayApplication* rapp,
66 : std::vector<conffwk::ConfigObject>* netConn,
67 : std::vector<conffwk::ConfigObject>* sidNetObj,
68 : std::vector<std::shared_ptr<conffwk::ConfigObject>> sidObjs,
69 : const NetworkConnectionDescriptor* descriptor,
70 : std::string smartapp_uid)
71 : {
72 0 : std::vector<const conffwk::ConfigObject*> source_id_objs;
73 :
74 0 : for (auto tp_sid : rapp->get_tp_source_ids()) {
75 : // get name extension
76 0 : std::string name = tp_sid->UID();
77 0 : size_t pos = name.find_last_of('-');
78 0 : std::string ext;
79 0 : if (pos != std::string::npos) {
80 0 : ext = name.substr(pos);
81 : }
82 :
83 : // set Network connections
84 0 : std::string dreqNetUid(smartapp_uid + ext);
85 0 : netConn->emplace_back(
86 0 : obj_fac.create_net_obj(descriptor, dreqNetUid));
87 0 : netConn->back().set_by_val<std::string>("data_type", descriptor->get_data_type());
88 0 : netConn->back().set_by_val<std::string>("connection_type", descriptor->get_connection_type());
89 0 : auto serviceObj = descriptor->get_associated_service()->config_object();
90 0 : netConn->back().set_obj("associated_service", &serviceObj);
91 :
92 : // set SourceID to Network connections
93 0 : std::string sidToNetUid(smartapp_uid + ext + "-sids");
94 0 : sidNetObj->emplace_back(
95 0 : obj_fac.create("SourceIDToNetworkConnection", sidToNetUid));
96 0 : sidNetObj->back().set_obj("netconn", &netConn->back());
97 :
98 : // set SourceID objs
99 0 : sidObjs.push_back(std::make_shared<conffwk::ConfigObject>(tp_sid->config_object()));
100 0 : sidNetObj->back().set_objs("source_ids", { sidObjs.back().get() });
101 0 : }
102 0 : }
103 :
104 : inline void
105 0 : fill_sourceid_object_from_app(const ConfigObjectFactory& obj_fac,
106 : const ReadoutApplication* roapp,
107 : const conffwk::ConfigObject* netConn,
108 : conffwk::ConfigObject& sidNetObj,
109 : std::vector<std::shared_ptr<conffwk::ConfigObject>> sidObjs)
110 : {
111 0 : sidNetObj.set_obj("netconn", netConn);
112 :
113 0 : std::vector<const conffwk::ConfigObject*> source_id_objs;
114 0 : std::vector<uint32_t> app_source_ids;
115 :
116 0 : for (auto d2d_conn_res : roapp->get_detector_connections()) {
117 :
118 : // get the readout groups and the interfaces and streams therein; 1 reaout group corresponds to 1 data reader
119 : // module
120 0 : auto d2d_conn = d2d_conn_res->cast<confmodel::DetectorToDaqConnection>();
121 :
122 0 : if (!d2d_conn) {
123 0 : continue;
124 : }
125 :
126 : // Loop over senders
127 0 : for (auto dros : d2d_conn->streams()) {
128 :
129 0 : auto stream = dros->cast<confmodel::DetectorStream>();
130 0 : if (!stream)
131 0 : continue;
132 0 : app_source_ids.push_back(stream->get_source_id());
133 0 : }
134 : }
135 :
136 0 : for (auto& source_id : app_source_ids) {
137 0 : std::string streamSidUid(roapp->UID() + "SourceIDConf" + std::to_string(source_id));
138 0 : auto stream_sid_obj = std::make_shared<conffwk::ConfigObject>(obj_fac.create("SourceIDConf", streamSidUid));
139 0 : stream_sid_obj->set_by_val<uint32_t>("sid", source_id);
140 0 : stream_sid_obj->set_by_val<std::string>("subsystem", "Detector_Readout");
141 0 : sidObjs.push_back(stream_sid_obj);
142 0 : source_id_objs.push_back(sidObjs.back().get());
143 0 : }
144 :
145 0 : for (auto tp_sid : roapp->get_tp_source_ids()) {
146 0 : sidObjs.push_back(std::make_shared<conffwk::ConfigObject>(tp_sid->config_object()));
147 0 : source_id_objs.push_back(sidObjs.back().get());
148 : }
149 : /*
150 : std::string trgSidUid(roapp->UID() + "TRGSourceIDConf" + std::to_string(roapp->get_tp_source_id()));
151 : auto trig_sid_obj = std::make_shared<conffwk::ConfigObject>(obj_fac.create("SourceIDConf", trgSidUid));
152 : trig_sid_obj->set_by_val<uint32_t>("sid", roapp->get_tp_source_id());
153 : trig_sid_obj->set_by_val<std::string>("subsystem", "Trigger");
154 : source_id_objs.push_back(sidObjs.back().get());
155 : */
156 :
157 0 : sidNetObj.set_objs("source_ids", source_id_objs);
158 0 : }
159 :
160 : inline void
161 0 : fill_sourceid_object_from_app(const ConfigObjectFactory& obj_fac,
162 : const FakeDataApplication* fdapp,
163 : const conffwk::ConfigObject* netConn,
164 : conffwk::ConfigObject& sidNetObj,
165 : std::vector<std::shared_ptr<conffwk::ConfigObject>> sidObjs)
166 : {
167 0 : sidNetObj.set_obj("netconn", netConn);
168 :
169 0 : std::vector<const conffwk::ConfigObject*> source_id_objs;
170 0 : std::vector<uint32_t> app_source_ids;
171 :
172 0 : for (auto fdpc : fdapp->get_producers()) {
173 :
174 : // get the readout groups and the interfaces and streams therein; 1 reaout group corresponds to 1 data reader
175 : // module
176 :
177 0 : app_source_ids.push_back(fdpc->get_source_id());
178 : }
179 :
180 0 : for (auto& source_id : app_source_ids) {
181 0 : std::string streamSidUid(fdapp->UID() + "SourceIDConf" + std::to_string(source_id));
182 0 : auto stream_sid_obj = std::make_shared<conffwk::ConfigObject>(obj_fac.create("SourceIDConf", streamSidUid));
183 0 : stream_sid_obj->set_by_val<uint32_t>("sid", source_id);
184 0 : stream_sid_obj->set_by_val<std::string>("subsystem", "Detector_Readout");
185 0 : sidObjs.push_back(stream_sid_obj);
186 0 : source_id_objs.push_back(sidObjs.back().get());
187 0 : }
188 :
189 0 : sidNetObj.set_objs("source_ids", source_id_objs);
190 0 : }
191 :
192 : void
193 0 : DFApplication::generate_modules(const confmodel::Session* session) const
194 : {
195 :
196 0 : ConfigObjectFactory obj_fac(this);
197 :
198 0 : std::vector<const confmodel::DaqModule*> modules;
199 :
200 : // Containers for module specific config objects for output/input
201 : // Prepare TRB output objects
202 0 : std::vector<const conffwk::ConfigObject*> trbInputObjs;
203 0 : std::vector<const conffwk::ConfigObject*> trbOutputObjs;
204 0 : std::vector<const conffwk::ConfigObject*> trbSidNetObjs;
205 :
206 : // -- First, we process expected Queue and Network connections and create their objects.
207 :
208 : // Process the queue rules looking for the TriggerRecord queue between TRB and DataWriterModule
209 0 : const QueueDescriptor* trQDesc = nullptr;
210 0 : for (auto rule : get_queue_rules()) {
211 0 : auto destination_class = rule->get_destination_class();
212 0 : if (destination_class == "DataWriterModule") {
213 0 : trQDesc = rule->get_descriptor();
214 : }
215 0 : }
216 0 : if (trQDesc == nullptr) { // BadConf if no descriptor between TRB and DataWriterModule
217 0 : throw(BadConf(ERS_HERE, "Could not find queue descriptor rule for TriggerRecords!"));
218 : }
219 : // Create queue connection config object
220 0 : auto trQueueObj = obj_fac.create_queue_obj(trQDesc, UID());
221 :
222 : // Place trigger record queue object into vector of output objs of TRB module
223 0 : trbOutputObjs.push_back(&trQueueObj);
224 :
225 : // Process the network rules looking for the Fragments and TriggerDecision inputs for TRB
226 0 : const NetworkConnectionDescriptor* fragNetDesc = nullptr;
227 0 : const NetworkConnectionDescriptor* trigdecNetDesc = nullptr;
228 0 : const NetworkConnectionDescriptor* tokenNetDesc = nullptr;
229 0 : const NetworkConnectionDescriptor* trmonReqNetDesc = nullptr;
230 0 : const NetworkConnectionDescriptor* trmonTRNetDesc = nullptr;
231 0 : for (auto rule : get_network_rules()) {
232 0 : auto descriptor = rule->get_descriptor();
233 0 : auto data_type = descriptor->get_data_type();
234 0 : if (data_type == "Fragment") {
235 0 : fragNetDesc = rule->get_descriptor();
236 0 : } else if (data_type == "TriggerDecision") {
237 0 : trigdecNetDesc = rule->get_descriptor();
238 0 : } else if (data_type == "TriggerDecisionToken") {
239 0 : tokenNetDesc = rule->get_descriptor();
240 0 : } else if (data_type == "TRMonRequest") {
241 0 : trmonReqNetDesc = rule->get_descriptor();
242 0 : } else if (data_type == "TriggerRecord") {
243 0 : trmonTRNetDesc = rule->get_descriptor();
244 : }
245 0 : }
246 0 : if (fragNetDesc == nullptr) { // BadConf if no descriptor for Fragments into TRB
247 0 : throw(BadConf(ERS_HERE, "Could not find network descriptor rule for input Fragments!"));
248 : }
249 0 : if (trigdecNetDesc == nullptr) { // BadCond if no descriptor for TriggerDecisions into TRB
250 0 : throw(BadConf(ERS_HERE, "Could not find network descriptor rule for input TriggerDecisions!"));
251 : }
252 0 : if (tokenNetDesc == nullptr) { // BadCond if no descriptor for Tokens out of DataWriterModule
253 0 : throw(BadConf(ERS_HERE, "Could not find network descriptor rule for output TriggerDecisionTokens!"));
254 : }
255 0 : if (get_source_id() == nullptr) {
256 0 : throw(BadConf(ERS_HERE, "Could not retrieve SourceIDConf"));
257 : }
258 : // Create network connection config object
259 0 : auto fragNetObj = obj_fac.create_net_obj(fragNetDesc, UID());
260 0 : auto trigdecNetObj = obj_fac.create_net_obj(trigdecNetDesc, UID());
261 0 : auto tokenNetObj = obj_fac.create_net_obj(tokenNetDesc, "");
262 0 : conffwk::ConfigObject trmonReqNetObj;
263 0 : conffwk::ConfigObject trmonTRNetObj;
264 0 : if (trmonReqNetDesc != nullptr) {
265 0 : trmonReqNetObj = obj_fac.create_net_obj(trmonReqNetDesc, UID());
266 : }
267 0 : if (trmonTRNetDesc != nullptr) {
268 0 : trmonTRNetObj = obj_fac.create_net_obj(trmonTRNetDesc, "");
269 : }
270 :
271 : // Process special Network rules!
272 : // Looking for DataRequest rules from ReadoutAppplications in current Session
273 0 : auto sessionApps = session->enabled_applications();
274 0 : std::vector<conffwk::ConfigObject> dreqNetObjs;
275 0 : std::vector<conffwk::ConfigObject> sidNetObjs;
276 0 : std::vector<std::shared_ptr<conffwk::ConfigObject>> sidObjs;
277 0 : for (auto app : sessionApps) {
278 0 : auto smartapp = app->cast<appmodel::SmartDaqApplication>();
279 0 : auto roapp = app->cast<appmodel::ReadoutApplication>();
280 0 : auto fdapp = app->cast<appmodel::FakeDataApplication>();
281 0 : auto ctbapp = app->cast<appmodel::CTBApplication>();
282 0 : auto dfapp = app->cast<appmodel::DFApplication>();
283 0 : auto rapp = app->cast<appmodel::TPReplayApplication>();
284 0 : if (smartapp == nullptr || dfapp != nullptr) {
285 0 : continue;
286 : }
287 0 : auto src_id_check = smartapp->get_source_id();
288 0 : if (roapp == nullptr
289 0 : && fdapp == nullptr
290 0 : && src_id_check == nullptr
291 0 : && rapp == nullptr
292 0 : && ctbapp == nullptr) {
293 0 : continue;
294 : }
295 :
296 0 : auto roQRules = smartapp->get_network_rules();
297 0 : for (auto rule : roQRules) {
298 0 : auto descriptor = rule->get_descriptor();
299 0 : auto data_type = descriptor->get_data_type();
300 0 : if (data_type == "DataRequest") {
301 0 : if (rapp != nullptr) {
302 0 : fill_sourceid_object_from_app(obj_fac, rapp, &dreqNetObjs, &sidNetObjs, sidObjs, descriptor, smartapp->UID());
303 : }
304 : // contrary to all the other applications
305 : // the CTB has 2 network connections, so this logic has to be splitted
306 0 : else if (ctbapp) {
307 0 : auto sources = ctbapp->get_sources();
308 0 : for ( const auto & s : sources ) {
309 0 : std::string dreqNetUid(descriptor->get_uid_base() + smartapp->UID()+ '_' + s.first);
310 0 : dreqNetObjs.emplace_back( obj_fac.create_net_obj(descriptor, dreqNetUid) );
311 :
312 0 : std::string sidToNetUid(descriptor->get_uid_base() + smartapp->UID() + "_" + s.first);
313 0 : sidNetObjs.emplace_back( obj_fac.create("SourceIDToNetworkConnection", sidToNetUid ) );
314 0 : sidNetObjs.back().set_obj("netconn", & dreqNetObjs.back());
315 0 : sidNetObjs.back().set_objs("source_ids", { & s.second->config_object() });
316 0 : } // loop over CTB sources
317 0 : } else {
318 :
319 0 : dreqNetObjs.emplace_back(obj_fac.create_net_obj(descriptor, smartapp->UID()));
320 :
321 0 : std::string sidToNetUid(descriptor->get_uid_base() + smartapp->UID() + "-sids");
322 0 : sidNetObjs.emplace_back(
323 0 : obj_fac.create("SourceIDToNetworkConnection", sidToNetUid));
324 0 : if (roapp != nullptr) {
325 0 : fill_sourceid_object_from_app(obj_fac, roapp, &dreqNetObjs.back(), sidNetObjs.back(), sidObjs);
326 0 : } else if (fdapp != nullptr) {
327 0 : fill_sourceid_object_from_app(obj_fac, fdapp, &dreqNetObjs.back(), sidNetObjs.back(), sidObjs);
328 : } else {
329 0 : fill_sourceid_object_from_app(smartapp, &dreqNetObjs.back(), sidNetObjs.back());
330 : }
331 0 : } // else from if (ctbapp)
332 : } // If network rule has DataRequest type of data
333 0 : } // Loop over Apps network rules
334 0 : } // loop over Session specific Apps
335 :
336 : // Get pointers to objects here, after vector has been filled so they don't move on us
337 0 : for (auto& obj : dreqNetObjs) {
338 0 : trbOutputObjs.push_back(&obj);
339 : }
340 0 : for (auto& obj : sidNetObjs) {
341 0 : trbSidNetObjs.push_back(&obj);
342 : }
343 :
344 : // -- Second, we create the Module objects and assign their configs, with the precreated
345 : // -- connection config objects above.
346 :
347 : // Get TRB Config Object
348 0 : auto trbConf = get_trb();
349 0 : if (trbConf == nullptr) {
350 0 : throw(BadConf(ERS_HERE, "No DataWriterModule or TRB configuration given"));
351 : }
352 0 : auto trbConfObj = trbConf->config_object();
353 0 : trbConfObj.set_by_val<uint32_t>("source_id", get_source_id()->get_sid());
354 0 : trbInputObjs = { &trigdecNetObj, &fragNetObj };
355 0 : if (trmonReqNetDesc != nullptr) {
356 0 : trbInputObjs.push_back(&trmonReqNetObj);
357 : }
358 0 : if (trmonTRNetDesc != nullptr) {
359 0 : trbOutputObjs.push_back(&trmonTRNetObj);
360 : }
361 : // Prepare TRB Module Object and assign its Config Object.
362 0 : std::string trbUid(UID() + "-trb");
363 0 : conffwk::ConfigObject trbObj = obj_fac.create("TRBModule", trbUid);
364 0 : trbObj.set_obj("configuration", &trbConfObj);
365 0 : trbObj.set_objs("inputs", trbInputObjs);
366 0 : trbObj.set_objs("outputs", trbOutputObjs);
367 0 : trbObj.set_obj("trigger_record_output", &trQueueObj);
368 0 : trbObj.set_objs("request_connections", trbSidNetObjs);
369 : // Push TRB Module Object from confdb
370 0 : modules.push_back(obj_fac.get_dal<TRBModule>(trbUid));
371 :
372 : // Get DataWriterModule Config Object (only one for now, maybe more later?)
373 0 : auto dwrConfs = get_data_writers();
374 0 : if (dwrConfs.size() == 0) {
375 0 : throw(BadConf(ERS_HERE, "No DataWriterModule or TRB configuration given"));
376 : }
377 0 : uint dw_idx = 0;
378 0 : for (auto dwrConf : dwrConfs) {
379 : // auto fnParamsObj = dwrConf->get_data_store_params()->get_filename_params()->config_object();
380 : // fnParamsObj.set_by_val<std::string>("writer_identifier", fmt::format("{}_datawriter-{}", UID(), dw_idx));
381 0 : auto dwrConfObj = dwrConf->config_object();
382 :
383 : // Prepare DataWriterModule Module Object and assign its Config Object.
384 0 : std::string dwrUid(fmt::format("{}-dw-{}", UID(), dw_idx));
385 0 : conffwk::ConfigObject dwrObj = obj_fac.create("DataWriterModule", dwrUid);
386 0 : dwrObj.set_by_val("writer_identifier", fmt::format("{}_dw_{}", UID(), dw_idx));
387 0 : dwrObj.set_obj("configuration", &dwrConfObj);
388 0 : dwrObj.set_objs("inputs", { &trQueueObj });
389 0 : dwrObj.set_objs("outputs", { &tokenNetObj });
390 : // Push DataWriterModule Module Object from confdb
391 0 : modules.push_back(obj_fac.get_dal<DataWriterModule>(dwrUid));
392 0 : ++dw_idx;
393 0 : }
394 :
395 0 : obj_fac.update_modules(modules);
396 0 : }
397 :
398 : } // namespace appmodel
399 : } // namespace dunedaq
|