blob: ba276a73e3283010797095af1f0628d48f4562f5 [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
Václav Kubernát19097f32020-10-05 10:08:29 +02009#include <experimental/iterator>
10#include <sstream>
Václav Kubernát73109382018-09-14 19:52:03 +020011#include <sysrepo-cpp/Session.hpp>
12#include "sysrepo_subscription.hpp"
13
14
15class MyCallback : public sysrepo::Callback {
16public:
17 MyCallback(const std::string& moduleName, Recorder* rec)
18 : m_moduleName(moduleName)
19 , m_recorder(rec)
20 {
21 }
22
23 int module_change(sysrepo::S_Session sess, const char* module_name, sr_notif_event_t event, void*) override
24 {
25 using namespace std::string_literals;
26 auto xpath = "/"s + module_name + ":*";
27 auto it = sess->get_changes_iter(xpath.c_str());
28
Václav Kubernát3a433232020-07-08 17:52:50 +020029 if (event == SR_EV_APPLY) {
Václav Kubernát73109382018-09-14 19:52:03 +020030 return SR_ERR_OK;
Václav Kubernát3a433232020-07-08 17:52:50 +020031 }
Václav Kubernát73109382018-09-14 19:52:03 +020032
33 while (auto change = sess->get_change_next(it)) {
Václav Kubernát69aabe92020-01-24 16:53:12 +010034 auto xpath = (change->new_val() ? change->new_val() : change->old_val())->xpath();
35
36 auto oldValue = change->old_val() ? std::optional{change->old_val()->val_to_string()} : std::nullopt;
37 auto newValue = change->new_val() ? std::optional{change->new_val()->val_to_string()} : std::nullopt;
38 m_recorder->write(xpath, oldValue, newValue);
Václav Kubernát73109382018-09-14 19:52:03 +020039 }
40
41 return SR_ERR_OK;
42 }
43
44private:
45 std::string m_moduleName;
46 Recorder* m_recorder;
47};
48
49Recorder::~Recorder() = default;
50
Jan Kundrátbb525b42020-02-04 11:56:59 +010051DataSupplier::~DataSupplier() = default;
52
Václav Kubernátab612e92019-11-26 19:51:31 +010053SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec)
Václav Kubernát73109382018-09-14 19:52:03 +020054 : m_connection(new sysrepo::Connection("netconf-cli-test-subscription"))
55{
56 m_session = std::make_shared<sysrepo::Session>(m_connection);
57 m_subscription = std::make_shared<sysrepo::Subscribe>(m_session);
Václav Kubernátab612e92019-11-26 19:51:31 +010058 if (rec) {
59 m_callback = std::make_shared<MyCallback>(moduleName, rec);
60 } else {
61 m_callback = std::make_shared<sysrepo::Callback>();
62 }
Václav Kubernát73109382018-09-14 19:52:03 +020063
Václav Kubernátab612e92019-11-26 19:51:31 +010064 m_subscription->module_change_subscribe(moduleName.c_str(), m_callback);
Václav Kubernát73109382018-09-14 19:52:03 +020065}
Jan Kundrátbb525b42020-02-04 11:56:59 +010066
67struct leafDataToSysrepoVal {
68 leafDataToSysrepoVal (sysrepo::S_Val v, const std::string& xpath)
69 : v(v)
70 , xpath(xpath)
71 {
72 }
73
74 void operator()(const binary_& what)
75 {
76 v->set(xpath.c_str(), what.m_value.c_str(), SR_BINARY_T);
77 }
78
79 void operator()(const enum_& what)
80 {
81 v->set(xpath.c_str(), what.m_value.c_str(), SR_ENUM_T);
82 }
83
84 void operator()(const identityRef_& what)
85 {
86 v->set(xpath.c_str(), (what.m_prefix->m_name + what.m_value).c_str(), SR_IDENTITYREF_T);
87 }
88
Jan Kundrát379bb572020-05-07 03:23:13 +020089 void operator()(const empty_)
90 {
91 v->set(xpath.c_str(), nullptr, SR_LEAF_EMPTY_T);
92 }
93
Jan Kundrátbb525b42020-02-04 11:56:59 +010094 void operator()(const std::string& what)
95 {
96 v->set(xpath.c_str(), what.c_str());
97 }
98
Václav Kubernát19097f32020-10-05 10:08:29 +020099 void operator()(const bits_& what)
100 {
101 std::stringstream ss;
102 std::copy(what.m_bits.begin(), what.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
103 v->set(xpath.c_str(), ss.str().c_str());
104
105 }
106
Jan Kundrátbb525b42020-02-04 11:56:59 +0100107 template <typename Type>
108 void operator()(const Type what)
109 {
110 v->set(xpath.c_str(), what);
111 }
112
113 void operator()([[maybe_unused]] const special_ what)
114 {
115 throw std::logic_error("Attempted to create a SR val from a special_ value");
116 }
117
118 ::sysrepo::S_Val v;
119 std::string xpath;
120};
121
122class OperationalDataCallback : public sysrepo::Callback {
123public:
124 OperationalDataCallback(const DataSupplier& dataSupplier)
125 : m_dataSupplier(dataSupplier)
126 {
127 }
128 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
129 {
130 auto data = m_dataSupplier.get_data(xpath);
131 auto out = vals->allocate(data.size());
132 size_t i = 0;
133 for (auto it = data.cbegin(); it != data.cend(); ++it, ++i) {
134 std::string valuePath = it->first;
135 boost::apply_visitor(leafDataToSysrepoVal(out->val(i), valuePath), it->second);
136 }
137 return SR_ERR_OK;
138 }
139private:
140 const DataSupplier& m_dataSupplier;
141};
142
143OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const DataSupplier& dataSupplier)
144 : m_connection(new sysrepo::Connection("netconf-cli-test-subscription"))
145 , m_session(std::make_shared<sysrepo::Session>(m_connection))
146 , m_subscription(std::make_shared<sysrepo::Subscribe>(m_session))
147 , m_callback(std::make_shared<OperationalDataCallback>(dataSupplier))
148{
149 m_subscription->dp_get_items_subscribe(moduleName.c_str(), m_callback);
150}