Line data Source code
1 : /**
2 : * @file TriggerApplication.cpp
3 : *
4 : * Implementation of TriggerApplication'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 "conffwk/Configuration.hpp"
13 :
14 : #include "confmodel/Connection.hpp"
15 : #include "confmodel/NetworkConnection.hpp"
16 : #include "confmodel/ResourceSet.hpp"
17 : #include "confmodel/Service.hpp"
18 : #include "confmodel/Session.hpp"
19 :
20 : #include "ConfigObjectFactory.hpp"
21 : #include "appmodel/DataSubscriberModule.hpp"
22 : #include "appmodel/DataReaderConf.hpp"
23 : #include "appmodel/DataRecorderConf.hpp"
24 :
25 : #include "appmodel/DataHandlerModule.hpp"
26 : #include "appmodel/DataHandlerConf.hpp"
27 :
28 : #include "appmodel/NetworkConnectionRule.hpp"
29 : #include "appmodel/QueueConnectionRule.hpp"
30 :
31 : #include "appmodel/QueueDescriptor.hpp"
32 : #include "appmodel/NetworkConnectionDescriptor.hpp"
33 :
34 : #include "appmodel/SourceIDConf.hpp"
35 :
36 : #include "appmodel/TriggerApplication.hpp"
37 : #include "appmodel/DFApplication.hpp"
38 : #include "appmodel/appmodelIssues.hpp"
39 :
40 : #include "logging/Logging.hpp"
41 :
42 : #include <string>
43 : #include <vector>
44 :
45 : namespace dunedaq {
46 : namespace appmodel {
47 :
48 : /**
49 : * \brief Helper function that gets a network connection config
50 : *
51 : * \param idname Unique ID name of the config object
52 : * \param ntDesc Network connection descriptor object
53 : * \param confdb Global database configuration
54 : * \param dbfile Database file location
55 : *
56 : * \ret OKS configuration object for the network connection
57 : */
58 : conffwk::ConfigObject
59 0 : create_network_connection(std::string uid,
60 : const NetworkConnectionDescriptor* ntDesc,
61 : conffwk::Configuration* confdb,
62 : const std::string& dbfile)
63 : {
64 0 : auto ntServiceObj = ntDesc->get_associated_service()->config_object();
65 0 : conffwk::ConfigObject ntObj;
66 0 : confdb->create(dbfile, "NetworkConnection", uid, ntObj);
67 0 : ntObj.set_by_val<std::string>("data_type", ntDesc->get_data_type());
68 0 : ntObj.set_by_val<std::string>("connection_type", ntDesc->get_connection_type());
69 0 : ntObj.set_obj("associated_service", &ntServiceObj);
70 :
71 0 : return ntObj;
72 0 : }
73 :
74 :
75 : void
76 0 : TriggerApplication::generate_modules(const confmodel::Session* session) const
77 : {
78 :
79 0 : std::vector<const confmodel::DaqModule*> modules;
80 :
81 0 : ConfigObjectFactory obj_fac(this);
82 :
83 0 : auto ti_conf = get_trigger_inputs_handler();
84 0 : auto ti_class = ti_conf->get_template_for();
85 0 : std::string handler_name("");
86 : // Process the queue rules looking for inputs to our trigger handler modules
87 0 : const QueueDescriptor* ti_inputq_desc = nullptr;
88 :
89 0 : for (auto rule : get_queue_rules()) {
90 0 : auto destination_class = rule->get_destination_class();
91 0 : auto data_type = rule->get_descriptor()->get_data_type();
92 0 : if (destination_class == "DataHandlerModule" || destination_class == ti_class) {
93 0 : ti_inputq_desc = rule->get_descriptor();
94 : }
95 0 : }
96 : // Process the network rules looking for the TP handler data reuest inputs
97 0 : const NetworkConnectionDescriptor* req_net_desc = nullptr;
98 0 : const NetworkConnectionDescriptor* tin_net_desc = nullptr;
99 0 : const NetworkConnectionDescriptor* tout_net_desc = nullptr;
100 0 : const NetworkConnectionDescriptor* tset_out_net_desc = nullptr;
101 0 : for (auto rule : get_network_rules()) {
102 0 : auto endpoint_class = rule->get_endpoint_class();
103 0 : auto data_type = rule->get_descriptor()->get_data_type();
104 :
105 0 : if (data_type == "DataRequest") {
106 0 : req_net_desc = rule->get_descriptor();
107 : }
108 0 : else if (data_type == "TASet" || data_type == "TCSet"){
109 0 : tset_out_net_desc = rule->get_descriptor();
110 : }
111 0 : else if (endpoint_class == "DataSubscriberModule") {
112 0 : if (!tin_net_desc) {
113 0 : tin_net_desc = rule->get_descriptor();
114 : }
115 0 : else if (rule->get_descriptor()->get_data_type() == tin_net_desc->get_data_type()) {
116 : // For now endpoint_class of DataSubscriberModule for both input and output
117 : // with the same data type is not possible.
118 0 : throw (BadConf(ERS_HERE, "Have two network connections of the same data_type and the same endpoint_class"));
119 : }
120 0 : else if (tin_net_desc->get_data_type() == "TriggerActivity" &&
121 0 : rule->get_descriptor()->get_data_type() == "TriggerCandidate") {
122 : // For TA->TC
123 0 : tout_net_desc = rule->get_descriptor();
124 0 : handler_name = "tahandler";
125 : }
126 0 : else if (tin_net_desc->get_data_type() == "TriggerCandidate" &&
127 0 : rule->get_descriptor()->get_data_type() == "TriggerActivity") {
128 : // For TA->TC if we saved TC network connection as input first...
129 0 : tout_net_desc = tin_net_desc;
130 0 : tin_net_desc = rule->get_descriptor();
131 0 : handler_name = "tahandler";
132 : }
133 : else {
134 0 : throw (BadConf(ERS_HERE, "Unexpected input & output network connection descriptors provided"));
135 : }
136 : }
137 0 : else if (data_type == "TriggerActivity" || data_type == "TriggerCandidate"){
138 0 : tout_net_desc = rule->get_descriptor();
139 0 : if (data_type == "TriggerActivity")
140 0 : handler_name = "tphandler";
141 : else
142 0 : handler_name = "tahandler";
143 : }
144 0 : }
145 :
146 : // Process special Network rules!
147 : // Looking for Fragment rules from DFAppplications in current Session
148 0 : auto sessionApps = session->enabled_applications();
149 0 : std::vector<conffwk::ConfigObject> fragOutObjs;
150 0 : for (auto app : sessionApps) {
151 0 : auto dfapp = app->cast<appmodel::DFApplication>();
152 0 : if (dfapp == nullptr)
153 0 : continue;
154 :
155 0 : auto dfNRules = dfapp->get_network_rules();
156 0 : for (auto rule : dfNRules) {
157 0 : auto descriptor = rule->get_descriptor();
158 0 : auto data_type = descriptor->get_data_type();
159 0 : if (data_type == "Fragment") {
160 : // std::string dreqNetUid(descriptor->get_uid_base() + )
161 0 : auto frag_conn = obj_fac.create_net_obj(descriptor, dfapp->UID());
162 :
163 0 : fragOutObjs.push_back(frag_conn);
164 0 : } // If network rule has TriggerDecision type of data
165 0 : } // Loop over Apps network rules
166 0 : } // loop over Session specific Apps
167 :
168 :
169 0 : if ( req_net_desc== nullptr) {
170 0 : throw (BadConf(ERS_HERE, "No network descriptor given to receive request and send data was set"));
171 : }
172 0 : if ( tin_net_desc== nullptr) {
173 0 : throw (BadConf(ERS_HERE, "No network descriptor given to receive trigger objects"));
174 : }
175 0 : if ( tout_net_desc== nullptr) {
176 0 : throw (BadConf(ERS_HERE, "No network descriptor given to publish trigger objects"));
177 : }
178 0 : if (ti_inputq_desc == nullptr) {
179 0 : throw (BadConf(ERS_HERE, "No data input queue descriptor given"));
180 : }
181 :
182 0 : auto input_queue_obj = obj_fac.create_queue_obj(ti_inputq_desc);
183 :
184 0 : auto req_net_obj = obj_fac.create_net_obj(req_net_desc, UID());
185 :
186 0 : auto tin_net_obj = obj_fac.create_net_obj(tin_net_desc, ".*");
187 :
188 0 : auto tout_net_obj = obj_fac.create_net_obj(tout_net_desc, UID());
189 0 : conffwk::ConfigObject tset_out_net_obj;
190 0 : if (tset_out_net_desc) {
191 0 : tset_out_net_obj = obj_fac.create_net_obj(tset_out_net_desc, UID());
192 : }
193 :
194 :
195 : // build up the full list of outputs
196 0 : std::vector<const conffwk::ConfigObject*> ti_output_objs;
197 0 : for (auto& fNet : fragOutObjs) {
198 0 : ti_output_objs.push_back(&fNet);
199 : }
200 0 : ti_output_objs.push_back(&tout_net_obj);
201 0 : if (tset_out_net_desc!= nullptr) {
202 0 : ti_output_objs.push_back(&tset_out_net_obj);
203 : }
204 :
205 0 : if (get_source_id() == nullptr) {
206 0 : throw(BadConf(ERS_HERE, "No source_id associated with this TriggerApplication!"));
207 : }
208 0 : uint32_t source_id = get_source_id()->get_sid();
209 0 : std::string ti_uid(handler_name + "-" + std::to_string(source_id));
210 0 : auto ti_obj = obj_fac.create(ti_class, ti_uid);
211 :
212 0 : ti_obj.set_by_val<uint32_t>("source_id", source_id);
213 0 : ti_obj.set_by_val<uint32_t>("detector_id", 1); // 1 == kDAQ
214 0 : ti_obj.set_by_val<bool>("post_processing_enabled", !get_tx_generation_disabled());
215 :
216 0 : auto ti_conf_obj = ti_conf->config_object();
217 0 : ti_obj.set_obj("module_configuration", &ti_conf_obj);
218 0 : ti_obj.set_objs("inputs", {&input_queue_obj, &req_net_obj});
219 0 : ti_obj.set_objs("outputs", ti_output_objs);
220 : // Add to our list of modules to return
221 0 : modules.push_back(obj_fac.get_dal<DataHandlerModule>(ti_uid));
222 :
223 :
224 : // Now create the DataSubscriberModule object
225 0 : auto rdr_conf = get_data_subscriber();
226 0 : if (rdr_conf == nullptr) {
227 0 : throw (BadConf(ERS_HERE, "No DataReaderModule configuration given"));
228 : }
229 :
230 : // Create a DataReaderModule
231 :
232 0 : std::string reader_uid("data-reader-"+UID());
233 0 : std::string reader_class = rdr_conf->get_template_for();
234 0 : TLOG_DEBUG(7) << "creating OKS configuration object for Data subscriber class " << reader_class;
235 0 : auto reader_obj = obj_fac.create(reader_class, reader_uid);
236 0 : reader_obj.set_objs("inputs", {&tin_net_obj} );
237 0 : reader_obj.set_objs("outputs", {&input_queue_obj} );
238 0 : reader_obj.set_obj("configuration", &rdr_conf->config_object());
239 :
240 0 : modules.push_back(obj_fac.get_dal<DataSubscriberModule>(reader_uid));
241 :
242 :
243 0 : obj_fac.update_modules(modules);
244 0 : }
245 :
246 : } // namespace appmodel
247 : } // namespace dunedaq
|