LCOV - code coverage report
Current view: top level - confmodel/src - dalMethods.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 32.0 % 225 72
Test Date: 2025-12-21 13:07:08 Functions: 48.5 % 33 16

            Line data    Source code
       1              : /**
       2              :  * @file dalMethods.cxx
       3              :  *
       4              :  * Implementations of Methods defined in confmodel schema classes
       5              :  *
       6              :  * This is part of the DUNE DAQ Software Suite, copyright 2020.
       7              :  * Licensing/copyright details are in the COPYING file that you should have
       8              :  * received with this code.
       9              :  */
      10              : 
      11              : #include "confmodel/Application.hpp"
      12              : #include "confmodel/confmodelIssues.hpp"
      13              : #include "confmodel/DaqApplication.hpp"
      14              : #include "confmodel/DaqModule.hpp"
      15              : #include "confmodel/DetDataSender.hpp"
      16              : #include "confmodel/DetDataReceiver.hpp"
      17              : #include "confmodel/DetectorToDaqConnection.hpp"
      18              : #include "confmodel/DetectorStream.hpp"
      19              : #include "confmodel/Jsonable.hpp"
      20              : #include "confmodel/OpMonURI.hpp"
      21              : #include "confmodel/PhysicalHost.hpp"
      22              : #include "confmodel/RCApplication.hpp"
      23              : #include "confmodel/Resource.hpp"
      24              : #include "confmodel/ResourceSet.hpp"
      25              : #include "confmodel/Segment.hpp"
      26              : #include "confmodel/Session.hpp"
      27              : #include "confmodel/Service.hpp"
      28              : #include "confmodel/VirtualHost.hpp"
      29              : 
      30              : #include "confmodel/test_circular_dependency.hpp"
      31              : 
      32              : #include "nlohmann/json.hpp"
      33              : #include "conffwk/ConfigObject.hpp"
      34              : #include "conffwk/Configuration.hpp"
      35              : #include "conffwk/Schema.hpp"
      36              : 
      37              : #include <list>
      38              : #include <set>
      39              : #include <iostream>
      40              : 
      41              : using namespace dunedaq::conffwk;
      42              : 
      43              : 
      44              : // Stolen from ATLAS dal package
      45              : namespace {
      46              :   /**
      47              :    *  Static function to calculate list of components
      48              :    *  from the root segment to the lowest component which
      49              :    *  the child object (a segment or a resource) belongs.
      50              :    */
      51              : 
      52              : void
      53            0 : make_parents_list(
      54              :     const ConfigObjectImpl * child,
      55              :     const dunedaq::confmodel::ResourceSet * resource_set,
      56              :     std::vector<const dunedaq::confmodel::Resource *> & p_list,
      57              :     std::list< std::vector<const dunedaq::confmodel::Resource *> >& out,
      58              :     dunedaq::confmodel::TestCircularDependency& cd_fuse)
      59              : {
      60            0 :   dunedaq::confmodel::AddTestOnCircularDependency add_fuse_test(cd_fuse, resource_set);
      61              : 
      62              :   // add the resource set to the path
      63            0 :   p_list.push_back(resource_set);
      64              : 
      65              :   // check if the application is in the resource relationship, i.e. is a resource or belongs to resource set(s)
      66            0 :   for (const auto& i : resource_set->contained_resources()) {
      67            0 :     if (i->config_object().implementation() == child) {
      68            0 :       out.push_back(p_list);
      69              :     }
      70            0 :     else if (const dunedaq::confmodel::ResourceSet * rs = i->cast<dunedaq::confmodel::ResourceSet>()) {
      71            0 :       make_parents_list(child, rs, p_list, out, cd_fuse);
      72              :     }
      73            0 :   }
      74              : 
      75              :   // remove the resource set from the path
      76            0 :   p_list.pop_back();
      77            0 : }
      78              : 
      79              : void
      80            0 : make_parents_list(
      81              :     const dunedaq::conffwk::ConfigObjectImpl * child,
      82              :     const dunedaq::confmodel::Segment * segment,
      83              :     std::vector<const dunedaq::confmodel::Resource *> & p_list,
      84              :     std::list<std::vector<const dunedaq::confmodel::Resource *> >& out,
      85              :     bool is_segment,
      86              :     dunedaq::confmodel::TestCircularDependency& cd_fuse)
      87              : {
      88            0 :   dunedaq::confmodel::AddTestOnCircularDependency add_fuse_test(cd_fuse, segment);
      89              : 
      90              :   // add the segment to the path
      91            0 :   p_list.push_back(segment);
      92              : 
      93              :   // check if the application is in the nested segment
      94            0 :   for (const auto& seg : segment->get_segments()) {
      95            0 :     if (seg->config_object().implementation() == child)
      96            0 :       out.push_back(p_list);
      97              :     else
      98            0 :       make_parents_list(child, seg, p_list, out, is_segment, cd_fuse);
      99              :   }
     100            0 :   if (!is_segment) {
     101            0 :     for (const auto& app : segment->get_applications()) {
     102            0 :       if (app->config_object().implementation() == child)
     103            0 :         out.push_back(p_list);
     104            0 :       else if (const auto resource_set = app->cast<dunedaq::confmodel::ResourceSet>())
     105            0 :         make_parents_list(child, resource_set, p_list, out, cd_fuse);
     106              :     }
     107              :   }
     108              : 
     109              :   // remove the segment from the path
     110              : 
     111            0 :   p_list.pop_back();
     112            0 : }
     113              : 
     114              : 
     115              : void
     116            0 : check_segment(
     117              :     std::list< std::vector<const dunedaq::confmodel::Resource *> >& out,
     118              :     const dunedaq::confmodel::Segment * segment,
     119              :     const dunedaq::conffwk::ConfigObjectImpl * child,
     120              :     bool is_segment,
     121              :     dunedaq::confmodel::TestCircularDependency& cd_fuse)
     122              : {
     123            0 :   dunedaq::confmodel::AddTestOnCircularDependency add_fuse_test(cd_fuse, segment);
     124              : 
     125            0 :   std::vector<const dunedaq::confmodel::Resource *> compList;
     126              : 
     127            0 :   if (segment->config_object().implementation() == child) {
     128            0 :     out.push_back(compList);
     129              :   }
     130            0 :   make_parents_list(child, segment, compList, out, is_segment, cd_fuse);
     131            0 : }
     132              : } // namespace
     133              : 
     134              : 
     135              : namespace dunedaq::confmodel {
     136              : 
     137              : void
     138            0 : Resource::parents(
     139              :   const Session& session,
     140              :   std::list<std::vector<const Resource *>>& parents) const
     141              : {
     142            0 :   const ConfigObjectImpl * obj_impl = config_object().implementation();
     143              : 
     144            0 :   const bool is_segment = castable(Segment::s_class_name);
     145              : 
     146            0 :   try {
     147            0 :     TestCircularDependency cd_fuse("component parents", &session);
     148              : 
     149              :     // check session's segment
     150            0 :     check_segment(parents, session.get_segment(), obj_impl, is_segment,
     151              :                   cd_fuse);
     152              : 
     153              : 
     154            0 :     if (parents.empty()) {
     155            0 :       TLOG_DEBUG(1) <<  "cannot find segment/resource path(s) between Resource " << this << " and session " << &session << " objects (check this object is linked with the session as a segment or a resource)" ;
     156              :     }
     157              :   }
     158            0 :   catch (ers::Issue & ex) {
     159            0 :     ers::error(CannotGetParents(ERS_HERE, full_name(), ex));
     160            0 :   }
     161            0 : }
     162              : 
     163              : // ========================================================================
     164              : 
     165              : std::vector<const Application*>
     166           30 : Session::getSegmentApps(const Segment* segment,
     167              :                         bool enabled_only) const {
     168           30 :   std::vector<const Application*> apps;
     169           30 :   auto segapps = segment->get_applications();
     170           30 :   if (enabled_only) {
     171            0 :     for (auto app : segapps) {
     172            0 :       auto comp = app->cast<Resource>();
     173            0 :       if (comp == nullptr || !comp->is_disabled(*this)) {
     174            0 :         apps.insert(apps.end(), app);
     175              :       }
     176              :     }
     177              :   }
     178              :   else {
     179           30 :     apps.swap(segapps);
     180              :   }
     181           45 :   for (auto seg : segment->get_segments()) {
     182           15 :     if (!enabled_only || !seg->is_disabled(*this)) {
     183           15 :       auto segapps = getSegmentApps(seg, enabled_only);
     184           15 :       apps.insert(apps.end(), segapps.begin(),segapps.end());
     185           15 :     }
     186              :   }
     187           30 :   return apps;
     188           30 : }
     189              : 
     190              : std::vector<const Application*>
     191           15 : Session::all_applications() const {
     192           15 :   std::vector<const Application*> apps;
     193           15 :   auto segapps = getSegmentApps(get_segment(), false);
     194           15 :   apps.insert(apps.end(), segapps.begin(),segapps.end());
     195           15 :   return apps;
     196           15 : }
     197              : 
     198              : std::vector<const Application*>
     199            0 : Session::enabled_applications() const {
     200            0 :   std::vector<const Application*> apps;
     201            0 :   auto segapps = getSegmentApps(get_segment(), true);
     202            0 :   apps.insert(apps.end(), segapps.begin(),segapps.end());
     203            0 :   return apps;
     204            0 : }
     205              : 
     206              : 
     207              : // ========================================================================
     208              : 
     209              : std::set<const HostComponent*>
     210            0 : DaqApplication::get_used_hostresources() const {
     211            0 :   std::set<const HostComponent*> res;
     212            0 :   for (auto module :  get_modules()) {
     213            0 :     for (auto hostresource : module->get_used_resources()) {
     214            0 :       res.insert(hostresource);
     215              :     }
     216              :   }
     217            0 :   return res;
     218            0 : }
     219              : 
     220              : namespace {
     221            0 : nlohmann::json get_json_config(conffwk::Configuration& confdb,
     222              :                                const std::string& class_name,
     223              :                                const std::string& uid,
     224              :                                bool direct_only,
     225              :                                bool skip_object_name) {
     226            0 :   using nlohmann::json;
     227            0 :   using namespace conffwk;
     228            0 :   TLOG_DBG(9) << "Getting attributes for " << uid << " of class " << class_name;
     229            0 :   json attributes;
     230            0 :   auto class_info = confdb.get_class_info(class_name);
     231            0 :   ConfigObject obj;
     232            0 :   confdb.get(class_name, uid, obj);
     233            0 :   for (auto attr : class_info.p_attributes) {
     234            0 :     if (attr.p_type == type_t::u8_type) {
     235            0 :       add_json_value<uint8_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     236              :     }
     237              :     else if (attr.p_type == type_t::u16_type) {
     238            0 :       add_json_value<uint16_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     239              :     }
     240              :     else if (attr.p_type == type_t::u32_type) {
     241            0 :       add_json_value<uint32_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     242              :     }
     243              :     else if (attr.p_type == type_t::u64_type) {
     244            0 :       add_json_value<uint64_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     245              :     }
     246              :     else if (attr.p_type == type_t::s8_type) {
     247            0 :       add_json_value<int8_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     248              :     }
     249              :     else if (attr.p_type == type_t::s16_type) {
     250            0 :       add_json_value<int16_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     251              :     }
     252              :     else if (attr.p_type == type_t::s32_type ||
     253              :              attr.p_type == type_t::s16_type) {
     254            0 :       add_json_value<int32_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     255              :     }
     256              :     else if (attr.p_type == type_t::s64_type) {
     257            0 :       add_json_value<int64_t>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     258              :     }
     259              :     else if (attr.p_type == type_t::float_type) {
     260            0 :       add_json_value<float>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     261              :     }
     262              :     else if (attr.p_type == type_t::double_type) {
     263            0 :       add_json_value<double>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     264              :     }
     265              :     else if (attr.p_type == type_t::bool_type) {
     266            0 :       add_json_value<bool>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     267              :     }
     268              :     else if ((attr.p_type == type_t::string_type) ||
     269              :              (attr.p_type == type_t::enum_type) ||
     270              :              (attr.p_type == type_t::date_type) ||
     271              :              (attr.p_type == type_t::time_type)) {
     272            0 :       add_json_value<std::string>(obj, attr.p_name, attr.p_is_multi_value, attributes);
     273              :     }
     274            0 :   }
     275            0 :   if (!direct_only) {
     276            0 :     TLOG_DBG(9) << "Processing  relationships";
     277            0 :     for (auto iter: class_info.p_relationships) {
     278            0 :       std::string rel_name = iter.p_name;
     279            0 :       if (iter.p_cardinality == cardinality_t::zero_or_one ||
     280              :           iter.p_cardinality == cardinality_t::only_one) {
     281            0 :         ConfigObject rel_obj;
     282            0 :         obj.get(rel_name, rel_obj);
     283            0 :         if (!rel_obj.is_null()) {
     284            0 :           TLOG_DBG(9) << "Getting attibute of relationship " << rel_name;
     285            0 :           attributes[rel_name] = get_json_config(confdb, rel_obj.class_name(),
     286              :                                                  rel_obj.UID(),
     287              :                                                  direct_only,
     288            0 :                                                  skip_object_name);
     289              :         }
     290              :         else {
     291            0 :           TLOG_DBG(9) << "Relationship " << rel_name << " not set";
     292              :         }
     293            0 :       }
     294              :       else {
     295            0 :         TLOG_DBG(9) << "Relationship " << rel_name << " is multi value. "
     296            0 :                     << "Getting attibutes for relationship.";
     297            0 :         std::vector<ConfigObject> rel_vec;
     298            0 :         obj.get(rel_name, rel_vec);
     299            0 :         std::vector<json> configs;
     300            0 :         for (auto rel_obj : rel_vec) {
     301            0 :           TLOG_DBG(9) << "Getting attibute of relationship " << rel_obj.UID();
     302            0 :           auto rel_conf = get_json_config(confdb, rel_obj.class_name(), rel_obj.UID(),
     303            0 :                                           direct_only, skip_object_name);
     304            0 :           configs.push_back(rel_conf);
     305            0 :         }
     306            0 :         attributes[rel_name] = configs;
     307            0 :       }
     308            0 :     }
     309              :   }
     310              : 
     311            0 :   if (skip_object_name) {
     312            0 :     return attributes;
     313              :   }
     314            0 :   json json_config;
     315            0 :   json_config[uid] = attributes;
     316            0 :   return json_config;
     317            0 : }
     318              : } // namespace
     319              : 
     320            0 : nlohmann::json Jsonable::to_json(bool direct_only,
     321              :                                  bool skip_object_name) const {
     322            0 :   return get_json_config(p_registry.configuration(), class_name(), UID(), direct_only,
     323            0 :                          skip_object_name);
     324              : }
     325              : 
     326            0 : const std::vector<std::string> DaqApplication::construct_commandline_parameters(
     327              :   const conffwk::Configuration& confdb,
     328              :   const dunedaq::confmodel::Session* session) const {
     329              : 
     330            0 :     return construct_commandline_parameters_appfwk<dunedaq::confmodel::DaqApplication>(this, confdb, session);
     331              : }
     332              : 
     333            0 : const std::vector<std::string> RCApplication::construct_commandline_parameters(
     334              :   const conffwk::Configuration& confdb,
     335              :   const dunedaq::confmodel::Session* session) const {
     336              : 
     337            0 :     const std::string configuration_uri = confdb.get_impl_spec();
     338            0 :     const dunedaq::confmodel::Service* control_service = nullptr;
     339              : 
     340            0 :     const std::string controller_log_level = session->get_controller_log_level();
     341              : 
     342            0 :     for (auto const *as : get_exposes_service()) {
     343            0 :       if (as->UID().ends_with("_control")) {
     344            0 :         if (control_service)
     345            0 :           throw DuplicatedControlService(ERS_HERE, as->UID());
     346              :         control_service = as;
     347              :       }
     348              :     }
     349              : 
     350            0 :     if (control_service == nullptr)
     351            0 :       throw NoControlServiceDefined(ERS_HERE, UID());
     352              : 
     353            0 :     const std::string control_uri =
     354            0 :       control_service->get_protocol()
     355            0 :       + "://"
     356            0 :       + get_runs_on()->get_runs_on()->UID()
     357            0 :       + ":"
     358            0 :       + std::to_string(control_service->get_port());
     359              : 
     360            0 :     std::vector<std::string> ret = { "-l", controller_log_level };
     361            0 :     ret.push_back(configuration_uri);
     362            0 :     ret.push_back(control_uri);
     363            0 :     ret.push_back(UID());
     364            0 :     ret.push_back(session->UID());
     365            0 :     return ret;
     366            0 : }
     367              : 
     368              : 
     369              : 
     370              : std::vector<const confmodel::DetectorStream*>
     371           61 : DetectorToDaqConnection::streams() const {
     372           61 :   std::vector<const confmodel::DetectorStream*> all_streams;
     373              :   // Loop over senders
     374          122 :   for (auto sender : this->senders()) {
     375           61 :     auto sender_streams = sender->get_streams();
     376           61 :     all_streams.insert(all_streams.end(), sender_streams.begin(), sender_streams.end());
     377          122 :   }
     378           61 :   return all_streams;
     379            0 : }
     380              : 
     381           10 : std::string OpMonURI::get_URI( const std::string & /* app */) const {
     382              : 
     383           10 :   auto type = get_type();
     384           10 :   if ( type == "file" ) {
     385           10 :     return type + "://" + get_path();
     386              :   }
     387              : 
     388            0 :   if ( type == "stream" ) {
     389            0 :     return type + "://" + get_path();
     390              :   }
     391              : 
     392            0 :   return "stdout://";
     393           10 : }
     394              : 
     395          257 : bool Resource::is_disabled(const dunedaq::confmodel::ResourceTree& holder) const {
     396          257 :   return (!holder.disabled_components().is_enabled(this));
     397              : }
     398           47 : bool Resource::compute_disabled_state(const std::set<std::string>& disabled_resources) const {
     399           47 :   TLOG_DEBUG(6) << "No compute_disabled_state method defined for Resource " << class_name();
     400           47 :   if (disabled_resources.contains(UID())) {
     401              :     return true;
     402              :   }
     403              :   return false;
     404              : }
     405              : 
     406           32 : std::vector<const Resource*> DetDataSender::contained_resources() const {
     407           32 :   return to_resources(get_streams());
     408              : }
     409              : 
     410            9 : std::vector<const Resource*> DetectorToDaqConnection::contained_resources() const {
     411            9 :   auto res = to_resources(senders());
     412            9 :   res.push_back(receiver());
     413            9 :   return res;
     414            0 : }
     415              : 
     416              : 
     417              : bool
     418            6 : DetectorToDaqConnection::compute_disabled_state(const std::set<std::string>& disabled_resources) const {
     419            6 :   if (disabled_resources.contains(UID())) {
     420              :     return true;
     421              :   }
     422            6 :   bool send_disabled = true;
     423           14 :   for (auto sender: senders()) {
     424           11 :     if (!sender->compute_disabled_state(disabled_resources)) {
     425            3 :       send_disabled = false;
     426            3 :       break;
     427              :     }
     428            6 :   }
     429            6 :   TLOG_DBG(6) << "receiver disabled=" << receiver()->compute_disabled_state(disabled_resources)
     430            6 :               << " senders disabled=" << send_disabled;
     431            6 :   if (receiver()->compute_disabled_state(disabled_resources) || send_disabled) {
     432              :     return true;
     433              :   }
     434              :   return false;
     435              : }
     436              : 
     437              : std::vector<const Resource*>
     438            5 : Segment::contained_resources() const {
     439              :   // All our contained segments are resources
     440            5 :   std::vector<const Resource*> resources = to_resources(get_segments());
     441              : 
     442              :   // Only a subset of our applications might be resources so check individually
     443           20 :   for (auto app: get_applications()) {
     444           15 :     TLOG_DBG(6) << "Checking " << app->UID();
     445           15 :     auto res=app->cast<const Resource>();
     446           15 :     if (res != nullptr) {
     447           15 :       TLOG_DBG(6) << "Adding " << app->UID();
     448           15 :       resources.push_back(res);
     449              :     }
     450              :   }
     451            5 :   TLOG_DBG(6) << "Returning vector of " << resources.size() << " resources";
     452            5 :   return resources;
     453            0 : }
     454              : 
     455              : bool
     456            2 : Segment::compute_disabled_state(const std::set<std::string>& disabled) const {
     457            2 :   if (disabled.contains(UID())) {
     458              :     return true;
     459              :   }
     460            8 :   for (auto app: get_applications()) {
     461            6 :     auto res=app->cast<const Resource>();
     462            6 :     if (res == nullptr) {
     463            0 :       return false;
     464              :     }
     465              :   }
     466            6 :   for (auto res: contained_resources()) {
     467            5 :     if (!res->compute_disabled_state(disabled)) {
     468            1 :       return false;
     469              :     }
     470            2 :   }
     471            1 :   return true;
     472              : }
     473              : 
     474              : } // namespace dunedaq::confmodel
        

Generated by: LCOV version 2.0-1