Line data Source code
1 : /**
2 : * @file CRTReaderApplication.cpp
3 : *
4 : * Implementation of CRTReaderApplication'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 : #include "appmodel/CRTReaderApplication.hpp"
12 :
13 : #include "appmodel/appmodelIssues.hpp"
14 :
15 : #include "appmodel/DataReaderConf.hpp"
16 : #include "appmodel/SocketWriterConf.hpp"
17 : #include "appmodel/SocketWriterModule.hpp"
18 : #include "appmodel/QueueConnectionRule.hpp"
19 : #include "appmodel/QueueDescriptor.hpp"
20 :
21 : #include "ConfigObjectFactory.hpp"
22 :
23 : #include "confmodel/Connection.hpp"
24 : #include "confmodel/DetectorStream.hpp"
25 : #include "confmodel/DetectorToDaqConnection.hpp"
26 :
27 : #include "logging/Logging.hpp"
28 :
29 : #include <fmt/core.h>
30 :
31 : #include <string>
32 : #include <vector>
33 :
34 : namespace dunedaq::appmodel {
35 :
36 : std::vector<const confmodel::Resource*>
37 0 : CRTReaderApplication::contained_resources() const {
38 0 : return to_resources(get_detector_connections());
39 : }
40 :
41 : void
42 0 : CRTReaderApplication::generate_modules(const confmodel::Session* session) const
43 : {
44 :
45 0 : TLOG_DEBUG(6) << "Generating modules for application " << this->UID();
46 :
47 0 : std::vector<const confmodel::DaqModule*> modules;
48 :
49 0 : ConfigObjectFactory obj_fac(this);
50 :
51 : //
52 : // Extract basic configuration objects
53 : //
54 :
55 : // Data reader
56 0 : const auto reader_conf = get_data_reader();
57 0 : if (reader_conf == 0) {
58 0 : throw(BadConf(ERS_HERE, "No DataReaderModule configuration given"));
59 : }
60 0 : const std::string reader_class = reader_conf->get_template_for();
61 :
62 : // Data writers
63 0 : const auto writer_confs = get_data_writers();
64 0 : if (writer_confs.size() == 0) {
65 0 : throw(BadConf(ERS_HERE, "No DataWriterModule configuration given"));
66 : }
67 :
68 : //
69 : // Process the queue rules looking for inputs to our DL/TP handler modules
70 : //
71 0 : const QueueDescriptor* dlh_input_qdesc = nullptr;
72 :
73 0 : for (auto rule : get_queue_rules()) {
74 0 : auto destination_class = rule->get_destination_class();
75 0 : auto data_type = rule->get_descriptor()->get_data_type();
76 : // Why datahander here? It is the base class for several DataHandler types (e.g. FDDataHandlerModule,
77 : // SNBDataHandlerModule)
78 0 : if (destination_class == "DataHandlerModule") {
79 0 : if (data_type != "DataRequest") {
80 0 : dlh_input_qdesc = rule->get_descriptor();
81 : }
82 : }
83 0 : }
84 :
85 0 : if (dlh_input_qdesc == nullptr) {
86 0 : throw(BadConf(ERS_HERE, "No data link handler input queue descriptor given"));
87 : }
88 :
89 : //
90 : // Scan Detector 2 DAQ connections to extract sender, receiver and stream information
91 : //
92 :
93 : // Loop over the detector to daq connections and generate one data reader per connection
94 :
95 : // Collect all streams
96 0 : std::map<uint32_t, const confmodel::Connection*> data_queues_by_sid;
97 :
98 0 : uint16_t conn_idx = 0;
99 :
100 0 : for (auto d2d_conn : get_detector_connections()) {
101 :
102 : // Are we sure?
103 0 : if (d2d_conn->is_disabled(*session)) {
104 0 : TLOG_DEBUG(7) << "Ignoring disabled DetectorToDaqConnection " << d2d_conn->UID();
105 0 : continue;
106 0 : }
107 :
108 0 : TLOG_DEBUG(6) << "Processing DetectorToDaqConnection " << d2d_conn->UID();
109 : // get the readout groups and the interfaces and streams therein; 1 reaout group corresponds to 1 data reader module
110 :
111 0 : std::vector<const confmodel::DetectorStream*> enabled_det_streams;
112 : // Loop over streams
113 0 : for (auto stream : d2d_conn->streams()) {
114 :
115 : // Are we sure?
116 0 : if (stream->is_disabled(*session)) {
117 0 : TLOG_DEBUG(7) << "Ignoring disabled DetectorStream " << stream->UID();
118 0 : continue;
119 0 : }
120 :
121 0 : enabled_det_streams.push_back(stream);
122 0 : }
123 :
124 : // Create the raw data queues
125 0 : std::vector<const conffwk::ConfigObject*> data_queue_objs;
126 : // keep a map for convenience
127 :
128 : // Create data queues
129 0 : for (auto ds : enabled_det_streams) {
130 0 : conffwk::ConfigObject queue_obj = obj_fac.create_queue_sid_obj(dlh_input_qdesc, ds);
131 0 : const auto* data_queue = obj_fac.get_dal<confmodel::Connection>(queue_obj.UID());
132 0 : data_queue_objs.push_back(&data_queue->config_object());
133 0 : data_queues_by_sid[ds->get_source_id()] = data_queue;
134 0 : }
135 :
136 : //-----------------------------------------------------------------
137 : //
138 : // Create DataReaderModule object
139 : //
140 :
141 : //
142 : // Instantiate DataReaderModule of type CRTBernReaderModule/CRTGrenobleReaderModule
143 : //
144 :
145 : // Create the Data reader object
146 :
147 0 : std::string reader_uid(fmt::format("crtdatareader-{}-{}", this->UID(), std::to_string(conn_idx++)));
148 0 : TLOG_DEBUG(6) << fmt::format("creating OKS configuration object for Data reader class {} with id {}", reader_class, reader_uid);
149 0 : auto reader_obj = obj_fac.create(reader_class, reader_uid);
150 :
151 : // Populate configuration and interfaces (leave output queues for later)
152 0 : reader_obj.set_obj("configuration", &reader_conf->config_object());
153 0 : reader_obj.set_objs("connections", {&d2d_conn->config_object()});
154 0 : reader_obj.set_objs("outputs", data_queue_objs);
155 :
156 0 : modules.push_back(obj_fac.get_dal<confmodel::DaqModule>(reader_obj.UID()));
157 :
158 : //-----------------------------------------------------------------
159 : //
160 : // Create DataWriterModule objects
161 : //
162 :
163 : //
164 : // Instantiate DataWriterModule of type SocketWriterModule
165 : //
166 :
167 : // Create the SocketWriterModule objects
168 :
169 0 : conn_idx = 0;
170 :
171 0 : for (const auto writer_conf : writer_confs) {
172 :
173 0 : const std::string writer_class = writer_conf->get_template_for();
174 :
175 0 : std::string writer_uid(fmt::format("socketdatawriter-{}-{}", this->UID(), std::to_string(conn_idx++)));
176 0 : TLOG_DEBUG(6) << fmt::format(
177 0 : "Creating OKS configuration object for socket data writer class {} with id {}", writer_class, writer_uid);
178 0 : auto writer_obj = obj_fac.create(writer_class, writer_uid);
179 :
180 : // Populate configuration and interfaces
181 0 : writer_obj.set_obj("configuration", &writer_conf->config_object());
182 0 : writer_obj.set_objs("connections", {&d2d_conn->config_object()});
183 0 : writer_obj.set_objs("inputs", data_queue_objs);
184 :
185 0 : modules.push_back(obj_fac.get_dal<confmodel::DaqModule>(writer_obj.UID()));
186 0 : }
187 0 : }
188 :
189 0 : obj_fac.update_modules(modules);
190 0 : }
191 :
192 : } // namespace dunedaq::appmodel
|