| /* |
| * Copyright (C) 2020 CESNET, https://photonics.cesnet.cz/ |
| * |
| * Written by Václav Kubernát <kubernat@cesnet.cz> |
| * |
| */ |
| #include <boost/algorithm/string/predicate.hpp> |
| #include "proxy_datastore.hpp" |
| #include "yang_schema.hpp" |
| |
| ProxyDatastore::ProxyDatastore(const std::shared_ptr<DatastoreAccess>& datastore, std::function<std::shared_ptr<DatastoreAccess>(const std::shared_ptr<DatastoreAccess>&)> createTemporaryDatastore) |
| : m_datastore(datastore) |
| , m_createTemporaryDatastore(createTemporaryDatastore) |
| { |
| } |
| |
| DatastoreAccess::Tree ProxyDatastore::getItems(const std::string& path) const |
| { |
| return pickDatastore(path)->getItems(path); |
| } |
| |
| void ProxyDatastore::setLeaf(const std::string& path, leaf_data_ value) |
| { |
| pickDatastore(path)->setLeaf(path, value); |
| } |
| |
| void ProxyDatastore::createItem(const std::string& path) |
| { |
| pickDatastore(path)->createItem(path); |
| } |
| |
| void ProxyDatastore::deleteItem(const std::string& path) |
| { |
| pickDatastore(path)->deleteItem(path); |
| } |
| |
| void ProxyDatastore::moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move) |
| { |
| pickDatastore(source)->moveItem(source, move); |
| } |
| |
| void ProxyDatastore::commitChanges() |
| { |
| m_datastore->commitChanges(); |
| } |
| |
| void ProxyDatastore::discardChanges() |
| { |
| m_datastore->discardChanges(); |
| } |
| |
| void ProxyDatastore::copyConfig(const Datastore source, const Datastore destination) |
| { |
| m_datastore->copyConfig(source, destination); |
| } |
| |
| std::string ProxyDatastore::dump(const DataFormat format) const |
| { |
| return m_datastore->dump(format); |
| } |
| |
| namespace { |
| struct getInputPath |
| { |
| template<typename InputType> |
| auto operator()(const InputType& input) |
| { |
| return input.m_path; |
| } |
| }; |
| } |
| |
| void ProxyDatastore::initiateRpc(const std::string& rpcPath) |
| { |
| if (m_inputDatastore) { |
| throw std::runtime_error("RPC/action input already in progress (" + std::visit(getInputPath{}, m_inputPath) + ")"); |
| } |
| m_inputDatastore = m_createTemporaryDatastore(m_datastore); |
| m_inputPath = RpcInput{rpcPath}; |
| m_inputDatastore->createItem(rpcPath); |
| } |
| |
| void ProxyDatastore::initiateAction(const std::string& actionPath) |
| { |
| if (m_inputDatastore) { |
| throw std::runtime_error("RPC/action input already in progress (" + std::visit(getInputPath{}, m_inputPath) + ")"); |
| } |
| m_inputDatastore = m_createTemporaryDatastore(m_datastore); |
| m_inputPath = ActionInput{actionPath}; |
| m_inputDatastore->createItem(actionPath); |
| } |
| |
| DatastoreAccess::Tree ProxyDatastore::execute() |
| { |
| if (!m_inputDatastore) { |
| throw std::runtime_error("No RPC/action input in progress"); |
| } |
| auto inputData = m_inputDatastore->getItems("/"); |
| m_inputDatastore = nullptr; |
| if (std::holds_alternative<RpcInput>(m_inputPath)) { |
| return m_datastore->executeRpc(std::visit(getInputPath{}, m_inputPath), inputData); |
| } else { |
| return m_datastore->executeAction(std::visit(getInputPath{}, m_inputPath), inputData); |
| } |
| } |
| |
| void ProxyDatastore::cancel() |
| { |
| m_inputDatastore = nullptr; |
| } |
| |
| std::shared_ptr<Schema> ProxyDatastore::schema() const |
| { |
| return m_datastore->schema(); |
| } |
| |
| std::shared_ptr<DatastoreAccess> ProxyDatastore::pickDatastore(const std::string& path) const |
| { |
| if (!m_inputDatastore || !boost::starts_with(path, std::visit(getInputPath{}, m_inputPath))) { |
| return m_datastore; |
| } else { |
| return m_inputDatastore; |
| } |
| } |