blob: 0d4fe336a44bca3baf4598733cbefcda24affd7b [file] [log] [blame]
Václav Kubernát73109382018-09-14 19:52:03 +02001/*
2 * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
3 * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
4 *
5 * Written by Václav Kubernát <kubervac@fit.cvut.cz>
6 *
7*/
8
9#include <sysrepo-cpp/Session.hpp>
10#include "sysrepo_subscription.hpp"
11
12
13class MyCallback : public sysrepo::Callback {
14public:
15 MyCallback(const std::string& moduleName, Recorder* rec)
16 : m_moduleName(moduleName)
17 , m_recorder(rec)
18 {
19 }
20
21 int module_change(sysrepo::S_Session sess, const char* module_name, sr_notif_event_t event, void*) override
22 {
23 using namespace std::string_literals;
24 auto xpath = "/"s + module_name + ":*";
25 auto it = sess->get_changes_iter(xpath.c_str());
26
27 if (event == SR_EV_APPLY)
28 return SR_ERR_OK;
29
30 while (auto change = sess->get_change_next(it)) {
Václav Kubernát69aabe92020-01-24 16:53:12 +010031 auto xpath = (change->new_val() ? change->new_val() : change->old_val())->xpath();
32
33 auto oldValue = change->old_val() ? std::optional{change->old_val()->val_to_string()} : std::nullopt;
34 auto newValue = change->new_val() ? std::optional{change->new_val()->val_to_string()} : std::nullopt;
35 m_recorder->write(xpath, oldValue, newValue);
Václav Kubernát73109382018-09-14 19:52:03 +020036 }
37
38 return SR_ERR_OK;
39 }
40
41private:
42 std::string m_moduleName;
43 Recorder* m_recorder;
44};
45
46Recorder::~Recorder() = default;
47
Jan Kundrátbb525b42020-02-04 11:56:59 +010048DataSupplier::~DataSupplier() = default;
49
Václav Kubernátab612e92019-11-26 19:51:31 +010050SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec)
Václav Kubernát73109382018-09-14 19:52:03 +020051 : m_connection(new sysrepo::Connection("netconf-cli-test-subscription"))
52{
53 m_session = std::make_shared<sysrepo::Session>(m_connection);
54 m_subscription = std::make_shared<sysrepo::Subscribe>(m_session);
Václav Kubernátab612e92019-11-26 19:51:31 +010055 if (rec) {
56 m_callback = std::make_shared<MyCallback>(moduleName, rec);
57 } else {
58 m_callback = std::make_shared<sysrepo::Callback>();
59 }
Václav Kubernát73109382018-09-14 19:52:03 +020060
Václav Kubernátab612e92019-11-26 19:51:31 +010061 m_subscription->module_change_subscribe(moduleName.c_str(), m_callback);
Václav Kubernát73109382018-09-14 19:52:03 +020062}
Jan Kundrátbb525b42020-02-04 11:56:59 +010063
64struct leafDataToSysrepoVal {
65 leafDataToSysrepoVal (sysrepo::S_Val v, const std::string& xpath)
66 : v(v)
67 , xpath(xpath)
68 {
69 }
70
71 void operator()(const binary_& what)
72 {
73 v->set(xpath.c_str(), what.m_value.c_str(), SR_BINARY_T);
74 }
75
76 void operator()(const enum_& what)
77 {
78 v->set(xpath.c_str(), what.m_value.c_str(), SR_ENUM_T);
79 }
80
81 void operator()(const identityRef_& what)
82 {
83 v->set(xpath.c_str(), (what.m_prefix->m_name + what.m_value).c_str(), SR_IDENTITYREF_T);
84 }
85
Jan Kundrát379bb572020-05-07 03:23:13 +020086 void operator()(const empty_)
87 {
88 v->set(xpath.c_str(), nullptr, SR_LEAF_EMPTY_T);
89 }
90
Jan Kundrátbb525b42020-02-04 11:56:59 +010091 void operator()(const std::string& what)
92 {
93 v->set(xpath.c_str(), what.c_str());
94 }
95
96 template <typename Type>
97 void operator()(const Type what)
98 {
99 v->set(xpath.c_str(), what);
100 }
101
102 void operator()([[maybe_unused]] const special_ what)
103 {
104 throw std::logic_error("Attempted to create a SR val from a special_ value");
105 }
106
107 ::sysrepo::S_Val v;
108 std::string xpath;
109};
110
111class OperationalDataCallback : public sysrepo::Callback {
112public:
113 OperationalDataCallback(const DataSupplier& dataSupplier)
114 : m_dataSupplier(dataSupplier)
115 {
116 }
117 int dp_get_items(const char *xpath, sysrepo::S_Vals_Holder vals, [[maybe_unused]] uint64_t request_id, [[maybe_unused]] const char *original_xpath, [[maybe_unused]] void *private_ctx) override
118 {
119 auto data = m_dataSupplier.get_data(xpath);
120 auto out = vals->allocate(data.size());
121 size_t i = 0;
122 for (auto it = data.cbegin(); it != data.cend(); ++it, ++i) {
123 std::string valuePath = it->first;
124 boost::apply_visitor(leafDataToSysrepoVal(out->val(i), valuePath), it->second);
125 }
126 return SR_ERR_OK;
127 }
128private:
129 const DataSupplier& m_dataSupplier;
130};
131
132OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const DataSupplier& dataSupplier)
133 : m_connection(new sysrepo::Connection("netconf-cli-test-subscription"))
134 , m_session(std::make_shared<sysrepo::Session>(m_connection))
135 , m_subscription(std::make_shared<sysrepo::Subscribe>(m_session))
136 , m_callback(std::make_shared<OperationalDataCallback>(dataSupplier))
137{
138 m_subscription->dp_get_items_subscribe(moduleName.c_str(), m_callback);
139}