Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 1 | /* |
| 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át | 19097f3 | 2020-10-05 10:08:29 +0200 | [diff] [blame] | 9 | #include <experimental/iterator> |
| 10 | #include <sstream> |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 11 | #include <sysrepo-cpp/Session.hpp> |
| 12 | #include "sysrepo_subscription.hpp" |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 13 | #include "utils.hpp" |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 14 | |
| 15 | |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 16 | class MyCallback { |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 17 | public: |
| 18 | MyCallback(const std::string& moduleName, Recorder* rec) |
| 19 | : m_moduleName(moduleName) |
| 20 | , m_recorder(rec) |
| 21 | { |
| 22 | } |
| 23 | |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 24 | int operator()( |
| 25 | sysrepo::S_Session sess, |
| 26 | const char *module_name, |
| 27 | [[maybe_unused]] const char *xpath, |
| 28 | [[maybe_unused]] sr_event_t event, |
| 29 | [[maybe_unused]] uint32_t request_id) |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 30 | { |
| 31 | using namespace std::string_literals; |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 32 | if (event == SR_EV_CHANGE) { |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 33 | return SR_ERR_OK; |
Václav Kubernát | 3a43323 | 2020-07-08 17:52:50 +0200 | [diff] [blame] | 34 | } |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 35 | |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 36 | auto it = sess->get_changes_iter(("/"s + module_name + ":*//.").c_str()); |
| 37 | |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 38 | while (auto change = sess->get_change_next(it)) { |
Václav Kubernát | 69aabe9 | 2020-01-24 16:53:12 +0100 | [diff] [blame] | 39 | 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át | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 44 | } |
| 45 | |
| 46 | return SR_ERR_OK; |
| 47 | } |
| 48 | |
| 49 | private: |
| 50 | std::string m_moduleName; |
| 51 | Recorder* m_recorder; |
| 52 | }; |
| 53 | |
| 54 | Recorder::~Recorder() = default; |
| 55 | |
Jan Kundrát | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 56 | DataSupplier::~DataSupplier() = default; |
| 57 | |
Václav Kubernát | ab612e9 | 2019-11-26 19:51:31 +0100 | [diff] [blame] | 58 | SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec) |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 59 | : m_connection(std::make_shared<sysrepo::Connection>()) |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 60 | { |
| 61 | m_session = std::make_shared<sysrepo::Session>(m_connection); |
| 62 | m_subscription = std::make_shared<sysrepo::Subscribe>(m_session); |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 63 | sysrepo::ModuleChangeCb cb; |
Václav Kubernát | ab612e9 | 2019-11-26 19:51:31 +0100 | [diff] [blame] | 64 | if (rec) { |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 65 | cb = MyCallback{moduleName, rec}; |
Václav Kubernát | ab612e9 | 2019-11-26 19:51:31 +0100 | [diff] [blame] | 66 | } else { |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 67 | cb = [] (auto, auto, auto, auto, auto) { return SR_ERR_OK; }; |
Václav Kubernát | ab612e9 | 2019-11-26 19:51:31 +0100 | [diff] [blame] | 68 | } |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 69 | |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 70 | m_subscription->module_change_subscribe(moduleName.c_str(), cb); |
Václav Kubernát | 7310938 | 2018-09-14 19:52:03 +0200 | [diff] [blame] | 71 | } |
Jan Kundrát | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 72 | |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 73 | |
Jan Kundrát | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 74 | struct 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át | 379bb57 | 2020-05-07 03:23:13 +0200 | [diff] [blame] | 96 | void operator()(const empty_) |
| 97 | { |
| 98 | v->set(xpath.c_str(), nullptr, SR_LEAF_EMPTY_T); |
| 99 | } |
| 100 | |
Jan Kundrát | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 101 | void operator()(const std::string& what) |
| 102 | { |
| 103 | v->set(xpath.c_str(), what.c_str()); |
| 104 | } |
| 105 | |
Václav Kubernát | 19097f3 | 2020-10-05 10:08:29 +0200 | [diff] [blame] | 106 | 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át | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 114 | 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át | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 129 | class OperationalDataCallback { |
Jan Kundrát | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 130 | public: |
| 131 | OperationalDataCallback(const DataSupplier& dataSupplier) |
| 132 | : m_dataSupplier(dataSupplier) |
| 133 | { |
| 134 | } |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 135 | 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át | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 142 | { |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 143 | 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át | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 161 | } |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 162 | parent = res; |
Jan Kundrát | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 163 | return SR_ERR_OK; |
| 164 | } |
| 165 | private: |
| 166 | const DataSupplier& m_dataSupplier; |
| 167 | }; |
| 168 | |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 169 | OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const std::string& path, const DataSupplier& dataSupplier) |
| 170 | : m_connection(std::make_shared<sysrepo::Connection>()) |
Jan Kundrát | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 171 | , m_session(std::make_shared<sysrepo::Session>(m_connection)) |
| 172 | , m_subscription(std::make_shared<sysrepo::Subscribe>(m_session)) |
Jan Kundrát | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 173 | { |
Václav Kubernát | 654303f | 2020-07-31 13:16:54 +0200 | [diff] [blame^] | 174 | m_subscription->oper_get_items_subscribe(moduleName.c_str(), OperationalDataCallback{dataSupplier}, path.c_str()); |
Jan Kundrát | bb525b4 | 2020-02-04 11:56:59 +0100 | [diff] [blame] | 175 | } |