LCOV - code coverage report
Current view: top level - restcmd/plugins - restCommandFacility.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 63 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 6 0

            Line data    Source code
       1              : /**
       2              :  * @file RestCommandFacility.cpp
       3              :  *
       4              :  * This is part of the DUNE DAQ Application Framework, copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : #include "restcmd/RestEndpoint.hpp"
       9              : 
      10              : #include "cmdlib/CommandFacility.hpp"
      11              : #include "cmdlib/Issues.hpp"
      12              : 
      13              : #include "confmodel/ConnectivityService.hpp"
      14              : #include "iomanager/network/ConfigClient.hpp"
      15              : #include "iomanager/network/ConfigClientStructs.hpp"
      16              : #include "utilities/get_ips.hpp"
      17              : 
      18              : #include "logging/Logging.hpp"
      19              : #include <cetlib/BasicPluginFactory.h>
      20              : // #include <tbb/concurrent_queue.h>
      21              : #include <folly/Uri.h>
      22              : 
      23              : #include <chrono>
      24              : #include <climits>
      25              : #include <fstream>
      26              : #include <functional>
      27              : #include <map>
      28              : #include <memory>
      29              : #include <string>
      30              : #include <unistd.h>
      31              : 
      32              : using namespace dunedaq::cmdlib;
      33              : using namespace dunedaq::restcmd;
      34              : 
      35              : class restCommandFacility : public CommandFacility
      36              : {
      37              : 
      38              : public:
      39              :   // friend backend for calling functions on CF
      40              :   friend class RestEndpoint;
      41              : 
      42            0 :   explicit restCommandFacility(std::string uri,
      43              :                                std::string session_name,
      44              :                                const dunedaq::confmodel::ConnectivityService* connectivity_service)
      45            0 :     : CommandFacility(uri)
      46            0 :     , m_session_name(session_name)
      47              :   {
      48              : 
      49            0 :     folly::Uri furi(uri);
      50              : 
      51            0 :     std::string hostname = furi.hostname();
      52            0 :     int port = furi.port();
      53              : 
      54            0 :     if (connectivity_service != nullptr) {
      55            0 :       auto connectivity_service_port = std::to_string(connectivity_service->get_service()->get_port());
      56            0 :       m_connectivity_client = std::make_unique<dunedaq::iomanager::ConfigClient>(
      57            0 :         connectivity_service->get_host(),
      58              :         connectivity_service_port,
      59              :         m_session_name,
      60            0 :         std::chrono::milliseconds(connectivity_service->get_interval_ms()));
      61            0 :     }
      62              : 
      63            0 :     if (port == 0 && connectivity_service == nullptr) {
      64            0 :       throw dunedaq::cmdlib::MalformedUri(
      65            0 :         ERS_HERE, "Can't bind the REST API to port 0 without connectivity service", std::to_string(port));
      66              :     }
      67              : 
      68            0 :     try { // to setup backend
      69            0 :       command_executor_ = std::bind(&inherited::execute_command, this, std::placeholders::_1, std::placeholders::_2);
      70            0 :       rest_endpoint_ = std::make_unique<dunedaq::restcmd::RestEndpoint>(hostname, port, command_executor_);
      71            0 :       rest_endpoint_->init(1); // 1 thread
      72            0 :       TLOG() << std::format("Endpoint open on host: {} port: {}", hostname, port);
      73              : 
      74            0 :     } catch (const std::exception& ex) {
      75            0 :       ers::error(dunedaq::cmdlib::CommandFacilityInitialization(ERS_HERE, ex.what()));
      76            0 :     }
      77              : 
      78              :     // Store hostname for connectivity service registration
      79            0 :     m_hostname = hostname;
      80            0 :   }
      81              : 
      82            0 :   void run(std::atomic<bool>& end_marker)
      83              :   {
      84              : 
      85            0 :     char* app_name_c = std::getenv("DUNEDAQ_APPLICATION_NAME");
      86            0 :     if (!app_name_c)
      87            0 :       throw dunedaq::restcmd::EnvVarNotFound(ERS_HERE, "DUNEDAQ_APPLICATION_NAME");
      88            0 :     std::string app_name = std::string(app_name_c);
      89              : 
      90              :     // Start endpoint
      91            0 :     try {
      92            0 :       rest_endpoint_->start();
      93              : 
      94            0 :       if (m_connectivity_client) {
      95            0 :         int port = rest_endpoint_->getPort();
      96              : 
      97            0 :         auto ips = dunedaq::utilities::get_hostname_ips(m_hostname);
      98              : 
      99            0 :         if (ips.size() == 0)
     100            0 :           throw dunedaq::cmdlib::CommandFacilityInitialization(ERS_HERE, "Could not resolve hostname to IP address");
     101              : 
     102            0 :         TLOG() << "Registering the control endpoint (" << app_name
     103            0 :                << "_control) on the connectivity service: " << ips[0] << ":" << port;
     104            0 :         dunedaq::iomanager::ConnectionRegistration cr;
     105            0 :         cr.uid = app_name + "_control";
     106            0 :         cr.data_type = "RunControlMessage";
     107            0 :         cr.uri = "rest://" + ips[0] + ":" + std::to_string(port);
     108            0 :         cr.connection_type = dunedaq::iomanager::ConnectionType::kSendRecv;
     109            0 :         m_connectivity_client->publish(cr);
     110            0 :       }
     111            0 :     } catch (const std::exception& ex) {
     112            0 :       ers::fatal(dunedaq::cmdlib::RunLoopTerminated(ERS_HERE, ex.what()));
     113            0 :     }
     114              : 
     115              :     // Wait until marked
     116            0 :     while (end_marker) {
     117            0 :       std::this_thread::sleep_for(std::chrono::seconds(1));
     118              :     }
     119              : 
     120              :     // Shutdown
     121            0 :     rest_endpoint_->shutdown();
     122            0 :     if (m_connectivity_client) {
     123            0 :       dunedaq::iomanager::ConnectionId ci{ app_name + "_control", "RunControlMessage", m_session_name };
     124            0 :       m_connectivity_client->retract(ci);
     125            0 :     }
     126            0 :   }
     127              : 
     128              : protected:
     129              :   typedef CommandFacility inherited;
     130              : 
     131              :   // Implementation of completionHandler interface
     132            0 :   void completion_callback(const cmdobj_t& cmd, cmd::CommandReply& meta)
     133              :   {
     134            0 :     rest_endpoint_->handleResponseCommand(cmd, meta);
     135            0 :   }
     136              : 
     137              : private:
     138              :   // Manager, HTTP REST Endpoint and backend resources
     139              :   mutable std::unique_ptr<RestEndpoint> rest_endpoint_;
     140              : 
     141              :   typedef std::function<void(const cmdobj_t&, cmd::CommandReply)> RequestCallback;
     142              :   RequestCallback command_executor_;
     143              : 
     144              :   std::string m_session_name;
     145              :   std::string m_hostname;
     146              :   std::unique_ptr<dunedaq::iomanager::ConfigClient> m_connectivity_client;
     147              : };
     148              : 
     149              : // NOLINTBEGIN
     150              : extern "C"
     151              : {
     152              :   std::shared_ptr<dunedaq::cmdlib::CommandFacility>
     153            0 :   make(std::string uri, std::string session_name, const dunedaq::confmodel::ConnectivityService* connectivity_service)
     154              :   {
     155              : 
     156            0 :     return std::shared_ptr<dunedaq::cmdlib::CommandFacility>(
     157            0 :       new restCommandFacility(uri, session_name, connectivity_service));
     158              :   }
     159              : }
     160              : // NOLINTEND
        

Generated by: LCOV version 2.0-1