blob: c74d7af1b2a9b2f957f5ee330680d651cb9f5b04 [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
Václav Kubernát3a433232020-07-08 17:52:50 +020027 if (event == SR_EV_APPLY) {
Václav Kubernát73109382018-09-14 19:52:03 +020028 return SR_ERR_OK;
Václav Kubernát3a433232020-07-08 17:52:50 +020029 }
Václav Kubernát73109382018-09-14 19:52:03 +020030
31 while (auto change = sess->get_change_next(it)) {
Václav Kubernát69aabe92020-01-24 16:53:12 +010032 auto xpath = (change->new_val() ? change->new_val() : change->old_val())->xpath();
33
34 auto oldValue = change->old_val() ? std::optional{change->old_val()->val_to_string()} : std::nullopt;
35 auto newValue = change->new_val() ? std::optional{change->new_val()->val_to_string()} : std::nullopt;
36 m_recorder->write(xpath, oldValue, newValue);
Václav Kubernát73109382018-09-14 19:52:03 +020037 }
38
39 return SR_ERR_OK;
40 }
41
42private:
43 std::string m_moduleName;
44 Recorder* m_recorder;
45};
46
47Recorder::~Recorder() = default;
48
Jan Kundrátbb525b42020-02-04 11:56:59 +010049DataSupplier::~DataSupplier() = default;
50
Václav Kubernátab612e92019-11-26 19:51:31 +010051SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec)
Václav Kubernát73109382018-09-14 19:52:03 +020052 : m_connection(new sysrepo::Connection("netconf-cli-test-subscription"))
53{
54 m_session = std::make_shared<sysrepo::Session>(m_connection);
55 m_subscription = std::make_shared<sysrepo::Subscribe>(m_session);
Václav Kubernátab612e92019-11-26 19:51:31 +010056 if (rec) {
57 m_callback = std::make_shared<MyCallback>(moduleName, rec);
58 } else {
59 m_callback = std::make_shared<sysrepo::Callback>();
60 }
Václav Kubernát73109382018-09-14 19:52:03 +020061
Václav Kubernátab612e92019-11-26 19:51:31 +010062 m_subscription->module_change_subscribe(moduleName.c_str(), m_callback);
Václav Kubernát73109382018-09-14 19:52:03 +020063}
Jan Kundrátbb525b42020-02-04 11:56:59 +010064
65struct leafDataToSysrepoVal {
66 leafDataToSysrepoVal (sysrepo::S_Val v, const std::string& xpath)
67 : v(v)
68 , xpath(xpath)
69 {
70 }
71
72 void operator()(const binary_& what)
73 {
74 v->set(xpath.c_str(), what.m_value.c_str(), SR_BINARY_T);
75 }
76
77 void operator()(const enum_& what)
78 {
79 v->set(xpath.c_str(), what.m_value.c_str(), SR_ENUM_T);
80 }
81
82 void operator()(const identityRef_& what)
83 {
84 v->set(xpath.c_str(), (what.m_prefix->m_name + what.m_value).c_str(), SR_IDENTITYREF_T);
85 }
86
Jan Kundrát379bb572020-05-07 03:23:13 +020087 void operator()(const empty_)
88 {
89 v->set(xpath.c_str(), nullptr, SR_LEAF_EMPTY_T);
90 }
91
Jan Kundrátbb525b42020-02-04 11:56:59 +010092 void operator()(const std::string& what)
93 {
94 v->set(xpath.c_str(), what.c_str());
95 }
96
97 template <typename Type>
98 void operator()(const Type what)
99 {
100 v->set(xpath.c_str(), what);
101 }
102
103 void operator()([[maybe_unused]] const special_ what)
104 {
105 throw std::logic_error("Attempted to create a SR val from a special_ value");
106 }
107
108 ::sysrepo::S_Val v;
109 std::string xpath;
110};
111
112class OperationalDataCallback : public sysrepo::Callback {
113public:
114 OperationalDataCallback(const DataSupplier& dataSupplier)
115 : m_dataSupplier(dataSupplier)
116 {
117 }
118 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
119 {
120 auto data = m_dataSupplier.get_data(xpath);
121 auto out = vals->allocate(data.size());
122 size_t i = 0;
123 for (auto it = data.cbegin(); it != data.cend(); ++it, ++i) {
124 std::string valuePath = it->first;
125 boost::apply_visitor(leafDataToSysrepoVal(out->val(i), valuePath), it->second);
126 }
127 return SR_ERR_OK;
128 }
129private:
130 const DataSupplier& m_dataSupplier;
131};
132
133OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const DataSupplier& dataSupplier)
134 : m_connection(new sysrepo::Connection("netconf-cli-test-subscription"))
135 , m_session(std::make_shared<sysrepo::Session>(m_connection))
136 , m_subscription(std::make_shared<sysrepo::Subscribe>(m_session))
137 , m_callback(std::make_shared<OperationalDataCallback>(dataSupplier))
138{
139 m_subscription->dp_get_items_subscribe(moduleName.c_str(), m_callback);
140}