Add support for executing RPCs
Creating a temporary YangAccess for RPC input means I need to somehow
give the right libyang schemas. For that reason I supply a callable
which is able to fetch the schema and create a YangAccess instance for
ProxyDatastore.
The ProxyDatastore class now has a simple mechanism for deciding whether
to use the normal datastore and the temporary based on a path prefix.
Change-Id: Ib455f53237598bc2620161a44fb89c48ddfeb6e3
diff --git a/src/proxy_datastore.cpp b/src/proxy_datastore.cpp
index ab9193c..e6878cb 100644
--- a/src/proxy_datastore.cpp
+++ b/src/proxy_datastore.cpp
@@ -4,36 +4,39 @@
* 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)
+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 m_datastore->getItems(path);
+ return pickDatastore(path)->getItems(path);
}
void ProxyDatastore::setLeaf(const std::string& path, leaf_data_ value)
{
- m_datastore->setLeaf(path, value);
+ pickDatastore(path)->setLeaf(path, value);
}
void ProxyDatastore::createItem(const std::string& path)
{
- m_datastore->createItem(path);
+ pickDatastore(path)->createItem(path);
}
void ProxyDatastore::deleteItem(const std::string& path)
{
- m_datastore->deleteItem(path);
+ pickDatastore(path)->deleteItem(path);
}
void ProxyDatastore::moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move)
{
- m_datastore->moveItem(source, move);
+ pickDatastore(source)->moveItem(source, move);
}
void ProxyDatastore::commitChanges()
@@ -56,7 +59,41 @@
return m_datastore->dump(format);
}
+void ProxyDatastore::initiateRpc(const std::string& rpcPath)
+{
+ if (m_inputDatastore) {
+ throw std::runtime_error("RPC input already in progress (" + m_rpcPath + ")");
+ }
+ m_inputDatastore = m_createTemporaryDatastore(m_datastore);
+ m_rpcPath = rpcPath;
+ m_inputDatastore->createItem(rpcPath);
+}
+
+DatastoreAccess::Tree ProxyDatastore::executeRpc()
+{
+ if (!m_inputDatastore) {
+ throw std::runtime_error("No RPC input in progress");
+ }
+ auto inputData = m_inputDatastore->getItems("/");
+ m_inputDatastore = nullptr;
+ return m_datastore->executeRpc(m_rpcPath, inputData);
+}
+
+void ProxyDatastore::cancelRpc()
+{
+ 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, m_rpcPath)) {
+ return m_datastore;
+ } else {
+ return m_inputDatastore;
+ }
+}