blob: 03be07569ce0963a5be42cc44fd8aab197d64770 [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"
Václav Kubernát654303f2020-07-31 13:16:54 +020013#include "utils.hpp"
Václav Kubernát73109382018-09-14 19:52:03 +020014
15
Václav Kubernát654303f2020-07-31 13:16:54 +020016class MyCallback {
Václav Kubernát73109382018-09-14 19:52:03 +020017public:
18 MyCallback(const std::string& moduleName, Recorder* rec)
19 : m_moduleName(moduleName)
20 , m_recorder(rec)
21 {
22 }
23
Václav Kubernát654303f2020-07-31 13:16:54 +020024 int operator()(
25 sysrepo::S_Session sess,
Václav Kubernátd1beedc2020-09-07 12:09:05 +020026 [[maybe_unused]] const char *module_name,
Václav Kubernát654303f2020-07-31 13:16:54 +020027 [[maybe_unused]] const char *xpath,
28 [[maybe_unused]] sr_event_t event,
29 [[maybe_unused]] uint32_t request_id)
Václav Kubernát73109382018-09-14 19:52:03 +020030 {
31 using namespace std::string_literals;
Václav Kubernát654303f2020-07-31 13:16:54 +020032 if (event == SR_EV_CHANGE) {
Václav Kubernát73109382018-09-14 19:52:03 +020033 return SR_ERR_OK;
Václav Kubernát3a433232020-07-08 17:52:50 +020034 }
Václav Kubernát73109382018-09-14 19:52:03 +020035
Václav Kubernát654303f2020-07-31 13:16:54 +020036 auto it = sess->get_changes_iter(("/"s + module_name + ":*//.").c_str());
37
Václav Kubernát73109382018-09-14 19:52:03 +020038 while (auto change = sess->get_change_next(it)) {
Václav Kubernát69aabe92020-01-24 16:53:12 +010039 auto xpath = (change->new_val() ? change->new_val() : change->old_val())->xpath();
40
41 auto oldValue = change->old_val() ? std::optional{change->old_val()->val_to_string()} : std::nullopt;
42 auto newValue = change->new_val() ? std::optional{change->new_val()->val_to_string()} : std::nullopt;
43 m_recorder->write(xpath, oldValue, newValue);
Václav Kubernát73109382018-09-14 19:52:03 +020044 }
45
46 return SR_ERR_OK;
47 }
48
49private:
50 std::string m_moduleName;
51 Recorder* m_recorder;
52};
53
54Recorder::~Recorder() = default;
55
Jan Kundrátbb525b42020-02-04 11:56:59 +010056DataSupplier::~DataSupplier() = default;
57
Václav Kubernátab612e92019-11-26 19:51:31 +010058SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec)
Václav Kubernát654303f2020-07-31 13:16:54 +020059 : m_connection(std::make_shared<sysrepo::Connection>())
Václav Kubernát73109382018-09-14 19:52:03 +020060{
61 m_session = std::make_shared<sysrepo::Session>(m_connection);
62 m_subscription = std::make_shared<sysrepo::Subscribe>(m_session);
Václav Kubernát654303f2020-07-31 13:16:54 +020063 sysrepo::ModuleChangeCb cb;
Václav Kubernátab612e92019-11-26 19:51:31 +010064 if (rec) {
Václav Kubernát654303f2020-07-31 13:16:54 +020065 cb = MyCallback{moduleName, rec};
Václav Kubernátab612e92019-11-26 19:51:31 +010066 } else {
Václav Kubernát654303f2020-07-31 13:16:54 +020067 cb = [] (auto, auto, auto, auto, auto) { return SR_ERR_OK; };
Václav Kubernátab612e92019-11-26 19:51:31 +010068 }
Václav Kubernát73109382018-09-14 19:52:03 +020069
Václav Kubernát654303f2020-07-31 13:16:54 +020070 m_subscription->module_change_subscribe(moduleName.c_str(), cb);
Václav Kubernát73109382018-09-14 19:52:03 +020071}
Jan Kundrátbb525b42020-02-04 11:56:59 +010072
Václav Kubernát654303f2020-07-31 13:16:54 +020073
Jan Kundrátbb525b42020-02-04 11:56:59 +010074struct leafDataToSysrepoVal {
75 leafDataToSysrepoVal (sysrepo::S_Val v, const std::string& xpath)
76 : v(v)
77 , xpath(xpath)
78 {
79 }
80
81 void operator()(const binary_& what)
82 {
83 v->set(xpath.c_str(), what.m_value.c_str(), SR_BINARY_T);
84 }
85
86 void operator()(const enum_& what)
87 {
88 v->set(xpath.c_str(), what.m_value.c_str(), SR_ENUM_T);
89 }
90
91 void operator()(const identityRef_& what)
92 {
93 v->set(xpath.c_str(), (what.m_prefix->m_name + what.m_value).c_str(), SR_IDENTITYREF_T);
94 }
95
Jan Kundrát379bb572020-05-07 03:23:13 +020096 void operator()(const empty_)
97 {
98 v->set(xpath.c_str(), nullptr, SR_LEAF_EMPTY_T);
99 }
100
Jan Kundrátbb525b42020-02-04 11:56:59 +0100101 void operator()(const std::string& what)
102 {
103 v->set(xpath.c_str(), what.c_str());
104 }
105
Václav Kubernát19097f32020-10-05 10:08:29 +0200106 void operator()(const bits_& what)
107 {
108 std::stringstream ss;
109 std::copy(what.m_bits.begin(), what.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
110 v->set(xpath.c_str(), ss.str().c_str());
111
112 }
113
Jan Kundrátbb525b42020-02-04 11:56:59 +0100114 template <typename Type>
115 void operator()(const Type what)
116 {
117 v->set(xpath.c_str(), what);
118 }
119
120 void operator()([[maybe_unused]] const special_ what)
121 {
122 throw std::logic_error("Attempted to create a SR val from a special_ value");
123 }
124
125 ::sysrepo::S_Val v;
126 std::string xpath;
127};
128
Václav Kubernát654303f2020-07-31 13:16:54 +0200129class OperationalDataCallback {
Jan Kundrátbb525b42020-02-04 11:56:59 +0100130public:
131 OperationalDataCallback(const DataSupplier& dataSupplier)
132 : m_dataSupplier(dataSupplier)
133 {
134 }
Václav Kubernát654303f2020-07-31 13:16:54 +0200135 int operator()(
136 [[maybe_unused]] sysrepo::S_Session sess,
137 [[maybe_unused]] const char *module_name,
138 const char* path,
139 [[maybe_unused]] const char* request_xpath,
140 [[maybe_unused]] uint32_t request_id,
141 libyang::S_Data_Node& parent)
Jan Kundrátbb525b42020-02-04 11:56:59 +0100142 {
Václav Kubernát654303f2020-07-31 13:16:54 +0200143 auto data = m_dataSupplier.get_data(path);
144 libyang::S_Data_Node res;
145 for (const auto& [p, v] : data) {
146 if (!res) {
147 res = std::make_shared<libyang::Data_Node>(
148 sess->get_context(),
149 p.c_str(),
150 v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str(),
151 LYD_ANYDATA_CONSTSTRING,
152 0);
153 } else {
154 res->new_path(
155 sess->get_context(),
156 p.c_str(),
157 v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str(),
158 LYD_ANYDATA_CONSTSTRING,
159 0);
160 }
Jan Kundrátbb525b42020-02-04 11:56:59 +0100161 }
Václav Kubernát654303f2020-07-31 13:16:54 +0200162 parent = res;
Jan Kundrátbb525b42020-02-04 11:56:59 +0100163 return SR_ERR_OK;
164 }
165private:
166 const DataSupplier& m_dataSupplier;
167};
168
Václav Kubernát654303f2020-07-31 13:16:54 +0200169OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const std::string& path, const DataSupplier& dataSupplier)
170 : m_connection(std::make_shared<sysrepo::Connection>())
Jan Kundrátbb525b42020-02-04 11:56:59 +0100171 , m_session(std::make_shared<sysrepo::Session>(m_connection))
172 , m_subscription(std::make_shared<sysrepo::Subscribe>(m_session))
Jan Kundrátbb525b42020-02-04 11:56:59 +0100173{
Václav Kubernát654303f2020-07-31 13:16:54 +0200174 m_subscription->oper_get_items_subscribe(moduleName.c_str(), OperationalDataCallback{dataSupplier}, path.c_str());
Jan Kundrátbb525b42020-02-04 11:56:59 +0100175}