blob: 444a714e686dd2fe729b4f1f88fc0bde9145b1c6 [file] [log] [blame]
Tomáš Pecka98ad18d2020-11-13 15:39:55 +01001/*
Tomáš Pecka43ef7ba2023-04-13 15:56:48 +02002 * Copyright (C) 2020-2023 CESNET, https://photonics.cesnet.cz/
Tomáš Pecka98ad18d2020-11-13 15:39:55 +01003 *
4 * Written by Tomáš Pecka <tomas.pecka@fit.cvut.cz>
5 *
6 */
7
Tomáš Pecka43ef7ba2023-04-13 15:56:48 +02008#include <regex>
9#include <sysrepo-cpp/Connection.hpp>
Tomáš Pecka98ad18d2020-11-13 15:39:55 +010010#include "Sysrepo.h"
11#include "utils/log.h"
Tomáš Peckaba2dc312021-01-23 22:29:11 +010012#include "utils/sysrepo.h"
Tomáš Pecka98ad18d2020-11-13 15:39:55 +010013
Tomáš Pecka98ad18d2020-11-13 15:39:55 +010014namespace {
15
Tomáš Pecka43ef7ba2023-04-13 15:56:48 +020016/** @brief Extracts component path prefix from an XPath under /ietf-hardware/component node
17 *
18 * Example input: /ietf-hardware:hardware/component[name='ne:psu:child']/oper-state/disabled
19 * Example output: /ietf-hardware:hardware/component[name='ne:psu:child']
20 */
21std::string extractComponentPrefix(const std::string& componentXPath)
22{
23 static const std::regex regex(R"((/ietf-hardware:hardware/component\[name=('|").*?(\2)\]).*)");
24 std::smatch match;
Tomáš Pecka98ad18d2020-11-13 15:39:55 +010025
Tomáš Pecka43ef7ba2023-04-13 15:56:48 +020026 if (std::regex_match(componentXPath, match, regex)) {
27 return match.str(1);
28 }
29
30 throw std::logic_error("Invalid xPath provided ('" + componentXPath + "')");
31}
Tomáš Pecka98ad18d2020-11-13 15:39:55 +010032}
33
Tomáš Pecka43ef7ba2023-04-13 15:56:48 +020034namespace velia::ietf_hardware::sysrepo {
35
36/** @brief The constructor expects the HardwareState instance which will provide the actual hardware state data and the poll interval */
37Sysrepo::Sysrepo(::sysrepo::Session session, std::shared_ptr<IETFHardware> hwState, std::chrono::microseconds pollInterval)
38 : m_log(spdlog::get("hardware"))
39 , m_pollInterval(std::move(pollInterval))
40 , m_session(std::move(session))
41 , m_hwState(std::move(hwState))
42 , m_quit(false)
43 , m_pollThread([&]() {
44 auto conn = m_session.getConnection();
45
46 DataTree prevValues;
47
48 while (!m_quit) {
49 m_log->trace("IetfHardware poll");
50
51 auto hwStateValues = m_hwState->process();
52 std::set<std::string> deletedComponents;
53
54 /* Some data readers can stop returning data in some cases (e.g. ejected PSU).
55 * Prune tree components that were removed before updating to avoid having not current data from previous invocations.
56 */
57 for (const auto& [k, v] : prevValues) {
58 if (!hwStateValues.contains(k)) {
59 deletedComponents.emplace(extractComponentPrefix(k));
60 }
61 }
62
63 for (const auto& component : deletedComponents) {
64 conn.discardOperationalChanges(component);
65 }
66
67 utils::valuesPush(hwStateValues, {}, m_session, ::sysrepo::Datastore::Operational);
68
69 prevValues = std::move(hwStateValues);
70 std::this_thread::sleep_for(m_pollInterval);
71 }
72 })
Tomáš Pecka98ad18d2020-11-13 15:39:55 +010073{
Tomáš Pecka43ef7ba2023-04-13 15:56:48 +020074}
Václav Kubernát7efd6d52021-11-09 01:31:11 +010075
Tomáš Pecka43ef7ba2023-04-13 15:56:48 +020076Sysrepo::~Sysrepo()
77{
78 m_log->trace("Requesting poll thread stop");
79 m_quit = true;
80 m_pollThread.join();
Tomáš Pecka98ad18d2020-11-13 15:39:55 +010081}
82}