DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
dalMethods.cpp
Go to the documentation of this file.
1
10
24#include "confmodel/Segment.hpp"
25#include "confmodel/Service.hpp"
26#include "confmodel/Session.hpp"
29
31
34#include "conffwk/Schema.hpp"
35#include "nlohmann/json.hpp"
36
37#include <iostream>
38#include <list>
39#include <set>
40
41using namespace dunedaq::conffwk;
42
43// Stolen from ATLAS dal package
44namespace {
50
51void
52make_parents_list(const ConfigObjectImpl* child,
54 std::vector<const dunedaq::confmodel::ExcludableEntity*>& p_list,
55 std::list<std::vector<const dunedaq::confmodel::ExcludableEntity*>>& out,
57{
58 dunedaq::confmodel::AddTestOnCircularDependency add_fuse_test(cd_fuse, resource_set);
59
60 // add the resource set to the path
61 p_list.push_back(resource_set);
62
63 // check if the application is in the resource relationship, i.e. is a resource or belongs to resource set(s)
64 for (const auto& i : resource_set->contained_excludable_entities()) {
65 if (i->config_object().implementation() == child) {
66 out.push_back(p_list);
68 make_parents_list(child, rs, p_list, out, cd_fuse);
69 }
70 }
71
72 // remove the resource set from the path
73 p_list.pop_back();
74}
75
76void
77make_parents_list(const dunedaq::conffwk::ConfigObjectImpl* child,
78 const dunedaq::confmodel::Segment* segment,
79 std::vector<const dunedaq::confmodel::ExcludableEntity*>& p_list,
80 std::list<std::vector<const dunedaq::confmodel::ExcludableEntity*>>& out,
81 bool is_segment,
83{
84 dunedaq::confmodel::AddTestOnCircularDependency add_fuse_test(cd_fuse, segment);
85
86 // add the segment to the path
87 p_list.push_back(segment);
88
89 // check if the application is in the nested segment
90 for (const auto& seg : segment->get_segments()) {
91 if (seg->config_object().implementation() == child)
92 out.push_back(p_list);
93 else
94 make_parents_list(child, seg, p_list, out, is_segment, cd_fuse);
95 }
96 if (!is_segment) {
97 for (const auto& app : segment->get_applications()) {
98 if (app->config_object().implementation() == child)
99 out.push_back(p_list);
100 else if (const auto resource_set = app->cast<dunedaq::confmodel::ExcludableEntitySet>())
101 make_parents_list(child, resource_set, p_list, out, cd_fuse);
102 }
103 }
104
105 // remove the segment from the path
106
107 p_list.pop_back();
108}
109
110void
111check_segment(std::list<std::vector<const dunedaq::confmodel::ExcludableEntity*>>& out,
112 const dunedaq::confmodel::Segment* segment,
114 bool is_segment,
116{
117 dunedaq::confmodel::AddTestOnCircularDependency add_fuse_test(cd_fuse, segment);
118
119 std::vector<const dunedaq::confmodel::ExcludableEntity*> compList;
120
121 if (segment->config_object().implementation() == child) {
122 out.push_back(compList);
123 }
124 make_parents_list(child, segment, compList, out, is_segment, cd_fuse);
125}
126} // namespace
127
128namespace dunedaq::confmodel {
129
130void
131ExcludableEntity::parents(const Session& session, std::list<std::vector<const ExcludableEntity*>>& parents) const
132{
133 const ConfigObjectImpl* obj_impl = config_object().implementation();
134
135 const bool is_segment = castable(Segment::s_class_name);
136
137 try {
138 TestCircularDependency cd_fuse("component parents", &session);
139
140 // check session's segment
141 check_segment(parents, session.get_segment(), obj_impl, is_segment, cd_fuse);
142
143 if (parents.empty()) {
144 TLOG_DEBUG(1) << "cannot find segment/resource path(s) between ExcludableEntity " << this << " and session "
145 << &session << " objects (check this object is linked with the session as a segment or a resource)";
146 }
147 } catch (ers::Issue& ex) {
148 ers::error(CannotGetParents(ERS_HERE, full_name(), ex));
149 }
150}
151
152// ========================================================================
153
154std::vector<const Application*>
155Session::getSegmentApps(const Segment* segment, bool included_only) const
156{
157 std::vector<const Application*> apps;
158 auto segapps = segment->get_applications();
159 if (included_only) {
160 for (auto app : segapps) {
161 auto comp = app->cast<ExcludableEntity>();
162 if (comp == nullptr || !comp->is_excluded(*this)) {
163 apps.insert(apps.end(), app);
164 }
165 }
166 } else {
167 apps.swap(segapps);
168 }
169 for (auto seg : segment->get_segments()) {
170 if (!included_only || !seg->is_excluded(*this)) {
171 auto segapps = getSegmentApps(seg, included_only);
172 apps.insert(apps.end(), segapps.begin(), segapps.end());
173 }
174 }
175 return apps;
176}
177
178std::vector<const Application*>
180{
181 std::vector<const Application*> apps;
182 auto segapps = getSegmentApps(get_segment(), false);
183 apps.insert(apps.end(), segapps.begin(), segapps.end());
184 return apps;
185}
186
187std::vector<const Application*>
189{
190 std::vector<const Application*> apps;
191 auto segapps = getSegmentApps(get_segment(), true);
192 apps.insert(apps.end(), segapps.begin(), segapps.end());
193 return apps;
194}
195
196// ========================================================================
197
198std::set<const HostComponent*>
200{
201 std::set<const HostComponent*> res;
202 for (auto module : get_modules()) {
203 for (auto hostresource : module->get_used_host_components()) {
204 res.insert(hostresource);
205 }
206 }
207 return res;
208}
209
210namespace {
211nlohmann::json
212get_json_config(conffwk::Configuration& confdb,
213 const std::string& class_name,
214 const std::string& uid,
215 bool direct_only,
216 bool skip_object_name)
217{
218 using nlohmann::json;
219 using namespace conffwk;
220 TLOG_DBG(9) << "Getting attributes for " << uid << " of class " << class_name;
221 json attributes;
222 auto class_info = confdb.get_class_info(class_name);
224 confdb.get(class_name, uid, obj);
225 for (auto attr : class_info.p_attributes) {
226 if (attr.p_type == type_t::u8_type) {
227 add_json_value<uint8_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
228 } else if (attr.p_type == type_t::u16_type) {
229 add_json_value<uint16_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
230 } else if (attr.p_type == type_t::u32_type) {
231 add_json_value<uint32_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
232 } else if (attr.p_type == type_t::u64_type) {
233 add_json_value<uint64_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
234 } else if (attr.p_type == type_t::s8_type) {
235 add_json_value<int8_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
236 } else if (attr.p_type == type_t::s16_type) {
237 add_json_value<int16_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
238 } else if (attr.p_type == type_t::s32_type || attr.p_type == type_t::s16_type) {
239 add_json_value<int32_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
240 } else if (attr.p_type == type_t::s64_type) {
241 add_json_value<int64_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
242 } else if (attr.p_type == type_t::float_type) {
243 add_json_value<float>(obj, attr.p_name, attr.p_is_multi_value, attributes);
244 } else if (attr.p_type == type_t::double_type) {
245 add_json_value<double>(obj, attr.p_name, attr.p_is_multi_value, attributes);
246 } else if (attr.p_type == type_t::bool_type) {
247 add_json_value<bool>(obj, attr.p_name, attr.p_is_multi_value, attributes);
248 } else if ((attr.p_type == type_t::string_type) || (attr.p_type == type_t::enum_type) ||
249 (attr.p_type == type_t::date_type) || (attr.p_type == type_t::time_type)) {
250 add_json_value<std::string>(obj, attr.p_name, attr.p_is_multi_value, attributes);
251 }
252 }
253 if (!direct_only) {
254 TLOG_DBG(9) << "Processing relationships";
255 for (auto iter : class_info.p_relationships) {
256 std::string rel_name = iter.p_name;
257 if (iter.p_cardinality == cardinality_t::zero_or_one || iter.p_cardinality == cardinality_t::only_one) {
258 ConfigObject rel_obj;
259 obj.get(rel_name, rel_obj);
260 if (!rel_obj.is_null()) {
261 TLOG_DBG(9) << "Getting attibute of relationship " << rel_name;
262 attributes[rel_name] =
263 get_json_config(confdb, rel_obj.class_name(), rel_obj.UID(), direct_only, skip_object_name);
264 } else {
265 TLOG_DBG(9) << "Relationship " << rel_name << " not set";
266 }
267 } else {
268 TLOG_DBG(9) << "Relationship " << rel_name << " is multi value. "
269 << "Getting attibutes for relationship.";
270 std::vector<ConfigObject> rel_vec;
271 obj.get(rel_name, rel_vec);
272 std::vector<json> configs;
273 for (auto rel_obj : rel_vec) {
274 TLOG_DBG(9) << "Getting attibute of relationship " << rel_obj.UID();
275 auto rel_conf = get_json_config(confdb, rel_obj.class_name(), rel_obj.UID(), direct_only, skip_object_name);
276 configs.push_back(rel_conf);
277 }
278 attributes[rel_name] = configs;
279 }
280 }
281 }
282
283 if (skip_object_name) {
284 return attributes;
285 }
286 json json_config;
287 json_config[uid] = attributes;
288 return json_config;
289}
290} // namespace
291
292nlohmann::json
293Jsonable::to_json(bool direct_only, bool skip_object_name) const
294{
295 return get_json_config(p_registry.configuration(), class_name(), UID(), direct_only, skip_object_name);
296}
297
298const std::vector<std::string>
305
306const std::vector<std::string>
309{
310
311 const std::string configuration_uri = confdb.get_impl_spec();
312 const dunedaq::confmodel::Service* control_service = nullptr;
313
314 const std::string controller_log_level = session->get_controller_log_level();
315
316 for (auto const* as : get_exposes_service()) {
317 if (as->UID().ends_with("_control")) {
318 if (control_service)
319 throw DuplicatedControlService(ERS_HERE, as->UID());
320 control_service = as;
321 }
322 }
323
324 if (control_service == nullptr)
325 throw NoControlServiceDefined(ERS_HERE, UID());
326
327 const std::string control_uri = control_service->get_protocol() + "://" + get_runs_on()->get_runs_on()->UID() + ":" +
328 std::to_string(control_service->get_port());
329
330 std::vector<std::string> ret = { "-l", controller_log_level };
331 ret.push_back(configuration_uri);
332 ret.push_back(control_uri);
333 ret.push_back(UID());
334 ret.push_back(session->UID());
335 return ret;
336}
337
338std::vector<const confmodel::DetectorStream*>
340{
341 std::vector<const confmodel::DetectorStream*> all_streams;
342 // Loop over senders
343 for (auto sender : this->senders()) {
344 auto sender_streams = sender->get_streams();
345 all_streams.insert(all_streams.end(), sender_streams.begin(), sender_streams.end());
346 }
347 return all_streams;
348}
349
350std::string
351OpMonURI::get_URI(const std::string& /* app */) const
352{
353
354 auto type = get_type();
355 if (type == "file") {
356 return type + "://" + get_path();
357 }
358
359 if (type == "stream") {
360 return type + "://" + get_path();
361 }
362
363 return "stdout://";
364}
365
366// ========================================================================
367void
369{
370 auto excluded_vec = get_excluded();
371 for (auto excluded_resource : excluded_vec) {
372 if (excluded_resource == res) {
373 return;
374 }
375 }
376 excluded_vec.push_back(res);
377
378 set_excluded(excluded_vec);
380
381 m_excluded_entities.update(root_entity(), excluded_vec);
382}
383void
385{
386 auto excluded_vec = get_excluded();
387 auto count = std::erase(excluded_vec, res);
388 if (count == 0) {
389 return;
390 }
391 set_excluded(excluded_vec);
393
394 m_excluded_entities.update(root_entity(), excluded_vec);
395}
396
397bool
402bool
403ExcludableEntity::compute_excluded_state(const std::set<std::string>& excluded_resources) const
404{
405 TLOG_DEBUG(6) << "No compute_excluded_state method defined for ExcludableEntity " << class_name();
406 if (excluded_resources.contains(UID())) {
407 return true;
408 }
409 return false;
410}
411
412std::vector<const ExcludableEntity*>
417
418std::vector<const ExcludableEntity*>
420{
421 auto res = to_resources(senders());
422 auto rec = receiver();
423 if (rec)
424 res.push_back(rec);
425 return res;
426}
427
428bool
429DetectorToDaqConnection::compute_excluded_state(const std::set<std::string>& excluded_resources) const
430{
431 if (excluded_resources.contains(UID())) {
432 return true;
433 }
434 bool send_excluded = true;
435 for (auto sender : senders()) {
436 if (!sender->compute_excluded_state(excluded_resources)) {
437 send_excluded = false;
438 break;
439 }
440 }
441 TLOG_DBG(6) << "receiver excluded=" << receiver()->compute_excluded_state(excluded_resources)
442 << " senders excluded=" << send_excluded;
443 auto rec = receiver();
444 if (!rec)
445 return send_excluded;
446
447 return (rec->compute_excluded_state(excluded_resources) || send_excluded);
448}
449
450std::vector<const ExcludableEntity*>
452{
453 // All our contained segments are resources
454 std::vector<const ExcludableEntity*> resources = to_resources(get_segments());
455
456 // Only a subset of our applications might be resources so check individually
457 for (auto app : get_applications()) {
458 TLOG_DBG(6) << "Checking " << app->UID();
459 auto res = app->cast<const ExcludableEntity>();
460 if (res != nullptr) {
461 TLOG_DBG(6) << "Adding " << app->UID();
462 resources.push_back(res);
463 }
464 }
465 TLOG_DBG(6) << "Returning vector of " << resources.size() << " resources";
466 return resources;
467}
468
469bool
470Segment::compute_excluded_state(const std::set<std::string>& excluded) const
471{
472 if (excluded.contains(UID())) {
473 return true;
474 }
475 for (auto app : get_applications()) {
476 auto res = app->cast<const ExcludableEntity>();
477 if (res == nullptr) {
478 return false;
479 }
480 }
481 for (auto res : contained_excludable_entities()) {
482 if (!res->compute_excluded_state(excluded)) {
483 return false;
484 }
485 }
486 return true;
487}
488
489} // namespace dunedaq::confmodel
#define ERS_HERE
Implements database objects.
Represents database objects.
const std::string & UID() const noexcept
Return object identity.
bool is_null() const noexcept
Check if object's implementation points to null.
const ConfigObjectImpl * implementation() const noexcept
Returns pointer on implementation.
const std::string & class_name() const noexcept
Return object's class name.
void get(const std::string &class_name, const std::string &id, ConfigObject &object, unsigned long rlevel=0, const std::vector< std::string > *rclasses=0)
Get object by class name and object id (multi-thread safe).
void update(const std::vector< std::string > &modified, const std::vector< std::string > &removed, const std::vector< std::string > &created) noexcept
Update cache of objects in case of modification.
const std::string & get_impl_spec() const noexcept
const dunedaq::conffwk::class_t & get_class_info(const std::string &class_name, bool direct_only=false)
The method provides access to description of class.
std::string full_name() const noexcept
bool castable(const std::string &target) const noexcept
const TARGET * cast() const noexcept
Casts object to different class.
const std::string & class_name() const noexcept
Configuration & configuration() const noexcept
const ConfigObject & config_object() const
const std::string & UID() const noexcept
DalRegistry & p_registry
Configuration object.
Configuration & configuration()
const std::vector< const dunedaq::confmodel::Service * > & get_exposes_service() const
Get "exposes_service" relationship value. Services exposed i.e. provided by this application.
const dunedaq::confmodel::VirtualHost * get_runs_on() const
Get "runs_on" relationship value. VirtualHost to run this application on.
const std::vector< const dunedaq::confmodel::DaqModule * > & get_modules() const
Get "modules" relationship value.
const std::vector< std::string > construct_commandline_parameters(const conffwk::Configuration &confdb, const dunedaq::confmodel::Session *session) const
std::set< const dunedaq::confmodel::HostComponent * > get_used_host_components() const
virtual std::vector< const ExcludableEntity * > contained_excludable_entities() const override
const std::vector< const dunedaq::confmodel::DetectorStream * > & get_streams() const
Get "streams" relationship value.
virtual const DetDataReceiver * receiver() const =0
bool compute_excluded_state(const std::set< std::string > &excluded) const final
std::vector< const confmodel::DetectorStream * > streams() const
virtual std::vector< const DetDataSender * > senders() const =0
virtual std::vector< const ExcludableEntity * > contained_excludable_entities() const override
virtual std::vector< const ExcludableEntity * > contained_excludable_entities() const =0
const dunedaq::confmodel::ExcludedEntities & excluded_entities() const
virtual const ExcludableEntitySet * root_entity() const =0
void exclude(const ExcludableEntity *)
void include(const ExcludableEntity *)
const std::vector< const dunedaq::confmodel::ExcludableEntity * > & get_excluded() const
Get "excluded" relationship value. ExcludableEntitys that should not participate in the current run.
void set_excluded(const std::vector< const dunedaq::confmodel::ExcludableEntity * > &value)
Set "excluded" relationship value. ExcludableEntitys that should not participate in the current run.
ExcludableEntityTree(conffwk::DalRegistry &db, const conffwk::ConfigObject &obj) noexcept
bool is_excluded(const dunedaq::confmodel::ExcludableEntityTree &session) const
void parents(const dunedaq::confmodel::Session &session, std::list< std::vector< const dunedaq::confmodel::ExcludableEntity * > > &parents) const
virtual bool compute_excluded_state(const std::set< std::string > &) const
void update(const ExcludableEntitySet *root, std::vector< const ExcludableEntity * > initial_list)
bool is_included(const ExcludableEntity *component) const
nlohmann::json to_json(bool direct=false, bool skip_name=false) const
std::string get_URI(const std::string &app) const
const std::string & get_type() const
Get "type" attribute value. type of the OpMonFacility.
Definition OpMonURI.hpp:137
const std::string & get_path() const
Get "path" attribute value. property used to generate the final URI.
Definition OpMonURI.hpp:94
const std::vector< std::string > construct_commandline_parameters(const conffwk::Configuration &confdb, const dunedaq::confmodel::Session *session) const
virtual std::vector< const ExcludableEntity * > contained_excludable_entities() const
bool compute_excluded_state(const std::set< std::string > &excluded) const final
const std::vector< const dunedaq::confmodel::Segment * > & get_segments() const
Get "segments" relationship value. Nested list of Segments that form part of this Segment.
Definition Segment.hpp:114
const std::vector< const dunedaq::confmodel::Application * > & get_applications() const
Get "applications" relationship value. List of Applications that run in this Segment.
Definition Segment.hpp:141
static const std::string & s_class_name
Definition Segment.hpp:54
const std::string & get_protocol() const
Get "protocol" attribute value.
Definition Service.hpp:99
uint16_t get_port() const
Get "port" attribute value.
Definition Service.hpp:130
const dunedaq::confmodel::Segment * get_segment() const
Get "segment" relationship value. List of configuration Segments that form this Session.
Definition Session.hpp:419
std::vector< const dunedaq::confmodel::Application * > included_applications() const
std::vector< const dunedaq::confmodel::Application * > all_applications() const
std::vector< const Application * > getSegmentApps(const Segment *, bool) const
const dunedaq::confmodel::PhysicalHost * get_runs_on() const
Get "runs_on" relationship value. The physical host that this virtual host runs on.
conffwk entry point
std::vector< const dunedaq::confmodel::ExcludableEntity * > to_resources(const std::vector< T * > &vector_of_children)
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:116
std::vector< T > attributes(tref const &item)
const std::vector< std::string > construct_commandline_parameters_appfwk(const T *app, const conffwk::Configuration &confdb, const dunedaq::confmodel::Session *session)
Definition util.hpp:77
void add_json_value(conffwk::ConfigObject &obj, std::string &name, bool multi_value, nlohmann::json &attributes)
Definition util.hpp:62
FELIX Initialization std::string initerror FELIX queue timed out
msgpack::object obj
void error(const Issue &issue)
Definition ers.hpp:101