diff --git a/etcd/Client.hpp.orig b/etcd/Client.hpp.orig new file mode 100644 index 0000000..4562926 --- /dev/null +++ b/etcd/Client.hpp.orig @@ -0,0 +1,165 @@ +#ifndef __ETCD_CLIENT_HPP__ +#define __ETCD_CLIENT_HPP__ + +#include "etcd/Response.hpp" +#include "v3/include/Transaction.hpp" +#include "v3/include/AsyncTxnResponse.hpp" + +#include +#include + +#include +#include "proto/rpc.grpc.pb.h" + +using etcdserverpb::KV; +using etcdserverpb::Watch; + +namespace etcd +{ + /** + * Client is responsible for maintaining a connection towards an etcd server. + * Etcd operations can be reached via the methods of the client. + */ + class Client + { + public: + /** + * Constructs an etcd client object. + * @param etcd_url is the url of the etcd server to connect to, like "http://127.0.0.1:4001" + */ + Client(std::string const & etcd_url); + + /** + * Sends a get request to the etcd server + * @param key is the key to be read + */ + pplx::task get(std::string const & key); + + /** + * Sets the value of a key. The key will be modified if already exists or created + * if it does not exists. + * @param key is the key to be created or modified + * @param value is the new value to be set + */ + pplx::task set(std::string const & key, std::string const & value); + + /** + * Creates a new key and sets it's value. Fails if the key already exists. + * @param key is the key to be created + * @param value is the value to be set + */ + pplx::task add(std::string const & key, std::string const & value); + + /** + * Modifies an existing key. Fails if the key does not exists. + * @param key is the key to be modified + * @param value is the new value to be set + */ + pplx::task modify(std::string const & key, std::string const & value); + + /** + * Modifies an existing key only if it has a specific value. Fails if the key does not exists + * or the original value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_value is the value to be replaced + */ + pplx::task modify_if(std::string const & key, std::string const & value, std::string const & old_value); + + /** + * Modifies an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of the previous value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_index is the expected index of the original value + */ + pplx::task modify_if(std::string const & key, std::string const & value, int old_index); + + /** + * Removes a single key. The key has to point to a plain, non directory entry. + * @param key is the key to be deleted + */ + pplx::task rm(std::string const & key); + + /** + * Removes a single key but only if it has a specific value. Fails if the key does not exists + * or the its value differs from the expected one. + * @param key is the key to be deleted + */ + pplx::task rm_if(std::string const & key, std::string const & old_value); + + /** + * Removes an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of it differs from the expected one. + * @param key is the key to be deleted + * @param old_index is the expected index of the existing value + */ + pplx::task rm_if(std::string const & key, int old_index); + + /** + * Gets a directory listing of the directory identified by the key. + * @param key is the key to be listed + */ + pplx::task ls(std::string const & key); + + + /** + * Removes a directory node. Fails if the parent directory dos not exists or not a directory. + * @param key is the directory to be created to be listed + * @param recursive if true then delete a whole subtree, otherwise deletes only an empty directory. + */ + pplx::task rmdir(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree. Please note that if you watch e.g. "/testdir" and + * a new key is created, like "/testdir/newkey" then no change happened in the value of + * "/testdir" so your watch will not detect this. If you want to detect addition and deletion of + * directory entries then you have to do a recursive watch. + * @param key is the value or directory to be watched + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree from a specific index. The index value can be in the "past". + * @param key is the value or directory to be watched + * @param fromIndex the first index we are interested in + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, int fromIndex, bool recursive = false); + + protected: + + std::unique_ptr stub_; + std::unique_ptr watchServiceStub; + + std::unique_ptr stub_; + pplx::task send_asyncput(const std::string& key, const std::string& value); + pplx::task send_asyncadd(std::string const & key, const std::string& value); + pplx::task send_asyncmodify(std::string const & key, std::string const & value); + pplx::task send_asyncget(std::string const & key,std::string const& range_end=""); + pplx::task send_put(const std::string& key, const std::string& value); + pplx::task send_get(std::string const & key); + pplx::task send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value); +<<<<<<< a592ce75a199b4e275a50c5f29992aa7dc0ff8d1 + pplx::task send_asyncmodify_if(std::string const & key, std::string const & value, int old_index); + pplx::task send_asyncdelete(std::string const & key, bool recursive); + pplx::task send_asyncrm_if(std::string const &key, std::string const &old_value); + pplx::task send_asyncrm_if(std::string const &key, int old_index); + pplx::task send_asyncwatch(std::string const & key, bool recursive); + pplx::task send_asyncwatch(std::string const & key, int fromIndex, bool recursive); +private: + std::shared_ptr initiate_transaction(const std::string &operation, + etcdv3::Transaction& transaction); +}; +======= + pplx::task send_asyncdelete(std::string const & key, bool recursive); + + }; +>>>>>>> Added delete + + + +} + +#endif diff --git a/etcd/Client_BACKUP_12440.hpp b/etcd/Client_BACKUP_12440.hpp new file mode 100644 index 0000000..e889312 --- /dev/null +++ b/etcd/Client_BACKUP_12440.hpp @@ -0,0 +1,184 @@ +#ifndef __ETCD_CLIENT_HPP__ +#define __ETCD_CLIENT_HPP__ + +#include "etcd/Response.hpp" + +#include +#include + +#include +#include "proto/rpc.grpc.pb.h" + +<<<<<<< b05a30586ef0191ca0d81fb87d79d781fc89f341 + +using grpc::Channel; +using grpc::ClientAsyncResponseReader; +using grpc::ClientContext; +using grpc::CompletionQueue; +using grpc::Status; +using etcdserverpb::PutRequest; +using etcdserverpb::PutResponse; +using etcdserverpb::RangeRequest; +using etcdserverpb::RangeResponse; +======= +>>>>>>> Use Txn +using etcdserverpb::KV; +using etcdserverpb::Watch; + +namespace etcd +{ + /** + * Client is responsible for maintaining a connection towards an etcd server. + * Etcd operations can be reached via the methods of the client. + */ + class Client + { + public: + /** + * Constructs an etcd client object. + * @param etcd_url is the url of the etcd server to connect to, like "http://127.0.0.1:4001" + */ + Client(std::string const & etcd_url); + + /** + * Sends a get request to the etcd server + * @param key is the key to be read + */ + pplx::task get(std::string const & key); + + /** + * Sets the value of a key. The key will be modified if already exists or created + * if it does not exists. + * @param key is the key to be created or modified + * @param value is the new value to be set + */ + pplx::task set(std::string const & key, std::string const & value); + + /** + * Creates a new key and sets it's value. Fails if the key already exists. + * @param key is the key to be created + * @param value is the value to be set + */ + pplx::task add(std::string const & key, std::string const & value); + + /** + * Modifies an existing key. Fails if the key does not exists. + * @param key is the key to be modified + * @param value is the new value to be set + */ + pplx::task modify(std::string const & key, std::string const & value); + + /** + * Modifies an existing key only if it has a specific value. Fails if the key does not exists + * or the original value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_value is the value to be replaced + */ + pplx::task modify_if(std::string const & key, std::string const & value, std::string const & old_value); + + /** + * Modifies an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of the previous value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_index is the expected index of the original value + */ + pplx::task modify_if(std::string const & key, std::string const & value, int old_index); + + /** + * Removes a single key. The key has to point to a plain, non directory entry. + * @param key is the key to be deleted + */ + pplx::task rm(std::string const & key); + + /** + * Removes a single key but only if it has a specific value. Fails if the key does not exists + * or the its value differs from the expected one. + * @param key is the key to be deleted + */ + pplx::task rm_if(std::string const & key, std::string const & old_value); + + /** + * Removes an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of it differs from the expected one. + * @param key is the key to be deleted + * @param old_index is the expected index of the existing value + */ + pplx::task rm_if(std::string const & key, int old_index); + + /** + * Gets a directory listing of the directory identified by the key. + * @param key is the key to be listed + */ + pplx::task ls(std::string const & key); + + /** + * Creates a new directory node. Fails if the parent directory dos not exists or not a directory. + * @param key is the directory to be created to be listed + */ + pplx::task mkdir(std::string const & key); + + /** + * Removes a directory node. Fails if the parent directory dos not exists or not a directory. + * @param key is the directory to be created to be listed + * @param recursive if true then delete a whole subtree, otherwise deletes only an empty directory. + */ + pplx::task rmdir(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree. Please note that if you watch e.g. "/testdir" and + * a new key is created, like "/testdir/newkey" then no change happened in the value of + * "/testdir" so your watch will not detect this. If you want to detect addition and deletion of + * directory entries then you have to do a recursive watch. + * @param key is the value or directory to be watched + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree from a specific index. The index value can be in the "past". + * @param key is the value or directory to be watched + * @param fromIndex the first index we are interested in + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, int fromIndex, bool recursive = false); + + protected: + + pplx::task send_get_request(web::http::uri_builder & uri); + pplx::task send_del_request(web::http::uri_builder & uri); + pplx::task send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value); + + web::http::client::http_client client; + + std::unique_ptr stub_; + pplx::task send_asyncput(const std::string& key, const std::string& value); + std::unique_ptr watchServiceStub; + pplx::task send_asyncget(std::string const & key); + pplx::task send_asyncadd(std::string const & key, const std::string& value); + pplx::task send_asyncmodify(std::string const & key, std::string const & value); +<<<<<<< b05a30586ef0191ca0d81fb87d79d781fc89f341 + pplx::task send_put(const std::string& key, const std::string& value); + pplx::task send_get(std::string const & key); + pplx::task send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value); + + etcdv3::grpcClient grpcClient; + +private: + pplx::task removeEntryWithKey(std::string const &entryKey); + pplx::task removeEntryWithKeyAndValue(std::string const &entryKey, std::string const &oldValue); + pplx::task removeEntryWithKeyAndIndex(std::string const &entryKey, int oldIndex); + pplx::task modifyEntryWithValueAndOldIndex(std::string const & key, std::string const & value, int old_index); + +======= + pplx::task send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value); +>>>>>>> Use Txn + + }; + + + +} + +#endif diff --git a/etcd/Client_BASE_12440.hpp b/etcd/Client_BASE_12440.hpp new file mode 100644 index 0000000..fc00308 --- /dev/null +++ b/etcd/Client_BASE_12440.hpp @@ -0,0 +1,162 @@ +#ifndef __ETCD_CLIENT_HPP__ +#define __ETCD_CLIENT_HPP__ + +#include "etcd/Response.hpp" + +#include +#include + +#include +#include "proto/rpc.grpc.pb.h" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/grpcClient.hpp" + + +using grpc::Channel; +using etcdserverpb::PutRequest; +using etcdserverpb::RangeRequest; +using etcdserverpb::KV; + +namespace etcd +{ + /** + * Client is responsible for maintaining a connection towards an etcd server. + * Etcd operations can be reached via the methods of the client. + */ + class Client + { + public: + /** + * Constructs an etcd client object. + * @param etcd_url is the url of the etcd server to connect to, like "http://127.0.0.1:4001" + */ + Client(std::string const & etcd_url); + + /** + * Sends a get request to the etcd server + * @param key is the key to be read + */ + pplx::task get(std::string const & key); + + /** + * Sets the value of a key. The key will be modified if already exists or created + * if it does not exists. + * @param key is the key to be created or modified + * @param value is the new value to be set + */ + pplx::task set(std::string const & key, std::string const & value); + + /** + * Creates a new key and sets it's value. Fails if the key already exists. + * @param key is the key to be created + * @param value is the value to be set + */ + pplx::task add(std::string const & key, std::string const & value); + + /** + * Modifies an existing key. Fails if the key does not exists. + * @param key is the key to be modified + * @param value is the new value to be set + */ + pplx::task modify(std::string const & key, std::string const & value); + + /** + * Modifies an existing key only if it has a specific value. Fails if the key does not exists + * or the original value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_value is the value to be replaced + */ + pplx::task modify_if(std::string const & key, std::string const & value, std::string const & old_value); + + /** + * Modifies an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of the previous value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_index is the expected index of the original value + */ + pplx::task modify_if(std::string const & key, std::string const & value, int old_index); + + /** + * Removes a single key. The key has to point to a plain, non directory entry. + * @param key is the key to be deleted + */ + pplx::task rm(std::string const & key); + + /** + * Removes a single key but only if it has a specific value. Fails if the key does not exists + * or the its value differs from the expected one. + * @param key is the key to be deleted + */ + pplx::task rm_if(std::string const & key, std::string const & old_value); + + /** + * Removes an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of it differs from the expected one. + * @param key is the key to be deleted + * @param old_index is the expected index of the existing value + */ + pplx::task rm_if(std::string const & key, int old_index); + + /** + * Gets a directory listing of the directory identified by the key. + * @param key is the key to be listed + */ + pplx::task ls(std::string const & key); + + /** + * Creates a new directory node. Fails if the parent directory dos not exists or not a directory. + * @param key is the directory to be created to be listed + */ + pplx::task mkdir(std::string const & key); + + /** + * Removes a directory node. Fails if the parent directory dos not exists or not a directory. + * @param key is the directory to be created to be listed + * @param recursive if true then delete a whole subtree, otherwise deletes only an empty directory. + */ + pplx::task rmdir(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree. Please note that if you watch e.g. "/testdir" and + * a new key is created, like "/testdir/newkey" then no change happened in the value of + * "/testdir" so your watch will not detect this. If you want to detect addition and deletion of + * directory entries then you have to do a recursive watch. + * @param key is the value or directory to be watched + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree from a specific index. The index value can be in the "past". + * @param key is the value or directory to be watched + * @param fromIndex the first index we are interested in + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, int fromIndex, bool recursive = false); + + protected: + + pplx::task send_get_request(web::http::uri_builder & uri); + pplx::task send_del_request(web::http::uri_builder & uri); + pplx::task send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value); + + web::http::client::http_client client; + + pplx::task send_asyncput(const std::string& key, const std::string& value); + pplx::task send_asyncget(std::string const & key); + pplx::task send_asyncadd(std::string const & key, const std::string& value); + pplx::task send_asyncmodify(std::string const & key, std::string const & value); + pplx::task send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value); + + etcdv3::grpcClient grpcClient; + + + }; + + + +} + +#endif diff --git a/etcd/Client_LOCAL_12440.hpp b/etcd/Client_LOCAL_12440.hpp new file mode 100644 index 0000000..498f512 --- /dev/null +++ b/etcd/Client_LOCAL_12440.hpp @@ -0,0 +1,179 @@ +#ifndef __ETCD_CLIENT_HPP__ +#define __ETCD_CLIENT_HPP__ + +#include "etcd/Response.hpp" + +#include +#include + +#include +#include "proto/rpc.grpc.pb.h" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/grpcClient.hpp" + + +using grpc::Channel; +using grpc::ClientAsyncResponseReader; +using grpc::ClientContext; +using grpc::CompletionQueue; +using grpc::Status; +using etcdserverpb::PutRequest; +using etcdserverpb::PutResponse; +using etcdserverpb::RangeRequest; +using etcdserverpb::RangeResponse; +using etcdserverpb::KV; +using etcdserverpb::Watch; + +namespace etcd +{ + /** + * Client is responsible for maintaining a connection towards an etcd server. + * Etcd operations can be reached via the methods of the client. + */ + class Client + { + public: + /** + * Constructs an etcd client object. + * @param etcd_url is the url of the etcd server to connect to, like "http://127.0.0.1:4001" + */ + Client(std::string const & etcd_url); + + /** + * Sends a get request to the etcd server + * @param key is the key to be read + */ + pplx::task get(std::string const & key); + + /** + * Sets the value of a key. The key will be modified if already exists or created + * if it does not exists. + * @param key is the key to be created or modified + * @param value is the new value to be set + */ + pplx::task set(std::string const & key, std::string const & value); + + /** + * Creates a new key and sets it's value. Fails if the key already exists. + * @param key is the key to be created + * @param value is the value to be set + */ + pplx::task add(std::string const & key, std::string const & value); + + /** + * Modifies an existing key. Fails if the key does not exists. + * @param key is the key to be modified + * @param value is the new value to be set + */ + pplx::task modify(std::string const & key, std::string const & value); + + /** + * Modifies an existing key only if it has a specific value. Fails if the key does not exists + * or the original value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_value is the value to be replaced + */ + pplx::task modify_if(std::string const & key, std::string const & value, std::string const & old_value); + + /** + * Modifies an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of the previous value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_index is the expected index of the original value + */ + pplx::task modify_if(std::string const & key, std::string const & value, int old_index); + + /** + * Removes a single key. The key has to point to a plain, non directory entry. + * @param key is the key to be deleted + */ + pplx::task rm(std::string const & key); + + /** + * Removes a single key but only if it has a specific value. Fails if the key does not exists + * or the its value differs from the expected one. + * @param key is the key to be deleted + */ + pplx::task rm_if(std::string const & key, std::string const & old_value); + + /** + * Removes an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of it differs from the expected one. + * @param key is the key to be deleted + * @param old_index is the expected index of the existing value + */ + pplx::task rm_if(std::string const & key, int old_index); + + /** + * Gets a directory listing of the directory identified by the key. + * @param key is the key to be listed + */ + pplx::task ls(std::string const & key); + + /** + * Creates a new directory node. Fails if the parent directory dos not exists or not a directory. + * @param key is the directory to be created to be listed + */ + pplx::task mkdir(std::string const & key); + + /** + * Removes a directory node. Fails if the parent directory dos not exists or not a directory. + * @param key is the directory to be created to be listed + * @param recursive if true then delete a whole subtree, otherwise deletes only an empty directory. + */ + pplx::task rmdir(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree. Please note that if you watch e.g. "/testdir" and + * a new key is created, like "/testdir/newkey" then no change happened in the value of + * "/testdir" so your watch will not detect this. If you want to detect addition and deletion of + * directory entries then you have to do a recursive watch. + * @param key is the value or directory to be watched + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree from a specific index. The index value can be in the "past". + * @param key is the value or directory to be watched + * @param fromIndex the first index we are interested in + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, int fromIndex, bool recursive = false); + + protected: + + pplx::task send_get_request(web::http::uri_builder & uri); + pplx::task send_del_request(web::http::uri_builder & uri); + pplx::task send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value); + + web::http::client::http_client client; + + std::unique_ptr stub_; + pplx::task send_asyncput(const std::string& key, const std::string& value); + std::unique_ptr watchServiceStub; + pplx::task send_asyncget(std::string const & key); + pplx::task send_asyncadd(std::string const & key, const std::string& value); + pplx::task send_asyncmodify(std::string const & key, std::string const & value); + pplx::task send_put(const std::string& key, const std::string& value); + pplx::task send_get(std::string const & key); + pplx::task send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value); + + etcdv3::grpcClient grpcClient; + +private: + pplx::task removeEntryWithKey(std::string const &entryKey); + pplx::task removeEntryWithKeyAndValue(std::string const &entryKey, std::string const &oldValue); + pplx::task removeEntryWithKeyAndIndex(std::string const &entryKey, int oldIndex); + pplx::task modifyEntryWithValueAndOldIndex(std::string const & key, std::string const & value, int old_index); + + + }; + + + +} + +#endif diff --git a/etcd/Client_REMOTE_12440.hpp b/etcd/Client_REMOTE_12440.hpp new file mode 100644 index 0000000..c138d50 --- /dev/null +++ b/etcd/Client_REMOTE_12440.hpp @@ -0,0 +1,154 @@ +#ifndef __ETCD_CLIENT_HPP__ +#define __ETCD_CLIENT_HPP__ + +#include "etcd/Response.hpp" + +#include +#include + +#include +#include "proto/rpc.grpc.pb.h" + +using etcdserverpb::KV; + +namespace etcd +{ + /** + * Client is responsible for maintaining a connection towards an etcd server. + * Etcd operations can be reached via the methods of the client. + */ + class Client + { + public: + /** + * Constructs an etcd client object. + * @param etcd_url is the url of the etcd server to connect to, like "http://127.0.0.1:4001" + */ + Client(std::string const & etcd_url); + + /** + * Sends a get request to the etcd server + * @param key is the key to be read + */ + pplx::task get(std::string const & key); + + /** + * Sets the value of a key. The key will be modified if already exists or created + * if it does not exists. + * @param key is the key to be created or modified + * @param value is the new value to be set + */ + pplx::task set(std::string const & key, std::string const & value); + + /** + * Creates a new key and sets it's value. Fails if the key already exists. + * @param key is the key to be created + * @param value is the value to be set + */ + pplx::task add(std::string const & key, std::string const & value); + + /** + * Modifies an existing key. Fails if the key does not exists. + * @param key is the key to be modified + * @param value is the new value to be set + */ + pplx::task modify(std::string const & key, std::string const & value); + + /** + * Modifies an existing key only if it has a specific value. Fails if the key does not exists + * or the original value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_value is the value to be replaced + */ + pplx::task modify_if(std::string const & key, std::string const & value, std::string const & old_value); + + /** + * Modifies an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of the previous value differs from the expected one. + * @param key is the key to be modified + * @param value is the new value to be set + * @param old_index is the expected index of the original value + */ + pplx::task modify_if(std::string const & key, std::string const & value, int old_index); + + /** + * Removes a single key. The key has to point to a plain, non directory entry. + * @param key is the key to be deleted + */ + pplx::task rm(std::string const & key); + + /** + * Removes a single key but only if it has a specific value. Fails if the key does not exists + * or the its value differs from the expected one. + * @param key is the key to be deleted + */ + pplx::task rm_if(std::string const & key, std::string const & old_value); + + /** + * Removes an existing key only if it has a specific modification index value. Fails if the key + * does not exists or the modification index of it differs from the expected one. + * @param key is the key to be deleted + * @param old_index is the expected index of the existing value + */ + pplx::task rm_if(std::string const & key, int old_index); + + /** + * Gets a directory listing of the directory identified by the key. + * @param key is the key to be listed + */ + pplx::task ls(std::string const & key); + + /** + * Creates a new directory node. Fails if the parent directory dos not exists or not a directory. + * @param key is the directory to be created to be listed + */ + pplx::task mkdir(std::string const & key); + + /** + * Removes a directory node. Fails if the parent directory dos not exists or not a directory. + * @param key is the directory to be created to be listed + * @param recursive if true then delete a whole subtree, otherwise deletes only an empty directory. + */ + pplx::task rmdir(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree. Please note that if you watch e.g. "/testdir" and + * a new key is created, like "/testdir/newkey" then no change happened in the value of + * "/testdir" so your watch will not detect this. If you want to detect addition and deletion of + * directory entries then you have to do a recursive watch. + * @param key is the value or directory to be watched + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, bool recursive = false); + + /** + * Watches for changes of a key or a subtree from a specific index. The index value can be in the "past". + * @param key is the value or directory to be watched + * @param fromIndex the first index we are interested in + * @param recursive if true watch a whole subtree + */ + pplx::task watch(std::string const & key, int fromIndex, bool recursive = false); + + protected: + + pplx::task send_get_request(web::http::uri_builder & uri); + pplx::task send_del_request(web::http::uri_builder & uri); + pplx::task send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value); + + web::http::client::http_client client; + + std::unique_ptr stub_; + pplx::task send_asyncput(const std::string& key, const std::string& value); + pplx::task send_asyncget(std::string const & key); + pplx::task send_asyncadd(std::string const & key, const std::string& value); + pplx::task send_asyncmodify(std::string const & key, std::string const & value); + pplx::task send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value); + + }; + + + +} + +#endif diff --git a/etcd/Response.hpp.orig b/etcd/Response.hpp.orig new file mode 100644 index 0000000..d7256e2 --- /dev/null +++ b/etcd/Response.hpp.orig @@ -0,0 +1,131 @@ +#ifndef __ETCD_RESPONSE_HPP__ +#define __ETCD_RESPONSE_HPP__ + +#include +#include +#include + +#include "etcd/Value.hpp" +#include + +#include "v3/include/V3Response.hpp" +#include + +#include + +namespace etcd +{ + typedef std::vector Keys; + + /** + * The Reponse object received for the requests of etcd::Client + */ + class Response + { + public: + static pplx::task create(pplx::task response_task); + +<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77 +======= + static pplx::task createResponse(const etcdv3::V3Response& response); + +>>>>>>> make templated create with shared_ptr arguement + templatestatic pplx::task create(std::shared_ptr call) + { + return pplx::task([call]() + { +<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77 + etcd::Response resp; + + call->waitForResponse(); +======= + void* got_tag; + bool ok = false; + etcd::Response resp; + + //blocking + call->cq_.Next(&got_tag, &ok); + GPR_ASSERT(got_tag == (void*)call.get()); +>>>>>>> make templated create with shared_ptr arguement + + auto v3resp = call->ParseResponse(); + + resp = etcd::Response(v3resp); + + return resp; + }); + }; + + Response(); + + /** + * Returns true if this is a successful response + */ + bool is_ok() const; + + /** + * Returns the error code received from the etcd server. In case of success the error code is 0. + */ + int error_code() const; + + /** + * Returns the string representation of the error code + */ + std::string const & error_message() const; + + /** + * Returns the action type of the operation that this response belongs to. + */ + std::string const & action() const; + + /** + * Returns the current index value of etcd + */ + int index() const; + + /** + * Returns the value object of the response to a get/set/modify operation. + */ + Value const & value() const; + + /** + * Returns the previous value object of the response to a set/modify/rm operation. + */ + Value const & prev_value() const; + + /** + * Returns the index-th value of the response to an 'ls' operation. Equivalent to values()[index] + */ + Value const & value(int index) const; + + /** + * Returns the vector of values in a directory in response to an 'ls' operation. + */ + Values const & values() const; + + /** + * Returns the vector of keys in a directory in response to an 'ls' operation. + */ + Keys const & keys() const; + + /** + * Returns the index-th key in a directory listing. Same as keys()[index] + */ + std::string const & key(int index) const; + + protected: + Response(web::http::http_response http_response, web::json::value json_value); + Response(const etcdv3::V3Response& response); + + int _error_code; + std::string _error_message; + int _index; + std::string _action; + Value _value; + Value _prev_value; + Values _values; + Keys _keys; + }; +} + +#endif diff --git a/src/CMakeLists.txt.orig b/src/CMakeLists.txt.orig new file mode 100644 index 0000000..cd58fe3 --- /dev/null +++ b/src/CMakeLists.txt.orig @@ -0,0 +1,14 @@ +<<<<<<< 18e11819d9a15bd08dcaf09c41fb91ae8cb0aa52 +add_library(etcd-cpp-api SHARED ../proto/kv.pb.cc ../proto/auth.pb.cc ../proto/rpc.pb.cc ../proto/rpc.grpc.pb.cc ../v3/src/AsyncTxnResponse.cpp ../v3/src/AsyncRangeResponse.cpp ../v3/src/AsyncWatchResponse.cpp ../v3/src/Transaction.cpp Client.cpp Response.cpp Value.cpp json_constants.cpp) +======= +add_library(etcd-cpp-api SHARED ../proto/kv.pb.cc ../proto/auth.pb.cc ../proto/rpc.pb.cc ../proto/rpc.grpc.pb.cc ../v3/src/AsyncRangeResponse ../v3/src/AsyncTxnResponse.cpp Client.cpp Response.cpp Value.cpp json_constants.cpp) +>>>>>>> Added implementation for ls +set_property(TARGET etcd-cpp-api PROPERTY CXX_STANDARD 11) + +target_link_libraries(etcd-cpp-api ${CPPREST_LIB} boost_system ssl crypto protobuf grpc++) + +install (TARGETS etcd-cpp-api DESTINATION lib) +install (FILES ../etcd/Client.hpp + ../etcd/Response.hpp + ../etcd/Value.hpp + DESTINATION include/etcd) diff --git a/src/Client.cpp.orig b/src/Client.cpp.orig new file mode 100644 index 0000000..12dcdda --- /dev/null +++ b/src/Client.cpp.orig @@ -0,0 +1,553 @@ +#include +#include "etcd/Client.hpp" +#include "v3/include/AsyncTxnResponse.hpp" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/AsyncWatchResponse.hpp" +#include "v3/include/Transaction.hpp" +#include + +using grpc::Channel; +using etcdserverpb::PutRequest; +using etcdserverpb::RangeRequest; +using etcdserverpb::TxnRequest; +using etcdserverpb::DeleteRangeRequest; +using etcdserverpb::Compare; +using etcdserverpb::RequestOp; + +using grpc::ClientReaderWriter; +using etcdserverpb::WatchRequest; +using etcdserverpb::WatchResponse; +using etcdserverpb::WatchCreateRequest; + +using grpc::Channel; +using etcdserverpb::PutRequest; +using etcdserverpb::RangeRequest; +using etcdserverpb::TxnRequest; +using etcdserverpb::DeleteRangeRequest; +using etcdserverpb::Compare; +using etcdserverpb::RequestOp; + +using grpc::ClientReaderWriter; +using etcdserverpb::WatchRequest; +using etcdserverpb::WatchResponse; +using etcdserverpb::WatchCreateRequest; + +etcd::Client::Client(std::string const & address) +{ + std::string stripped_address(address); + std::string substr("http://"); + std::string::size_type i = stripped_address.find(substr); + if(i != std::string::npos) + { + stripped_address.erase(i,substr.length()); + } + std::shared_ptr channel = grpc::CreateChannel(stripped_address, grpc::InsecureChannelCredentials()); + stub_= KV::NewStub(channel); +<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77 + { + stripped_address.erase(i,substr.length()); + } + std::shared_ptr channel = grpc::CreateChannel(stripped_address, grpc::InsecureChannelCredentials()); + stub_= KV::NewStub(channel); + watchServiceStub= Watch::NewStub(channel); +======= + stub1_= Watch::NewStub(channel); +>>>>>>> make templated create with shared_ptr arguement +} + + +pplx::task etcd::Client::get(std::string const & key) +{ + return send_asyncget(key); +} + +pplx::task etcd::Client::set(std::string const & key, std::string const & value) +{ + return send_asyncput(key,value); +} + +pplx::task etcd::Client::add(std::string const & key, std::string const & value) +{ + return send_asyncadd(key,value); +} + +pplx::task etcd::Client::modify(std::string const & key, std::string const & value) +{ + return send_asyncmodify(key,value); +} + + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + return send_asyncmodify_if(key, value, old_value); +} + + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, int old_index) +{ + return send_asyncmodify_if(key, value, old_index); +} + + +pplx::task etcd::Client::rm(std::string const & key) +{ + return send_asyncdelete(key,false); +} + + +pplx::task etcd::Client::rm_if(std::string const & key, std::string const & old_value) +{ + return send_asyncrm_if(key, old_value); +} + + +pplx::task etcd::Client::rm_if(std::string const & key, int old_index) +{ + return send_asyncrm_if(key, old_index); + + +} + + + +pplx::task etcd::Client::rmdir(std::string const & key, bool recursive) +{ + + return send_asyncdelete(key,recursive); + + return send_asyncdelete(key,recursive); +} + + +pplx::task etcd::Client::ls(std::string const & key) +{ + + std::string range_end(key); + int ascii = (int)range_end[range_end.length()-1]; + range_end.back() = ascii+1; + + return send_asyncget(key,range_end); +} + + +pplx::task etcd::Client::watch(std::string const & key, bool recursive) +{ + return send_asyncwatch(key,recursive); +} + + +pplx::task etcd::Client::watch(std::string const & key, int fromIndex, bool recursive) +{ + return send_asyncwatch(key, fromIndex, recursive); +} + + +std::shared_ptr etcd::Client::initiate_transaction(const std::string &operation, + etcdv3::Transaction& transaction) +{ + std::shared_ptr call(new etcdv3::AsyncTxnResponse(operation)); + call->response_reader = stub_->AsyncTxn(&call->context, transaction.txn_request, &call->cq_); + call->response_reader->Finish(&call->reply, &call->status, (void*) (call.get())); + return call; +} + + +pplx::task etcd::Client::send_asyncadd(std::string const & key, std::string const & value) +{ + etcdv3::Transaction transaction(key); + transaction.init_compare(Compare::CompareResult::Compare_CompareResult_EQUAL, + Compare::CompareTarget::Compare_CompareTarget_VERSION); + + transaction.setup_basic_failure_operation(key); + transaction.setup_basic_create_sequence(key, value); + + std::shared_ptr call = initiate_transaction("create", transaction); + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + etcdv3::Transaction transaction(key); + transaction.init_compare(old_value, Compare::CompareResult::Compare_CompareResult_EQUAL, + Compare::CompareTarget::Compare_CompareTarget_VALUE); + + transaction.setup_basic_failure_operation(key); + transaction.setup_compare_and_swap_sequence(value); + + std::shared_ptr call = initiate_transaction("compareAndSwap", transaction); + return Response::create(call); +} + put_request->set_value(value); + + RequestOp* req_success = txn_request.add_success(); + req_success->set_allocated_request_put(put_request.release()); + + get_request.reset(new RangeRequest()); + get_request->set_key(key); + req_success = txn_request.add_success(); + req_success->set_allocated_request_range(get_request.release()); + + + std::shared_ptr call(new etcdv3::AsyncTxnResponse("create")); + + call->response_reader = stub_->AsyncTxn(&call->context,txn_request,&call->cq_); + +<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77 +======= + call->response_reader->Finish(&call->reply, &call->status, (void*)call.get()); +>>>>>>> make templated create with shared_ptr arguement + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, int old_index) +{ + etcdv3::Transaction transaction(key); + transaction.init_compare(old_index, Compare::CompareResult::Compare_CompareResult_EQUAL, + Compare::CompareTarget::Compare_CompareTarget_MOD); + + transaction.setup_basic_failure_operation(key); + transaction.setup_compare_and_swap_sequence(value); + + std::shared_ptr call = initiate_transaction("compareAndSwap", transaction); + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncmodify(std::string const & key, std::string const & value) +{ + etcdv3::Transaction transaction(key); + transaction.init_compare(Compare::CompareResult::Compare_CompareResult_GREATER, + Compare::CompareTarget::Compare_CompareTarget_VERSION); + + transaction.setup_basic_failure_operation(key); + transaction.setup_compare_and_swap_sequence(value); + + std::shared_ptr call = initiate_transaction("update", transaction); + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncget(std::string const & key, std::string const& range_end) +{ + RangeRequest get_request; + get_request.set_key(key); + if(!range_end.empty()) + { + get_request.set_range_end(range_end); + get_request.set_sort_target(RangeRequest::SortTarget::RangeRequest_SortTarget_KEY); + get_request.set_sort_order(RangeRequest::SortOrder::RangeRequest_SortOrder_ASCEND); + + std::shared_ptr call(new etcdv3::AsyncRangeResponse()); + call->response_reader = stub_->AsyncRange(&call->context,get_request,&call->cq_); + call->response_reader->Finish(&call->reply, &call->status, (void*)call.get()); + compare->set_target(Compare::CompareTarget::Compare_CompareTarget_VALUE); + compare->set_key(key); + compare->set_value(old_value); + + return Response::create(call); +} + get_request->set_key(key); + RequestOp* req_failure = txn_request.add_failure(); + req_failure->set_allocated_request_range(get_request.release()); + + req_success->set_allocated_request_range(get_request.release()); + +pplx::task etcd::Client::send_asyncput(std::string const & key, std::string const & value) +{ + etcdv3::Transaction transaction(key); + transaction.init_compare(Compare::CompareResult::Compare_CompareResult_EQUAL, + Compare::CompareTarget::Compare_CompareTarget_VERSION); + + get_request.reset(new RangeRequest()); + get_request->set_key(key); + req_success = txn_request.add_success(); + req_success->set_allocated_request_range(get_request.release()); + + + + std::shared_ptr call(new etcdv3::AsyncTxnResponse("compareAndSwap")); + + call->response_reader = stub_->AsyncTxn(&call->context,txn_request,&call->cq_); + +<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77 + transaction.setup_set_failure_operation(key, value); + transaction.setup_basic_create_sequence(key, value); +======= + call->response_reader->Finish(&call->reply, &call->status, (void*)call.get()); +>>>>>>> make templated create with shared_ptr arguement + + std::shared_ptr call = initiate_transaction("set", transaction); + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncdelete(std::string const & key, bool recursive) +{ + etcdv3::Transaction transaction(key); + transaction.init_compare(Compare::CompareResult::Compare_CompareResult_GREATER, + Compare::CompareTarget::Compare_CompareTarget_VERSION); + + std::string range_end(key); + if(recursive) + compare->set_result(Compare::CompareResult::Compare_CompareResult_GREATER); + int ascii = (int)range_end[range_end.length()-1]; + range_end.back() = ascii+1; + + transaction.setup_delete_sequence(key, range_end, recursive); + transaction.setup_delete_failure_operation(key, range_end, recursive); + get_request->set_key(key); + RequestOp* req_failure = txn_request.add_failure(); + req_failure->set_allocated_request_range(get_request.release()); + + std::shared_ptr call = initiate_transaction("delete", transaction); + return Response::create(call); +} + req_success->set_allocated_request_range(get_request.release()); + + +pplx::task etcd::Client::send_asyncrm_if(std::string const &key, std::string const &old_value) +{ + etcdv3::Transaction transaction(key); + transaction.init_compare(old_value, Compare::CompareResult::Compare_CompareResult_EQUAL, + Compare::CompareTarget::Compare_CompareTarget_VALUE); + req_success = txn_request.add_success(); + req_success->set_allocated_request_put(put_request.release()); + + get_request.reset(new RangeRequest()); + get_request->set_key(key); + req_success = txn_request.add_success(); + req_success->set_allocated_request_range(get_request.release()); + + + std::shared_ptr call(new etcdv3::AsyncTxnResponse("update")); + + call->response_reader = stub_->AsyncTxn(&call->context,txn_request,&call->cq_); + +<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77 + transaction.setup_compare_and_delete_operation(key); + transaction.setup_basic_failure_operation(key); +======= + call->response_reader->Finish(&call->reply, &call->status, (void*)call.get()); + + return Response::create(call); +>>>>>>> make templated create with shared_ptr arguement + + std::shared_ptr call = initiate_transaction("compareAndDelete", transaction); + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncrm_if(std::string const &key, int old_index) { + etcdv3::Transaction transaction(key); + transaction.init_compare(old_index, Compare::CompareResult::Compare_CompareResult_EQUAL, + Compare::CompareTarget::Compare_CompareTarget_MOD); + if(!range_end.empty()) + { + get_request.set_range_end(range_end); + get_request.set_sort_target(RangeRequest::SortTarget::RangeRequest_SortTarget_KEY); + get_request.set_sort_order(RangeRequest::SortOrder::RangeRequest_SortOrder_ASCEND); + } + + std::shared_ptr call(new etcdv3::AsyncRangeResponse()); + + call->response_reader = stub_->AsyncRange(&call->context,get_request,&call->cq_); + +<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77 + transaction.setup_compare_and_delete_operation(key); + transaction.setup_basic_failure_operation(key); +======= + call->response_reader->Finish(&call->reply, &call->status, (void*)call.get()); +>>>>>>> make templated create with shared_ptr arguement + + std::shared_ptr call = initiate_transaction("compareAndDelete", transaction); + return Response::create(call); +} + +pplx::task etcd::Client::send_asyncwatch(std::string const & key, bool recursive) +{ +<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77 + std::shared_ptr call(new etcdv3::AsyncWatchResponse()); + call->stream = watchServiceStub->AsyncWatch(&call->context,&call->cq_,(void*)call.get()); +======= +#if 0 + //try watch here: + ClientContext context; + std::shared_ptr> stream(stub1_->Watch(&context)); + + WatchRequest watch_req; + WatchCreateRequest watch_create_req; + watch_create_req.set_key(key); + watch_req.mutable_create_request()->CopyFrom(watch_create_req); + + stream->Write(watch_req); + + std::cout<< "write finished" << std::endl; + + WatchResponse server_resp; + while(stream->Read(&server_resp)) + { + std::cout<< "read...watch id: "<< server_resp.watch_id()<< std::endl; + if(server_resp.events_size()) + { + std::cout << "event type: " << server_resp.events(0).type() << std::endl; + std::cout << "key: " << server_resp.events(0).kv().key() << std::endl; + std::cout << "value: " << server_resp.events(0).kv().value() << std::endl; + stream->WritesDone(); + + } + } + Status status = stream->Finish(); + if(!status.ok()) + { + std::cout << "rpc failed" << std::endl; + } +#endif +>>>>>>> make templated create with shared_ptr arguement + + WatchRequest watch_req; + WatchCreateRequest watch_create_req; + watch_create_req.set_key(key); + compare->set_result(Compare::CompareResult::Compare_CompareResult_EQUAL); + compare->set_target(Compare::CompareTarget::Compare_CompareTarget_VERSION); + compare->set_key(key); + compare->set_version(0); + + std::string range_end(key); + if(recursive) + RequestOp* req_failure = txn_request.add_failure(); + int ascii = (int)range_end[range_end.length()-1]; + range_end.back() = ascii+1; + watch_create_req.set_range_end(range_end); + + put_request->set_value(value); + req_failure = txn_request.add_failure(); + req_failure->set_allocated_request_put(put_request.release()); + + watch_req.mutable_create_request()->CopyFrom(watch_create_req); + call->stream->Write(watch_req, (void*)call.get()); + call->stub_ = stub_.get(); + req_failure->set_allocated_request_range(get_request.release()); + + return Response::create(call); +} + put_request.reset(new PutRequest()); + put_request->set_key(key); + put_request->set_value(value); + RequestOp* req_success = txn_request.add_success(); + req_success->set_allocated_request_put(put_request.release()); + + get_request.reset(new RangeRequest()); + get_request->set_key(key); + req_success = txn_request.add_success(); + req_success->set_allocated_request_range(get_request.release()); + + std::shared_ptr call(new etcdv3::AsyncTxnResponse("set")); + + call->response_reader = stub_->AsyncTxn(&call->context,txn_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call.get()); + + return Response::create(call); +} + +pplx::task etcd::Client::send_asyncdelete(std::string const & key, bool recursive) +{ + + //check if key is present + TxnRequest txn_request; + Compare* compare = txn_request.add_compare(); + compare->set_result(Compare::CompareResult::Compare_CompareResult_GREATER); + compare->set_target(Compare::CompareTarget::Compare_CompareTarget_VERSION); + compare->set_key(key); + compare->set_version(0); + + std::string range_end(key); + if(recursive) + { + int ascii = (int)range_end[range_end.length()-1]; + range_end.back() = ascii+1; + } + + //if success, get key, delete + std::unique_ptr get_request(new RangeRequest()); + get_request->set_key(key); + if(recursive) + { + get_request->set_range_end(range_end); + get_request->set_sort_target(RangeRequest::SortTarget::RangeRequest_SortTarget_KEY); + get_request->set_sort_order(RangeRequest::SortOrder::RangeRequest_SortOrder_ASCEND); + } + + RequestOp* req_success = txn_request.add_success(); + req_success->set_allocated_request_range(get_request.release()); + + std::unique_ptr del_request(new DeleteRangeRequest()); + del_request->set_key(key); + if(recursive) + { + del_request->set_range_end(range_end); + } + + req_success = txn_request.add_success(); + req_success->set_allocated_request_delete_range(del_request.release()); + + + //if success, get key, delete + get_request.reset(new RangeRequest()); + get_request->set_key(key); + if(recursive) + { + get_request->set_range_end(range_end); + get_request->set_sort_target(RangeRequest::SortTarget::RangeRequest_SortTarget_KEY); + get_request->set_sort_order(RangeRequest::SortOrder::RangeRequest_SortOrder_ASCEND); + } + RequestOp* req_failure = txn_request.add_failure(); + req_failure->set_allocated_request_range(get_request.release()); + + del_request.reset(new DeleteRangeRequest()); + del_request->set_key(key); + if(recursive) + { + del_request->set_range_end(range_end); + } + + req_failure = txn_request.add_failure(); + req_failure->set_allocated_request_delete_range(del_request.release()); + + + std::shared_ptr call(new etcdv3::AsyncTxnResponse("delete")); + + call->response_reader = stub_->AsyncTxn(&call->context,txn_request,&call->cq_); + +<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77 +pplx::task etcd::Client::send_asyncwatch(std::string const & key, int fromIndex, bool recursive) +{ + std::shared_ptr call(new etcdv3::AsyncWatchResponse()); + call->stream = watchServiceStub->AsyncWatch(&call->context,&call->cq_,(void*)call.get()); + + WatchRequest watch_req; + WatchCreateRequest watch_create_req; + watch_create_req.set_key(key); + watch_create_req.set_start_revision(fromIndex); + + std::string range_end(key); + if(recursive) + { + int ascii = (int)range_end[range_end.length()-1]; + range_end.back() = ascii+1; + watch_create_req.set_range_end(range_end); + } +======= + call->response_reader->Finish(&call->reply, &call->status, (void*)call.get()); + + return Response::create(call); +} +>>>>>>> make templated create with shared_ptr arguement + + + watch_req.mutable_create_request()->CopyFrom(watch_create_req); + call->stream->Write(watch_req, (void*)call.get()); + call->stub_ = stub_.get(); + call->fromIndex = fromIndex; + + return Response::create(call); +} diff --git a/src/Client_BACKUP_12044.cpp b/src/Client_BACKUP_12044.cpp new file mode 100644 index 0000000..b166897 --- /dev/null +++ b/src/Client_BACKUP_12044.cpp @@ -0,0 +1,417 @@ +#include "etcd/Client.hpp" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/AsyncPutResponse.hpp" +<<<<<<< a1293c770afcde1996cd1d899b74fc622628c06c +#include "v3/include/AsyncDelResponse.hpp" +#include "v3/include/AsyncModifyResponse.hpp" +#include "v3/include/Utils.hpp" + +#include +======= +#include "v3/include/AsyncTxnResponse.hpp" +#include "v3/include/Utils.hpp" + +#include + + +using etcdserverpb::TxnRequest; +using etcdserverpb::Compare; +using etcdserverpb::RequestOp; +>>>>>>> Use Txn for add() + +etcd::Client::Client(std::string const & address) + : client(address), grpcClient(address) +{ +} + +pplx::task etcd::Client::send_get_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::GET, uri.to_string())); +} + +pplx::task etcd::Client::send_del_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::DEL, uri.to_string())); +} + +pplx::task etcd::Client::send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value) +{ + std::string data = key + "=" + value; + std::string content_type = "application/x-www-form-urlencoded; param=" + key; + return Response::create(client.request(web::http::methods::PUT, uri.to_string(), data.c_str(), content_type.c_str())); +} + +pplx::task etcd::Client::get(std::string const & key) +{ + return send_asyncget(key); +} + +pplx::task etcd::Client::set(std::string const & key, std::string const & value) +{ + return send_asyncput(key,value); +} + +pplx::task etcd::Client::add(std::string const & key, std::string const & value) +{ + return send_asyncadd(key,value); +} + +pplx::task etcd::Client::modify(std::string const & key, std::string const & value) +{ + return send_asyncmodify(key,value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + return send_asyncmodify_if(key, value, old_value); +} + +pplx::task etcd::Client::modifyEntryWithValueAndOldIndex(std::string const & key, std::string const & value, int old_index) { + + + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else if(resp->reply.kvs(0).mod_revision() != old_index) + { + resp->error_code = 101; + resp->error_message = "Compare failed"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, int old_index) +{ + return modifyEntryWithValueAndOldIndex(key, value, old_index); +} + +//note: this one seems to not need the parseResponse() method +pplx::task etcd::Client::removeEntryWithKey(std::string const & entryKey) { + + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!resp->reply.kvs_size()) + { + std::cout << "nothing to delete" << std::endl; + resp->error_code = 100; + resp->error_message = "Nothing to delete"; + return Response::createResponse(*resp); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse* call = new etcdv3::AsyncDelResponse("delete"); + + //mano-mano + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = entryKey; + + call->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&call->context, deleteRangeRequest, &call->cq_); + call->rpcInstance->Finish(&call->deleteResponse, &call->status, (void*)call); + + return Response::createResponse(*call); +} + +pplx::task etcd::Client::rm(std::string const & key) +{ + return removeEntryWithKey(key); +} + +pplx::task etcd::Client::removeEntryWithKeyAndValue(std::string const &entryKey, std::string const &oldValue) { + + etcdv3::AsyncRangeResponse *searchResult = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!searchResult->reply.kvs_size()) { + searchResult->error_code = 100; + searchResult->error_message = "Key not Found"; + return Response::createResponse(*searchResult); + } + else if(searchResult->reply.kvs(0).value() != oldValue) { + searchResult->error_code = 101; + searchResult->error_message = "Compare failed"; + return Response::createResponse(*searchResult); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse *deleteResponseCall = new etcdv3::AsyncDelResponse("compareAndDelete"); + + deleteResponseCall->prev_value = searchResult->reply.kvs(0); + deleteResponseCall->client = &grpcClient; + deleteResponseCall->key = entryKey; + + deleteResponseCall->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&deleteResponseCall->context, deleteRangeRequest, &deleteResponseCall->cq_); + deleteResponseCall->rpcInstance->Finish(&deleteResponseCall->deleteResponse, &deleteResponseCall->status, (void*)deleteResponseCall); + + return Response::createResponse(*deleteResponseCall); +} + +pplx::task etcd::Client::rm_if(std::string const & key, std::string const & old_value) +{ + return removeEntryWithKeyAndValue(key, old_value); +} + +pplx::task etcd::Client::removeEntryWithKeyAndIndex(std::string const &entryKey, int oldIndex) { + + etcdv3::AsyncRangeResponse *searchResult = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!searchResult->reply.kvs_size()) { + searchResult->error_code = 100; + searchResult->error_message = "Key not Found"; + return Response::createResponse(*searchResult); + } + else if(searchResult->reply.kvs(0).create_revision() != oldIndex) { + searchResult->error_code = 101; + searchResult->error_message = "Compare failed"; + return Response::createResponse(*searchResult); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse *deleteResponseCall = new etcdv3::AsyncDelResponse("compareAndDelete"); + + deleteResponseCall->prev_value = searchResult->reply.kvs(0); + deleteResponseCall->client = &grpcClient; + deleteResponseCall->key = entryKey; + + deleteResponseCall->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&deleteResponseCall->context, deleteRangeRequest, &deleteResponseCall->cq_); + deleteResponseCall->rpcInstance->Finish(&deleteResponseCall->deleteResponse, &deleteResponseCall->status, (void*)deleteResponseCall); + + return Response::createResponse(*deleteResponseCall); +} + +pplx::task etcd::Client::rm_if(std::string const & key, int old_index) +{ +<<<<<<< a1293c770afcde1996cd1d899b74fc622628c06c + return removeEntryWithKeyAndIndex(key, old_index); +======= + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevIndex", old_index); + return send_del_request(uri); + +>>>>>>> Use Txn for add() +} + +pplx::task etcd::Client::mkdir(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + return send_put_request(uri, "dir", "true"); +} + +pplx::task etcd::Client::rmdir(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_del_request(uri); +} + +pplx::task etcd::Client::ls(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("sorted=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, int fromIndex, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + uri.append_query("waitIndex", fromIndex); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::send_asyncadd(std::string const & key, std::string const & value) +{ + + //check if key is not present + TxnRequest txn_request; + Compare* compare = txn_request.add_compare(); + compare->set_result(Compare::CompareResult::Compare_CompareResult_EQUAL); + compare->set_target(Compare::CompareTarget::Compare_CompareTarget_VERSION); + compare->set_key(key); + compare->set_version(0); + + + //get key whether success or failure + RangeRequest get_request1 = new RangeRequest(); + get_request1->set_key(key); + RequestOp* req_failure = txn_request.add_failure(); + req_failure->set_allocated_request_range(get_request1); + + + //if success, add key and then get new value of key + PutRequest* put_request = new PutRequest(); + put_request->set_key(key); + put_request->set_value(value); + RequestOp* req_success2 = txn_request.add_success(); + req_success2->set_allocated_request_put(put_request); + + RangeRequest* get_request2 = new RangeRequest(); + get_request2->set_key(key); + RequestOp* req_success3 = txn_request.add_success(); + req_success3->set_allocated_request_range(get_request2); + + + + etcdv3::AsyncTxnResponse* call= new etcdv3::AsyncTxnResponse("create"); + + call->response_reader = grpcClient.stub_->AsyncTxn(&call->context,txn_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + + //check current key is equal to old_value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else + { + if(resp->reply.kvs(0).value() != old_value) + { + resp->error_code=101; + resp->error_message="Compare failed"; + return Response::createResponse(*resp); + } + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("update"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); + +} + + +pplx::task etcd::Client::send_asyncget(std::string const & key) +{ + RangeRequest request; + request.set_key(key); + + etcdv3::AsyncRangeResponse* call= new etcdv3::AsyncRangeResponse(); + + call->response_reader = grpcClient.stub_->AsyncRange(&call->context,request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncput(std::string const & key, std::string const & value) +{ + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("set"); + + //get current value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + call->prev_value = resp->reply.kvs(0); + } + + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + diff --git a/src/Client_BACKUP_9708.cpp b/src/Client_BACKUP_9708.cpp new file mode 100644 index 0000000..b166897 --- /dev/null +++ b/src/Client_BACKUP_9708.cpp @@ -0,0 +1,417 @@ +#include "etcd/Client.hpp" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/AsyncPutResponse.hpp" +<<<<<<< a1293c770afcde1996cd1d899b74fc622628c06c +#include "v3/include/AsyncDelResponse.hpp" +#include "v3/include/AsyncModifyResponse.hpp" +#include "v3/include/Utils.hpp" + +#include +======= +#include "v3/include/AsyncTxnResponse.hpp" +#include "v3/include/Utils.hpp" + +#include + + +using etcdserverpb::TxnRequest; +using etcdserverpb::Compare; +using etcdserverpb::RequestOp; +>>>>>>> Use Txn for add() + +etcd::Client::Client(std::string const & address) + : client(address), grpcClient(address) +{ +} + +pplx::task etcd::Client::send_get_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::GET, uri.to_string())); +} + +pplx::task etcd::Client::send_del_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::DEL, uri.to_string())); +} + +pplx::task etcd::Client::send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value) +{ + std::string data = key + "=" + value; + std::string content_type = "application/x-www-form-urlencoded; param=" + key; + return Response::create(client.request(web::http::methods::PUT, uri.to_string(), data.c_str(), content_type.c_str())); +} + +pplx::task etcd::Client::get(std::string const & key) +{ + return send_asyncget(key); +} + +pplx::task etcd::Client::set(std::string const & key, std::string const & value) +{ + return send_asyncput(key,value); +} + +pplx::task etcd::Client::add(std::string const & key, std::string const & value) +{ + return send_asyncadd(key,value); +} + +pplx::task etcd::Client::modify(std::string const & key, std::string const & value) +{ + return send_asyncmodify(key,value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + return send_asyncmodify_if(key, value, old_value); +} + +pplx::task etcd::Client::modifyEntryWithValueAndOldIndex(std::string const & key, std::string const & value, int old_index) { + + + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else if(resp->reply.kvs(0).mod_revision() != old_index) + { + resp->error_code = 101; + resp->error_message = "Compare failed"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, int old_index) +{ + return modifyEntryWithValueAndOldIndex(key, value, old_index); +} + +//note: this one seems to not need the parseResponse() method +pplx::task etcd::Client::removeEntryWithKey(std::string const & entryKey) { + + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!resp->reply.kvs_size()) + { + std::cout << "nothing to delete" << std::endl; + resp->error_code = 100; + resp->error_message = "Nothing to delete"; + return Response::createResponse(*resp); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse* call = new etcdv3::AsyncDelResponse("delete"); + + //mano-mano + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = entryKey; + + call->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&call->context, deleteRangeRequest, &call->cq_); + call->rpcInstance->Finish(&call->deleteResponse, &call->status, (void*)call); + + return Response::createResponse(*call); +} + +pplx::task etcd::Client::rm(std::string const & key) +{ + return removeEntryWithKey(key); +} + +pplx::task etcd::Client::removeEntryWithKeyAndValue(std::string const &entryKey, std::string const &oldValue) { + + etcdv3::AsyncRangeResponse *searchResult = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!searchResult->reply.kvs_size()) { + searchResult->error_code = 100; + searchResult->error_message = "Key not Found"; + return Response::createResponse(*searchResult); + } + else if(searchResult->reply.kvs(0).value() != oldValue) { + searchResult->error_code = 101; + searchResult->error_message = "Compare failed"; + return Response::createResponse(*searchResult); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse *deleteResponseCall = new etcdv3::AsyncDelResponse("compareAndDelete"); + + deleteResponseCall->prev_value = searchResult->reply.kvs(0); + deleteResponseCall->client = &grpcClient; + deleteResponseCall->key = entryKey; + + deleteResponseCall->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&deleteResponseCall->context, deleteRangeRequest, &deleteResponseCall->cq_); + deleteResponseCall->rpcInstance->Finish(&deleteResponseCall->deleteResponse, &deleteResponseCall->status, (void*)deleteResponseCall); + + return Response::createResponse(*deleteResponseCall); +} + +pplx::task etcd::Client::rm_if(std::string const & key, std::string const & old_value) +{ + return removeEntryWithKeyAndValue(key, old_value); +} + +pplx::task etcd::Client::removeEntryWithKeyAndIndex(std::string const &entryKey, int oldIndex) { + + etcdv3::AsyncRangeResponse *searchResult = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!searchResult->reply.kvs_size()) { + searchResult->error_code = 100; + searchResult->error_message = "Key not Found"; + return Response::createResponse(*searchResult); + } + else if(searchResult->reply.kvs(0).create_revision() != oldIndex) { + searchResult->error_code = 101; + searchResult->error_message = "Compare failed"; + return Response::createResponse(*searchResult); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse *deleteResponseCall = new etcdv3::AsyncDelResponse("compareAndDelete"); + + deleteResponseCall->prev_value = searchResult->reply.kvs(0); + deleteResponseCall->client = &grpcClient; + deleteResponseCall->key = entryKey; + + deleteResponseCall->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&deleteResponseCall->context, deleteRangeRequest, &deleteResponseCall->cq_); + deleteResponseCall->rpcInstance->Finish(&deleteResponseCall->deleteResponse, &deleteResponseCall->status, (void*)deleteResponseCall); + + return Response::createResponse(*deleteResponseCall); +} + +pplx::task etcd::Client::rm_if(std::string const & key, int old_index) +{ +<<<<<<< a1293c770afcde1996cd1d899b74fc622628c06c + return removeEntryWithKeyAndIndex(key, old_index); +======= + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevIndex", old_index); + return send_del_request(uri); + +>>>>>>> Use Txn for add() +} + +pplx::task etcd::Client::mkdir(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + return send_put_request(uri, "dir", "true"); +} + +pplx::task etcd::Client::rmdir(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_del_request(uri); +} + +pplx::task etcd::Client::ls(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("sorted=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, int fromIndex, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + uri.append_query("waitIndex", fromIndex); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::send_asyncadd(std::string const & key, std::string const & value) +{ + + //check if key is not present + TxnRequest txn_request; + Compare* compare = txn_request.add_compare(); + compare->set_result(Compare::CompareResult::Compare_CompareResult_EQUAL); + compare->set_target(Compare::CompareTarget::Compare_CompareTarget_VERSION); + compare->set_key(key); + compare->set_version(0); + + + //get key whether success or failure + RangeRequest get_request1 = new RangeRequest(); + get_request1->set_key(key); + RequestOp* req_failure = txn_request.add_failure(); + req_failure->set_allocated_request_range(get_request1); + + + //if success, add key and then get new value of key + PutRequest* put_request = new PutRequest(); + put_request->set_key(key); + put_request->set_value(value); + RequestOp* req_success2 = txn_request.add_success(); + req_success2->set_allocated_request_put(put_request); + + RangeRequest* get_request2 = new RangeRequest(); + get_request2->set_key(key); + RequestOp* req_success3 = txn_request.add_success(); + req_success3->set_allocated_request_range(get_request2); + + + + etcdv3::AsyncTxnResponse* call= new etcdv3::AsyncTxnResponse("create"); + + call->response_reader = grpcClient.stub_->AsyncTxn(&call->context,txn_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + + //check current key is equal to old_value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else + { + if(resp->reply.kvs(0).value() != old_value) + { + resp->error_code=101; + resp->error_message="Compare failed"; + return Response::createResponse(*resp); + } + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("update"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); + +} + + +pplx::task etcd::Client::send_asyncget(std::string const & key) +{ + RangeRequest request; + request.set_key(key); + + etcdv3::AsyncRangeResponse* call= new etcdv3::AsyncRangeResponse(); + + call->response_reader = grpcClient.stub_->AsyncRange(&call->context,request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncput(std::string const & key, std::string const & value) +{ + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("set"); + + //get current value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + call->prev_value = resp->reply.kvs(0); + } + + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + diff --git a/src/Client_BASE_12044.cpp b/src/Client_BASE_12044.cpp new file mode 100644 index 0000000..77c38c7 --- /dev/null +++ b/src/Client_BASE_12044.cpp @@ -0,0 +1,272 @@ +#include "etcd/Client.hpp" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/AsyncPutResponse.hpp" +#include "v3/include/Utils.hpp" + +etcd::Client::Client(std::string const & address) + : client(address), grpcClient(address) +{ +} + +pplx::task etcd::Client::send_get_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::GET, uri.to_string())); +} + +pplx::task etcd::Client::send_del_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::DEL, uri.to_string())); +} + +pplx::task etcd::Client::send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value) +{ + std::string data = key + "=" + value; + std::string content_type = "application/x-www-form-urlencoded; param=" + key; + return Response::create(client.request(web::http::methods::PUT, uri.to_string(), data.c_str(), content_type.c_str())); +} + +pplx::task etcd::Client::get(std::string const & key) +{ + return send_asyncget(key); +} + +pplx::task etcd::Client::set(std::string const & key, std::string const & value) +{ + return send_asyncput(key,value); +} + +pplx::task etcd::Client::add(std::string const & key, std::string const & value) +{ + return send_asyncadd(key,value); +} + +pplx::task etcd::Client::modify(std::string const & key, std::string const & value) +{ + return send_asyncmodify(key,value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + return send_asyncmodify_if(key, value, old_value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, int old_index) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("prevIndex", old_index); + return send_put_request(uri, "value", value); +} + +pplx::task etcd::Client::rm(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + return Response::create(client.request("DELETE", uri.to_string())); +} + +pplx::task etcd::Client::rm_if(std::string const & key, std::string const & old_value) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevValue", old_value); + return send_del_request(uri); +} + +pplx::task etcd::Client::rm_if(std::string const & key, int old_index) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevIndex", old_index); + return send_del_request(uri); +} + +pplx::task etcd::Client::mkdir(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + return send_put_request(uri, "dir", "true"); +} + +pplx::task etcd::Client::rmdir(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_del_request(uri); +} + +pplx::task etcd::Client::ls(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("sorted=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, int fromIndex, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + uri.append_query("waitIndex", fromIndex); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + + + + + +pplx::task etcd::Client::send_asyncadd(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + resp->error_code=105; + resp->error_message="Key already exists"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("create"); + + //below 2 lines can be removed once we are able to use Txn + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + + //check current key is equal to old_value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else + { + if(resp->reply.kvs(0).value() != old_value) + { + resp->error_code=101; + resp->error_message="Compare failed"; + return Response::createResponse(*resp); + } + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("update"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + + +pplx::task etcd::Client::send_asyncget(std::string const & key) +{ + RangeRequest request; + request.set_key(key); + + etcdv3::AsyncRangeResponse* call= new etcdv3::AsyncRangeResponse(); + + call->response_reader = grpcClient.stub_->AsyncRange(&call->context,request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncput(std::string const & key, std::string const & value) +{ + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("set"); + + //get current value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + call->prev_value = resp->reply.kvs(0); + } + + call->client = &grpcClient; + call->key = key; + + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + diff --git a/src/Client_BASE_9708.cpp b/src/Client_BASE_9708.cpp new file mode 100644 index 0000000..77c38c7 --- /dev/null +++ b/src/Client_BASE_9708.cpp @@ -0,0 +1,272 @@ +#include "etcd/Client.hpp" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/AsyncPutResponse.hpp" +#include "v3/include/Utils.hpp" + +etcd::Client::Client(std::string const & address) + : client(address), grpcClient(address) +{ +} + +pplx::task etcd::Client::send_get_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::GET, uri.to_string())); +} + +pplx::task etcd::Client::send_del_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::DEL, uri.to_string())); +} + +pplx::task etcd::Client::send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value) +{ + std::string data = key + "=" + value; + std::string content_type = "application/x-www-form-urlencoded; param=" + key; + return Response::create(client.request(web::http::methods::PUT, uri.to_string(), data.c_str(), content_type.c_str())); +} + +pplx::task etcd::Client::get(std::string const & key) +{ + return send_asyncget(key); +} + +pplx::task etcd::Client::set(std::string const & key, std::string const & value) +{ + return send_asyncput(key,value); +} + +pplx::task etcd::Client::add(std::string const & key, std::string const & value) +{ + return send_asyncadd(key,value); +} + +pplx::task etcd::Client::modify(std::string const & key, std::string const & value) +{ + return send_asyncmodify(key,value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + return send_asyncmodify_if(key, value, old_value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, int old_index) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("prevIndex", old_index); + return send_put_request(uri, "value", value); +} + +pplx::task etcd::Client::rm(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + return Response::create(client.request("DELETE", uri.to_string())); +} + +pplx::task etcd::Client::rm_if(std::string const & key, std::string const & old_value) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevValue", old_value); + return send_del_request(uri); +} + +pplx::task etcd::Client::rm_if(std::string const & key, int old_index) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevIndex", old_index); + return send_del_request(uri); +} + +pplx::task etcd::Client::mkdir(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + return send_put_request(uri, "dir", "true"); +} + +pplx::task etcd::Client::rmdir(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_del_request(uri); +} + +pplx::task etcd::Client::ls(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("sorted=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, int fromIndex, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + uri.append_query("waitIndex", fromIndex); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + + + + + +pplx::task etcd::Client::send_asyncadd(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + resp->error_code=105; + resp->error_message="Key already exists"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("create"); + + //below 2 lines can be removed once we are able to use Txn + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + + //check current key is equal to old_value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else + { + if(resp->reply.kvs(0).value() != old_value) + { + resp->error_code=101; + resp->error_message="Compare failed"; + return Response::createResponse(*resp); + } + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("update"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + + +pplx::task etcd::Client::send_asyncget(std::string const & key) +{ + RangeRequest request; + request.set_key(key); + + etcdv3::AsyncRangeResponse* call= new etcdv3::AsyncRangeResponse(); + + call->response_reader = grpcClient.stub_->AsyncRange(&call->context,request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncput(std::string const & key, std::string const & value) +{ + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("set"); + + //get current value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + call->prev_value = resp->reply.kvs(0); + } + + call->client = &grpcClient; + call->key = key; + + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + diff --git a/src/Client_LOCAL_12044.cpp b/src/Client_LOCAL_12044.cpp new file mode 100644 index 0000000..7823115 --- /dev/null +++ b/src/Client_LOCAL_12044.cpp @@ -0,0 +1,384 @@ +#include "etcd/Client.hpp" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/AsyncPutResponse.hpp" +#include "v3/include/AsyncDelResponse.hpp" +#include "v3/include/AsyncModifyResponse.hpp" +#include "v3/include/Utils.hpp" + +#include + +etcd::Client::Client(std::string const & address) + : client(address), grpcClient(address) +{ +} + +pplx::task etcd::Client::send_get_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::GET, uri.to_string())); +} + +pplx::task etcd::Client::send_del_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::DEL, uri.to_string())); +} + +pplx::task etcd::Client::send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value) +{ + std::string data = key + "=" + value; + std::string content_type = "application/x-www-form-urlencoded; param=" + key; + return Response::create(client.request(web::http::methods::PUT, uri.to_string(), data.c_str(), content_type.c_str())); +} + +pplx::task etcd::Client::get(std::string const & key) +{ + return send_asyncget(key); +} + +pplx::task etcd::Client::set(std::string const & key, std::string const & value) +{ + return send_asyncput(key,value); +} + +pplx::task etcd::Client::add(std::string const & key, std::string const & value) +{ + return send_asyncadd(key,value); +} + +pplx::task etcd::Client::modify(std::string const & key, std::string const & value) +{ + return send_asyncmodify(key,value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + return send_asyncmodify_if(key, value, old_value); +} + +pplx::task etcd::Client::modifyEntryWithValueAndOldIndex(std::string const & key, std::string const & value, int old_index) { + + + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else if(resp->reply.kvs(0).mod_revision() != old_index) + { + resp->error_code = 101; + resp->error_message = "Compare failed"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, int old_index) +{ + return modifyEntryWithValueAndOldIndex(key, value, old_index); +} + +//note: this one seems to not need the parseResponse() method +pplx::task etcd::Client::removeEntryWithKey(std::string const & entryKey) { + + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!resp->reply.kvs_size()) + { + std::cout << "nothing to delete" << std::endl; + resp->error_code = 100; + resp->error_message = "Nothing to delete"; + return Response::createResponse(*resp); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse* call = new etcdv3::AsyncDelResponse("delete"); + + //mano-mano + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = entryKey; + + call->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&call->context, deleteRangeRequest, &call->cq_); + call->rpcInstance->Finish(&call->deleteResponse, &call->status, (void*)call); + + return Response::createResponse(*call); +} + +pplx::task etcd::Client::rm(std::string const & key) +{ + return removeEntryWithKey(key); +} + +pplx::task etcd::Client::removeEntryWithKeyAndValue(std::string const &entryKey, std::string const &oldValue) { + + etcdv3::AsyncRangeResponse *searchResult = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!searchResult->reply.kvs_size()) { + searchResult->error_code = 100; + searchResult->error_message = "Key not Found"; + return Response::createResponse(*searchResult); + } + else if(searchResult->reply.kvs(0).value() != oldValue) { + searchResult->error_code = 101; + searchResult->error_message = "Compare failed"; + return Response::createResponse(*searchResult); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse *deleteResponseCall = new etcdv3::AsyncDelResponse("compareAndDelete"); + + deleteResponseCall->prev_value = searchResult->reply.kvs(0); + deleteResponseCall->client = &grpcClient; + deleteResponseCall->key = entryKey; + + deleteResponseCall->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&deleteResponseCall->context, deleteRangeRequest, &deleteResponseCall->cq_); + deleteResponseCall->rpcInstance->Finish(&deleteResponseCall->deleteResponse, &deleteResponseCall->status, (void*)deleteResponseCall); + + return Response::createResponse(*deleteResponseCall); +} + +pplx::task etcd::Client::rm_if(std::string const & key, std::string const & old_value) +{ + return removeEntryWithKeyAndValue(key, old_value); +} + +pplx::task etcd::Client::removeEntryWithKeyAndIndex(std::string const &entryKey, int oldIndex) { + + etcdv3::AsyncRangeResponse *searchResult = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!searchResult->reply.kvs_size()) { + searchResult->error_code = 100; + searchResult->error_message = "Key not Found"; + return Response::createResponse(*searchResult); + } + else if(searchResult->reply.kvs(0).create_revision() != oldIndex) { + searchResult->error_code = 101; + searchResult->error_message = "Compare failed"; + return Response::createResponse(*searchResult); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse *deleteResponseCall = new etcdv3::AsyncDelResponse("compareAndDelete"); + + deleteResponseCall->prev_value = searchResult->reply.kvs(0); + deleteResponseCall->client = &grpcClient; + deleteResponseCall->key = entryKey; + + deleteResponseCall->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&deleteResponseCall->context, deleteRangeRequest, &deleteResponseCall->cq_); + deleteResponseCall->rpcInstance->Finish(&deleteResponseCall->deleteResponse, &deleteResponseCall->status, (void*)deleteResponseCall); + + return Response::createResponse(*deleteResponseCall); +} + +pplx::task etcd::Client::rm_if(std::string const & key, int old_index) +{ + return removeEntryWithKeyAndIndex(key, old_index); +} + +pplx::task etcd::Client::mkdir(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + return send_put_request(uri, "dir", "true"); +} + +pplx::task etcd::Client::rmdir(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_del_request(uri); +} + +pplx::task etcd::Client::ls(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("sorted=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, int fromIndex, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + uri.append_query("waitIndex", fromIndex); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::send_asyncadd(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + resp->error_code=105; + resp->error_message="Key already exists"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("create"); + + //below 2 lines can be removed once we are able to use Txn + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + + //check current key is equal to old_value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else + { + if(resp->reply.kvs(0).value() != old_value) + { + resp->error_code=101; + resp->error_message="Compare failed"; + return Response::createResponse(*resp); + } + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("update"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); + +} + + +pplx::task etcd::Client::send_asyncget(std::string const & key) +{ + RangeRequest request; + request.set_key(key); + + etcdv3::AsyncRangeResponse* call= new etcdv3::AsyncRangeResponse(); + + call->response_reader = grpcClient.stub_->AsyncRange(&call->context,request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncput(std::string const & key, std::string const & value) +{ + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("set"); + + //get current value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + call->prev_value = resp->reply.kvs(0); + } + + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + diff --git a/src/Client_LOCAL_9708.cpp b/src/Client_LOCAL_9708.cpp new file mode 100644 index 0000000..7823115 --- /dev/null +++ b/src/Client_LOCAL_9708.cpp @@ -0,0 +1,384 @@ +#include "etcd/Client.hpp" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/AsyncPutResponse.hpp" +#include "v3/include/AsyncDelResponse.hpp" +#include "v3/include/AsyncModifyResponse.hpp" +#include "v3/include/Utils.hpp" + +#include + +etcd::Client::Client(std::string const & address) + : client(address), grpcClient(address) +{ +} + +pplx::task etcd::Client::send_get_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::GET, uri.to_string())); +} + +pplx::task etcd::Client::send_del_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::DEL, uri.to_string())); +} + +pplx::task etcd::Client::send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value) +{ + std::string data = key + "=" + value; + std::string content_type = "application/x-www-form-urlencoded; param=" + key; + return Response::create(client.request(web::http::methods::PUT, uri.to_string(), data.c_str(), content_type.c_str())); +} + +pplx::task etcd::Client::get(std::string const & key) +{ + return send_asyncget(key); +} + +pplx::task etcd::Client::set(std::string const & key, std::string const & value) +{ + return send_asyncput(key,value); +} + +pplx::task etcd::Client::add(std::string const & key, std::string const & value) +{ + return send_asyncadd(key,value); +} + +pplx::task etcd::Client::modify(std::string const & key, std::string const & value) +{ + return send_asyncmodify(key,value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + return send_asyncmodify_if(key, value, old_value); +} + +pplx::task etcd::Client::modifyEntryWithValueAndOldIndex(std::string const & key, std::string const & value, int old_index) { + + + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else if(resp->reply.kvs(0).mod_revision() != old_index) + { + resp->error_code = 101; + resp->error_message = "Compare failed"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, int old_index) +{ + return modifyEntryWithValueAndOldIndex(key, value, old_index); +} + +//note: this one seems to not need the parseResponse() method +pplx::task etcd::Client::removeEntryWithKey(std::string const & entryKey) { + + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!resp->reply.kvs_size()) + { + std::cout << "nothing to delete" << std::endl; + resp->error_code = 100; + resp->error_message = "Nothing to delete"; + return Response::createResponse(*resp); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse* call = new etcdv3::AsyncDelResponse("delete"); + + //mano-mano + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = entryKey; + + call->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&call->context, deleteRangeRequest, &call->cq_); + call->rpcInstance->Finish(&call->deleteResponse, &call->status, (void*)call); + + return Response::createResponse(*call); +} + +pplx::task etcd::Client::rm(std::string const & key) +{ + return removeEntryWithKey(key); +} + +pplx::task etcd::Client::removeEntryWithKeyAndValue(std::string const &entryKey, std::string const &oldValue) { + + etcdv3::AsyncRangeResponse *searchResult = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!searchResult->reply.kvs_size()) { + searchResult->error_code = 100; + searchResult->error_message = "Key not Found"; + return Response::createResponse(*searchResult); + } + else if(searchResult->reply.kvs(0).value() != oldValue) { + searchResult->error_code = 101; + searchResult->error_message = "Compare failed"; + return Response::createResponse(*searchResult); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse *deleteResponseCall = new etcdv3::AsyncDelResponse("compareAndDelete"); + + deleteResponseCall->prev_value = searchResult->reply.kvs(0); + deleteResponseCall->client = &grpcClient; + deleteResponseCall->key = entryKey; + + deleteResponseCall->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&deleteResponseCall->context, deleteRangeRequest, &deleteResponseCall->cq_); + deleteResponseCall->rpcInstance->Finish(&deleteResponseCall->deleteResponse, &deleteResponseCall->status, (void*)deleteResponseCall); + + return Response::createResponse(*deleteResponseCall); +} + +pplx::task etcd::Client::rm_if(std::string const & key, std::string const & old_value) +{ + return removeEntryWithKeyAndValue(key, old_value); +} + +pplx::task etcd::Client::removeEntryWithKeyAndIndex(std::string const &entryKey, int oldIndex) { + + etcdv3::AsyncRangeResponse *searchResult = etcdv3::Utils::getKey(entryKey, grpcClient); + + if(!searchResult->reply.kvs_size()) { + searchResult->error_code = 100; + searchResult->error_message = "Key not Found"; + return Response::createResponse(*searchResult); + } + else if(searchResult->reply.kvs(0).create_revision() != oldIndex) { + searchResult->error_code = 101; + searchResult->error_message = "Compare failed"; + return Response::createResponse(*searchResult); + } + + etcdserverpb::DeleteRangeRequest deleteRangeRequest; + deleteRangeRequest.set_key(entryKey); + + etcdv3::AsyncDelResponse *deleteResponseCall = new etcdv3::AsyncDelResponse("compareAndDelete"); + + deleteResponseCall->prev_value = searchResult->reply.kvs(0); + deleteResponseCall->client = &grpcClient; + deleteResponseCall->key = entryKey; + + deleteResponseCall->rpcInstance = grpcClient.stub_->AsyncDeleteRange(&deleteResponseCall->context, deleteRangeRequest, &deleteResponseCall->cq_); + deleteResponseCall->rpcInstance->Finish(&deleteResponseCall->deleteResponse, &deleteResponseCall->status, (void*)deleteResponseCall); + + return Response::createResponse(*deleteResponseCall); +} + +pplx::task etcd::Client::rm_if(std::string const & key, int old_index) +{ + return removeEntryWithKeyAndIndex(key, old_index); +} + +pplx::task etcd::Client::mkdir(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + return send_put_request(uri, "dir", "true"); +} + +pplx::task etcd::Client::rmdir(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_del_request(uri); +} + +pplx::task etcd::Client::ls(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("sorted=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, int fromIndex, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + uri.append_query("waitIndex", fromIndex); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::send_asyncadd(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + resp->error_code=105; + resp->error_message="Key already exists"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("create"); + + //below 2 lines can be removed once we are able to use Txn + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + + //check current key is equal to old_value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else + { + if(resp->reply.kvs(0).value() != old_value) + { + resp->error_code=101; + resp->error_message="Compare failed"; + return Response::createResponse(*resp); + } + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncModifyResponse* call= new etcdv3::AsyncModifyResponse("update"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->rpcInstance = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->rpcInstance->Finish(&call->putResponse, &call->status, (void*)call); + + return Response::create(call); + +} + + +pplx::task etcd::Client::send_asyncget(std::string const & key) +{ + RangeRequest request; + request.set_key(key); + + etcdv3::AsyncRangeResponse* call= new etcdv3::AsyncRangeResponse(); + + call->response_reader = grpcClient.stub_->AsyncRange(&call->context,request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncput(std::string const & key, std::string const & value) +{ + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("set"); + + //get current value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + call->prev_value = resp->reply.kvs(0); + } + + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + diff --git a/src/Client_REMOTE_12044.cpp b/src/Client_REMOTE_12044.cpp new file mode 100644 index 0000000..879bfbf --- /dev/null +++ b/src/Client_REMOTE_12044.cpp @@ -0,0 +1,294 @@ +#include "etcd/Client.hpp" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/AsyncPutResponse.hpp" +#include "v3/include/AsyncTxnResponse.hpp" +#include "v3/include/Utils.hpp" + +#include + + +using etcdserverpb::TxnRequest; +using etcdserverpb::Compare; +using etcdserverpb::RequestOp; + +etcd::Client::Client(std::string const & address) + : client(address), grpcClient(address) +{ +} + +pplx::task etcd::Client::send_get_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::GET, uri.to_string())); +} + +pplx::task etcd::Client::send_del_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::DEL, uri.to_string())); +} + +pplx::task etcd::Client::send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value) +{ + std::string data = key + "=" + value; + std::string content_type = "application/x-www-form-urlencoded; param=" + key; + return Response::create(client.request(web::http::methods::PUT, uri.to_string(), data.c_str(), content_type.c_str())); +} + +pplx::task etcd::Client::get(std::string const & key) +{ + return send_asyncget(key); +} + +pplx::task etcd::Client::set(std::string const & key, std::string const & value) +{ + return send_asyncput(key,value); +} + +pplx::task etcd::Client::add(std::string const & key, std::string const & value) +{ + return send_asyncadd(key,value); +} + +pplx::task etcd::Client::modify(std::string const & key, std::string const & value) +{ + return send_asyncmodify(key,value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + return send_asyncmodify_if(key, value, old_value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, int old_index) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("prevIndex", old_index); + return send_put_request(uri, "value", value); +} + +pplx::task etcd::Client::rm(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + return Response::create(client.request("DELETE", uri.to_string())); +} + +pplx::task etcd::Client::rm_if(std::string const & key, std::string const & old_value) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevValue", old_value); + return send_del_request(uri); +} + +pplx::task etcd::Client::rm_if(std::string const & key, int old_index) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevIndex", old_index); + return send_del_request(uri); + +} + +pplx::task etcd::Client::mkdir(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + return send_put_request(uri, "dir", "true"); +} + +pplx::task etcd::Client::rmdir(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_del_request(uri); +} + +pplx::task etcd::Client::ls(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("sorted=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, int fromIndex, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + uri.append_query("waitIndex", fromIndex); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + + + + + +pplx::task etcd::Client::send_asyncadd(std::string const & key, std::string const & value) +{ + + //check if key is not present + TxnRequest txn_request; + Compare* compare = txn_request.add_compare(); + compare->set_result(Compare::CompareResult::Compare_CompareResult_EQUAL); + compare->set_target(Compare::CompareTarget::Compare_CompareTarget_VERSION); + compare->set_key(key); + compare->set_version(0); + + + //get key whether success or failure + RangeRequest get_request1 = new RangeRequest(); + get_request1->set_key(key); + RequestOp* req_failure = txn_request.add_failure(); + req_failure->set_allocated_request_range(get_request1); + + + //if success, add key and then get new value of key + PutRequest* put_request = new PutRequest(); + put_request->set_key(key); + put_request->set_value(value); + RequestOp* req_success2 = txn_request.add_success(); + req_success2->set_allocated_request_put(put_request); + + RangeRequest* get_request2 = new RangeRequest(); + get_request2->set_key(key); + RequestOp* req_success3 = txn_request.add_success(); + req_success3->set_allocated_request_range(get_request2); + + + + etcdv3::AsyncTxnResponse* call= new etcdv3::AsyncTxnResponse("create"); + + call->response_reader = grpcClient.stub_->AsyncTxn(&call->context,txn_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + + //check current key is equal to old_value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else + { + if(resp->reply.kvs(0).value() != old_value) + { + resp->error_code=101; + resp->error_message="Compare failed"; + return Response::createResponse(*resp); + } + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("update"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + + +pplx::task etcd::Client::send_asyncget(std::string const & key) +{ + RangeRequest request; + request.set_key(key); + + etcdv3::AsyncRangeResponse* call= new etcdv3::AsyncRangeResponse(); + + call->response_reader = grpcClient.stub_->AsyncRange(&call->context,request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncput(std::string const & key, std::string const & value) +{ + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("set"); + + //get current value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + call->prev_value = resp->reply.kvs(0); + } + + call->client = &grpcClient; + call->key = key; + + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + diff --git a/src/Client_REMOTE_9708.cpp b/src/Client_REMOTE_9708.cpp new file mode 100644 index 0000000..879bfbf --- /dev/null +++ b/src/Client_REMOTE_9708.cpp @@ -0,0 +1,294 @@ +#include "etcd/Client.hpp" +#include "v3/include/AsyncRangeResponse.hpp" +#include "v3/include/AsyncPutResponse.hpp" +#include "v3/include/AsyncTxnResponse.hpp" +#include "v3/include/Utils.hpp" + +#include + + +using etcdserverpb::TxnRequest; +using etcdserverpb::Compare; +using etcdserverpb::RequestOp; + +etcd::Client::Client(std::string const & address) + : client(address), grpcClient(address) +{ +} + +pplx::task etcd::Client::send_get_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::GET, uri.to_string())); +} + +pplx::task etcd::Client::send_del_request(web::http::uri_builder & uri) +{ + return Response::create(client.request(web::http::methods::DEL, uri.to_string())); +} + +pplx::task etcd::Client::send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value) +{ + std::string data = key + "=" + value; + std::string content_type = "application/x-www-form-urlencoded; param=" + key; + return Response::create(client.request(web::http::methods::PUT, uri.to_string(), data.c_str(), content_type.c_str())); +} + +pplx::task etcd::Client::get(std::string const & key) +{ + return send_asyncget(key); +} + +pplx::task etcd::Client::set(std::string const & key, std::string const & value) +{ + return send_asyncput(key,value); +} + +pplx::task etcd::Client::add(std::string const & key, std::string const & value) +{ + return send_asyncadd(key,value); +} + +pplx::task etcd::Client::modify(std::string const & key, std::string const & value) +{ + return send_asyncmodify(key,value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + return send_asyncmodify_if(key, value, old_value); +} + +pplx::task etcd::Client::modify_if(std::string const & key, std::string const & value, int old_index) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("prevIndex", old_index); + return send_put_request(uri, "value", value); +} + +pplx::task etcd::Client::rm(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + return Response::create(client.request("DELETE", uri.to_string())); +} + +pplx::task etcd::Client::rm_if(std::string const & key, std::string const & old_value) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevValue", old_value); + return send_del_request(uri); +} + +pplx::task etcd::Client::rm_if(std::string const & key, int old_index) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=false"); + uri.append_query("prevIndex", old_index); + return send_del_request(uri); + +} + +pplx::task etcd::Client::mkdir(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + return send_put_request(uri, "dir", "true"); +} + +pplx::task etcd::Client::rmdir(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("dir=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_del_request(uri); +} + +pplx::task etcd::Client::ls(std::string const & key) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("sorted=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + +pplx::task etcd::Client::watch(std::string const & key, int fromIndex, bool recursive) +{ + web::http::uri_builder uri("/v2/keys" + key); + uri.append_query("wait=true"); + uri.append_query("waitIndex", fromIndex); + if (recursive) + uri.append_query("recursive=true"); + return send_get_request(uri); +} + + + + + +pplx::task etcd::Client::send_asyncadd(std::string const & key, std::string const & value) +{ + + //check if key is not present + TxnRequest txn_request; + Compare* compare = txn_request.add_compare(); + compare->set_result(Compare::CompareResult::Compare_CompareResult_EQUAL); + compare->set_target(Compare::CompareTarget::Compare_CompareTarget_VERSION); + compare->set_key(key); + compare->set_version(0); + + + //get key whether success or failure + RangeRequest get_request1 = new RangeRequest(); + get_request1->set_key(key); + RequestOp* req_failure = txn_request.add_failure(); + req_failure->set_allocated_request_range(get_request1); + + + //if success, add key and then get new value of key + PutRequest* put_request = new PutRequest(); + put_request->set_key(key); + put_request->set_value(value); + RequestOp* req_success2 = txn_request.add_success(); + req_success2->set_allocated_request_put(put_request); + + RangeRequest* get_request2 = new RangeRequest(); + get_request2->set_key(key); + RequestOp* req_success3 = txn_request.add_success(); + req_success3->set_allocated_request_range(get_request2); + + + + etcdv3::AsyncTxnResponse* call= new etcdv3::AsyncTxnResponse("create"); + + call->response_reader = grpcClient.stub_->AsyncTxn(&call->context,txn_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value) +{ + + //check current key is equal to old_value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + else + { + if(resp->reply.kvs(0).value() != old_value) + { + resp->error_code=101; + resp->error_message="Compare failed"; + return Response::createResponse(*resp); + } + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("compareAndSwap"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + +pplx::task etcd::Client::send_asyncmodify(std::string const & key, std::string const & value) +{ + + //check if key already exist + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(!resp->reply.kvs_size()) + { + resp->error_code=100; + resp->error_message="Key not found"; + return Response::createResponse(*resp); + } + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("update"); + + //below 2 lines can be removed once we are able to use Txn + call->prev_value = resp->reply.kvs(0); + call->client = &grpcClient; + call->key = key; + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); + +} + + +pplx::task etcd::Client::send_asyncget(std::string const & key) +{ + RangeRequest request; + request.set_key(key); + + etcdv3::AsyncRangeResponse* call= new etcdv3::AsyncRangeResponse(); + + call->response_reader = grpcClient.stub_->AsyncRange(&call->context,request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + +pplx::task etcd::Client::send_asyncput(std::string const & key, std::string const & value) +{ + + PutRequest put_request; + put_request.set_key(key); + put_request.set_value(value); + + etcdv3::AsyncPutResponse* call= new etcdv3::AsyncPutResponse("set"); + + //get current value + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, grpcClient); + if(resp->reply.kvs_size()) + { + call->prev_value = resp->reply.kvs(0); + } + + call->client = &grpcClient; + call->key = key; + + + call->response_reader = grpcClient.stub_->AsyncPut(&call->context,put_request,&call->cq_); + + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + + return Response::create(call); +} + + diff --git a/src/Response.cpp.orig b/src/Response.cpp.orig new file mode 100644 index 0000000..7bf655e --- /dev/null +++ b/src/Response.cpp.orig @@ -0,0 +1,143 @@ +#include "etcd/Response.hpp" +#include "json_constants.hpp" + +#include + +pplx::task etcd::Response::create(pplx::task response_task) +{ + return pplx::task ( + [response_task]() + { + auto json_task = response_task.get().extract_json(); + return etcd::Response(response_task.get(), json_task.get()); + } + ); +} + + +etcd::Response::Response(const etcdv3::V3Response& reply) +{ + _index = reply.index; + _error_code = reply.error_code; + _error_message = reply.error_message; + _action = reply.action; + int size = reply.values.size(); + if(size > 1) + { + for(int index = 0; index < size; index++) + { + _values.push_back(Value(reply.values[index])); + _keys.push_back(reply.values[index].key()); + } + } + else if(size == 1) + { + _value = Value(reply.values[0]); + } + + if(reply.prev_values.size() == 1) +<<<<<<< 4adff1a7552b34d6c98def525fa38351e37bf47d + { + _prev_value = Value(reply.prev_values[0]); + } +======= + _prev_value = Value(reply.prev_values[0]); +>>>>>>> made prev_values a vector. +} + + +etcd::Response::Response() + : _error_code(0), + _index(0) +{ +} + +etcd::Response::Response(web::http::http_response http_response, web::json::value json_value) + : _error_code(0), + _index(0) +{ + if (http_response.headers().has(JSON_ETCD_INDEX)) + _index = atoi(http_response.headers()[JSON_ETCD_INDEX].c_str()); + + if (json_value.has_field(JSON_ERROR_CODE)) + { + _error_code = json_value[JSON_ERROR_CODE].as_number().to_int64(); + _error_message = json_value[JSON_MESSAGE].as_string(); + } + + if (json_value.has_field(JSON_ACTION)) + _action = json_value[JSON_ACTION].as_string(); + + if (json_value.has_field(JSON_NODE)) + { + if (json_value[JSON_NODE].has_field(JSON_NODES)) + { + std::string prefix = json_value[JSON_NODE][JSON_KEY].as_string(); + for (auto & node : json_value[JSON_NODE][JSON_NODES].as_array()) + { + _values.push_back(Value(node)); + _keys.push_back(node[JSON_KEY].as_string().substr(prefix.length() + 1)); + } + } + else + _value = Value(json_value.at(JSON_NODE)); + } + + if (json_value.has_field(JSON_PREV_NODE)) + _prev_value = Value(json_value.at(JSON_PREV_NODE)); +} + +int etcd::Response::error_code() const +{ + return _error_code; +} + +std::string const & etcd::Response::error_message() const +{ + return _error_message; +} + +int etcd::Response::index() const +{ + return _index; +} + +std::string const & etcd::Response::action() const +{ + return _action; +} + +bool etcd::Response::is_ok() const +{ + return error_code() == 0; +} + +etcd::Value const & etcd::Response::value() const +{ + return _value; +} + +etcd::Value const & etcd::Response::prev_value() const +{ + return _prev_value; +} + +etcd::Values const & etcd::Response::values() const +{ + return _values; +} + +etcd::Value const & etcd::Response::value(int index) const +{ + return _values[index]; +} + +etcd::Keys const & etcd::Response::keys() const +{ + return _keys; +} + +std::string const & etcd::Response::key(int index) const +{ + return _keys[index]; +} diff --git a/tst/EtcdTest.cpp.orig b/tst/EtcdTest.cpp.orig new file mode 100644 index 0000000..3b21ed3 --- /dev/null +++ b/tst/EtcdTest.cpp.orig @@ -0,0 +1,304 @@ +#define CATCH_CONFIG_MAIN +#include +#include + +#include "etcd/Client.hpp" + + +TEST_CASE("setup") +{ + etcd::Client etcd("http://127.0.0.1:2379"); +<<<<<<< 12282f826d6973d5bfdb24a44b076a9cdeca21e8 + etcd.rmdir("/test", true).wait(); +======= + //etcd.rmdir("/test", true).wait(); +>>>>>>> Use Txn +} + + +TEST_CASE("add a new key") +{ +<<<<<<< 12282f826d6973d5bfdb24a44b076a9cdeca21e8 + +======= +>>>>>>> Use Txn + etcd::Client etcd("http://127.0.0.1:2379"); + etcd::Response resp = etcd.add("/test/key1", "42").get(); + REQUIRE(0 == resp.error_code()); + CHECK("create" == resp.action()); + etcd::Value const & val = resp.value(); + CHECK("42" == val.as_string()); + CHECK("/test/key1" == val.key()); + CHECK(!val.is_dir()); + CHECK(0 < val.created_index()); + CHECK(0 < val.modified_index()); + CHECK(0 < resp.index()); // X-Etcd-Index header value + CHECK(105 == etcd.add("/test/key1", "43").get().error_code()); // Key already exists + CHECK(105 == etcd.add("/test/key1", "42").get().error_code()); // Key already exists + CHECK("Key already exists" == etcd.add("/test/key1", "42").get().error_message()); +} + + +TEST_CASE("read a value from etcd") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + etcd::Response resp = etcd.get("/test/key1").get(); + CHECK("get" == resp.action()); + REQUIRE(resp.is_ok()); + REQUIRE(0 == resp.error_code()); + CHECK("42" == resp.value().as_string()); + + CHECK("" == etcd.get("/test").get().value().as_string()); // key points to a directory +} + + +TEST_CASE("simplified read") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + CHECK("42" == etcd.get("/test/key1").get().value().as_string()); + CHECK(100 == etcd.get("/test/key2").get().error_code()); // Key not found +} + + + +TEST_CASE("modify a key") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + etcd::Response resp = etcd.modify("/test/key1", "43").get(); + REQUIRE(0 == resp.error_code()); // overwrite + CHECK("update" == resp.action()); + CHECK(100 == etcd.modify("/test/key2", "43").get().error_code()); // Key not found + CHECK("43" == etcd.modify("/test/key1", "42").get().prev_value().as_string()); +} + + +TEST_CASE("set a key") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + etcd::Response resp = etcd.set("/test/key1", "43").get(); + REQUIRE(0 == resp.error_code()); // overwrite + CHECK("set" == resp.action()); + CHECK(0 == etcd.set("/test/key2", "43").get().error_code()); // create new + CHECK("43" == etcd.set("/test/key2", "44").get().prev_value().as_string()); + CHECK("" == etcd.set("/test/key3", "44").get().prev_value().as_string()); + CHECK(0 == etcd.set("/test", "42").get().error_code()); // Not a file +} + +TEST_CASE("atomic compare-and-swap") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + etcd.set("/test/key1", "42").wait(); + + // modify success + etcd::Response res = etcd.modify_if("/test/key1", "43", "42").get(); + int index = res.index(); + REQUIRE(res.is_ok()); + CHECK("compareAndSwap" == res.action()); + CHECK("43" == res.value().as_string()); + + // modify fails the second time + res = etcd.modify_if("/test/key1", "44", "42").get(); + CHECK(!res.is_ok()); + CHECK(101 == res.error_code()); + CHECK("Compare failed" == res.error_message()); +} + +<<<<<<< 12282f826d6973d5bfdb24a44b076a9cdeca21e8 +======= + +#if 0 +>>>>>>> Use Txn + +TEST_CASE("delete a value") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + etcd::Response resp = etcd.rm("/test/key1").get(); + CHECK("43" == resp.prev_value().as_string()); + CHECK("delete" == resp.action()); +} + +TEST_CASE("atomic compare-and-delete based on prevValue") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + etcd.set("/test/key1", "42").wait(); + + etcd::Response res = etcd.rm_if("/test/key1", "43").get(); + CHECK(!res.is_ok()); + CHECK(101 == res.error_code()); + CHECK("Compare failed" == res.error_message()); + + res = etcd.rm_if("/test/key1", "42").get(); + REQUIRE(res.is_ok()); + CHECK("compareAndDelete" == res.action()); + CHECK("42" == res.prev_value().as_string()); +} + +TEST_CASE("atomic compare-and-delete based on prevIndex") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + int index = etcd.set("/test/key1", "42").get().index(); + + etcd::Response res = etcd.rm_if("/test/key1", index - 1).get(); + CHECK(!res.is_ok()); + CHECK(101 == res.error_code()); + CHECK("Compare failed" == res.error_message()); + + res = etcd.rm_if("/test/key1", index).get(); + REQUIRE(res.is_ok()); + CHECK("compareAndDelete" == res.action()); + CHECK("42" == res.prev_value().as_string()); +} + + +TEST_CASE("deep atomic compare-and-swap") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + etcd.set("/test/key1", "42").wait(); + + // modify success + etcd::Response res = etcd.modify_if("/test/key1", "43", "42").get(); + int index = res.index(); + REQUIRE(res.is_ok()); + CHECK("compareAndSwap" == res.action()); + CHECK("43" == res.value().as_string()); + + // modify fails the second time + res = etcd.modify_if("/test/key1", "44", "42").get(); + CHECK(!res.is_ok()); + CHECK(101 == res.error_code()); + CHECK("Compare failed" == res.error_message()); + + + // succes with the correct index + res = etcd.modify_if("/test/key1", "44", index).get(); + REQUIRE(res.is_ok()); + CHECK("compareAndSwap" == res.action()); + CHECK("44" == res.value().as_string()); + + // index changes so second modify fails + res = etcd.modify_if("/test/key1", "45", index).get(); + CHECK(!res.is_ok()); + CHECK(101 == res.error_code()); + CHECK("Compare failed" == res.error_message()); + +} + + +//skip this test case +/* +TEST_CASE("create a directory") +{ + etcd::Client etcd("http://127.0.0.1:4001"); + etcd::Response resp = etcd.mkdir("/test/new_dir").get(); + CHECK("set" == resp.action()); + CHECK(resp.value().is_dir()); +} +*/ + +TEST_CASE("list a directory") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + CHECK(0 == etcd.ls("/test/new_dir").get().keys().size()); + + etcd.set("/test/new_dir/key1", "value1").wait(); + etcd.set("/test/new_dir/key2", "value2").wait(); + etcd.set("/test/new_dir/sub_dir", "value3").wait(); + + etcd::Response resp = etcd.ls("/test/new_dir").get(); + CHECK("get" == resp.action()); + REQUIRE(3 == resp.keys().size()); + CHECK("/test/new_dir/key1" == resp.key(0)); + CHECK("/test/new_dir/key2" == resp.key(1)); + CHECK("/test/new_dir/sub_dir" == resp.key(2)); + CHECK("value1" == resp.value(0).as_string()); + CHECK("value2" == resp.value(1).as_string()); + CHECK(resp.values()[2].is_dir() == 0); + + CHECK(0 == etcd.ls("/test/new_dir/key1").get().error_code()); +} + +TEST_CASE("delete a directory") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + //CHECK(108 == etcd.rmdir("/test/new_dir").get().error_code()); // Directory not empty + CHECK(0 == etcd.rmdir("/test/new_dir", true).get().error_code()); +} + + +TEST_CASE("wait for a value change") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + etcd.set("/test/key1", "42").wait(); + + pplx::task res = etcd.watch("/test/key1"); + CHECK(!res.is_done()); + sleep(1); + CHECK(!res.is_done()); + + etcd.set("/test/key1", "43").get(); + sleep(1); + REQUIRE(res.is_done()); + REQUIRE("set" == res.get().action()); + CHECK("43" == res.get().value().as_string()); +} + +TEST_CASE("wait for a directory change") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + + pplx::task res = etcd.watch("/test", true); + CHECK(!res.is_done()); + sleep(1); + CHECK(!res.is_done()); + + etcd.add("/test/key4", "44").wait(); + sleep(1); + REQUIRE(res.is_done()); + CHECK("create" == res.get().action()); + CHECK("44" == res.get().value().as_string()); + + pplx::task res2 = etcd.watch("/test", true); + CHECK(!res2.is_done()); + sleep(1); + CHECK(!res2.is_done()); + + etcd.set("/test/key4", "45").wait(); + sleep(1); + REQUIRE(res2.is_done()); + CHECK("set" == res2.get().action()); + CHECK("45" == res2.get().value().as_string()); +} + +TEST_CASE("watch changes in the past") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + + int index = etcd.set("/test/key1", "42").get().index(); + + etcd.set("/test/key1", "43").wait(); + etcd.set("/test/key1", "44").wait(); + etcd.set("/test/key1", "45").wait(); + + etcd::Response res = etcd.watch("/test/key1", ++index).get(); + CHECK("set" == res.action()); + CHECK("43" == res.value().as_string()); + + res = etcd.watch("/test/key1", ++index).get(); + CHECK("set" == res.action()); + CHECK("44" == res.value().as_string()); + + res = etcd.watch("/test", ++index, true).get(); + CHECK("set" == res.action()); + CHECK("45" == res.value().as_string()); +} + + +TEST_CASE("cleanup") +{ + etcd::Client etcd("http://127.0.0.1:2379"); + REQUIRE(0 == etcd.rmdir("/test", true).get().error_code()); +} + + + + diff --git a/v3/include/AsyncRangeResponse.hpp.orig b/v3/include/AsyncRangeResponse.hpp.orig new file mode 100644 index 0000000..ada9629 --- /dev/null +++ b/v3/include/AsyncRangeResponse.hpp.orig @@ -0,0 +1,36 @@ +#ifndef __ASYNC_RANGERESPONSE_HPP__ +#define __ASYNC_RANGERESPONSE_HPP__ + +#include +#include "proto/rpc.grpc.pb.h" +#include "v3/include/V3Response.hpp" + +using grpc::ClientAsyncResponseReader; +using grpc::ClientContext; +using grpc::CompletionQueue; +using grpc::Status; +using etcdserverpb::RangeResponse; + +namespace etcdv3 +{ + class AsyncRangeResponse : public etcdv3::V3Response + { + public: + AsyncRangeResponse(){action = "get";}; + AsyncRangeResponse(const AsyncRangeResponse& other); + AsyncRangeResponse& operator=(const AsyncRangeResponse& other); + AsyncRangeResponse& ParseResponse(); + void waitForResponse(); + RangeResponse reply; + Status status; + ClientContext context; + CompletionQueue cq_; + std::unique_ptr> response_reader; +<<<<<<< a592ce75a199b4e275a50c5f29992aa7dc0ff8d1 +======= + AsyncRangeResponse& ParseResponse(); +>>>>>>> Added delete + }; +} + +#endif diff --git a/v3/include/AsyncTxnResponse.hpp.orig b/v3/include/AsyncTxnResponse.hpp.orig new file mode 100644 index 0000000..8add267 --- /dev/null +++ b/v3/include/AsyncTxnResponse.hpp.orig @@ -0,0 +1,46 @@ +#ifndef __ASYNC_TXNRESPONSE_HPP__ +#define __ASYNC_TXNRESPONSE_HPP__ + +#include +#include "proto/rpc.grpc.pb.h" +#include "v3/include/V3Response.hpp" +<<<<<<< 0cb5bd762aca24c5a8d9e959c5f72590d85ad2b4 +======= +#include "v3/include/grpcClient.hpp" + + +>>>>>>> Use Txn for add() + +using grpc::ClientAsyncResponseReader; +using grpc::ClientContext; +using grpc::CompletionQueue; +using grpc::Status; +using etcdserverpb::TxnResponse; + +namespace etcdv3 +{ + class AsyncTxnResponse : public etcdv3::V3Response + { + public: + AsyncTxnResponse(){}; + AsyncTxnResponse(const std::string act){action = act;}; + AsyncTxnResponse(const AsyncTxnResponse& other); + AsyncTxnResponse& operator=(const AsyncTxnResponse& other); +<<<<<<< 0cb5bd762aca24c5a8d9e959c5f72590d85ad2b4 + AsyncTxnResponse& ParseResponse(); + void waitForResponse(); +======= +>>>>>>> Use Txn for add() + TxnResponse reply; + Status status; + ClientContext context; + CompletionQueue cq_; + std::unique_ptr> response_reader; +<<<<<<< 0cb5bd762aca24c5a8d9e959c5f72590d85ad2b4 +======= + AsyncTxnResponse& ParseResponse(); +>>>>>>> Use Txn for add() + }; +} + +#endif diff --git a/v3/src/AsyncPutResponse.cpp.orig b/v3/src/AsyncPutResponse.cpp.orig new file mode 100644 index 0000000..13e7612 --- /dev/null +++ b/v3/src/AsyncPutResponse.cpp.orig @@ -0,0 +1,49 @@ +#include "v3/include/AsyncPutResponse.hpp" +#include "v3/include/Utils.hpp" + +#include + +using etcdserverpb::PutRequest; +using etcdserverpb::PutRequest; + +etcdv3::AsyncPutResponse::AsyncPutResponse(const etcdv3::AsyncPutResponse& other) +{ + error_code = other.error_code; + error_message = other.error_message; + index = other.index; + action = other.action; + values = other.values; + prev_value.set_key(other.prev_value.key()); + prev_value.set_value(other.prev_value.value()); + prev_value.set_create_revision(other.prev_value.create_revision()); + prev_value.set_mod_revision(other.prev_value.mod_revision()); + +} + +etcdv3::AsyncPutResponse& etcdv3::AsyncPutResponse::operator=(const etcdv3::AsyncPutResponse& other) +{ + error_code = other.error_code; + error_message = other.error_message; + index = other.index; + action = other.action; + values = other.values; + prev_value.set_key(other.prev_value.key()); + prev_value.set_value(other.prev_value.value()); + prev_value.set_create_revision(other.prev_value.create_revision()); + prev_value.set_mod_revision(other.prev_value.mod_revision()); + return *this; +} + +etcdv3::AsyncPutResponse& etcdv3::AsyncPutResponse::ParseResponse() +{ + etcdv3::AsyncRangeResponse* resp = etcdv3::Utils::getKey(key, *client); + if(resp->reply.kvs_size()) + { + values.push_back(resp->reply.kvs(0)); + index = resp->reply.kvs(0).create_revision(); + } + else + index = resp->reply.header().revision(); + + return *this; +} diff --git a/v3/src/AsyncRangeResponse.cpp.orig b/v3/src/AsyncRangeResponse.cpp.orig new file mode 100644 index 0000000..20f78e0 --- /dev/null +++ b/v3/src/AsyncRangeResponse.cpp.orig @@ -0,0 +1,75 @@ +#include "v3/include/AsyncRangeResponse.hpp" + +etcdv3::AsyncRangeResponse::AsyncRangeResponse(const etcdv3::AsyncRangeResponse& other) +{ + error_code = other.error_code; + error_message = other.error_message; + index = other.index; + action = other.action; + values = other.values; + prev_values = other.prev_values; + +} + +etcdv3::AsyncRangeResponse& etcdv3::AsyncRangeResponse::operator=(const etcdv3::AsyncRangeResponse& other) +{ + error_code = other.error_code; + error_message = other.error_message; + index = other.index; + action = other.action; + values = other.values; + prev_values = other.prev_values; + return *this; +} + +void etcdv3::AsyncRangeResponse::waitForResponse() +{ + void* got_tag; + bool ok = false; + + cq_.Next(&got_tag, &ok); + GPR_ASSERT(got_tag == (void*)this); +} + +etcdv3::AsyncRangeResponse& etcdv3::AsyncRangeResponse::ParseResponse() +{ + index = reply.header().revision(); + if(!status.ok()) + { + error_code = status.error_code(); + error_message = status.error_message(); + } + else + { +<<<<<<< a592ce75a199b4e275a50c5f29992aa7dc0ff8d1 +======= + + if(reply.kvs_size() == 0) + { + error_code=100; + error_message="Key not found"; + } + + for(int index=0; index < reply.kvs_size(); index++) + { + std::cout << "key: " << reply.kvs(index).key() << std::endl; + std::cout << "value: " << reply.kvs(index).value()<< std::endl; + values.push_back(reply.kvs(index)); + } + } +>>>>>>> Added delete + + if(reply.kvs_size() == 0) + { + error_code=100; + error_message="Key not found"; + } + + for(int index=0; index < reply.kvs_size(); index++) + { + values.push_back(reply.kvs(index)); + } + } + index = reply.header().revision(); + return *this; +} diff --git a/v3/src/AsyncTxnResponse.cpp.orig b/v3/src/AsyncTxnResponse.cpp.orig new file mode 100644 index 0000000..cd6e649 --- /dev/null +++ b/v3/src/AsyncTxnResponse.cpp.orig @@ -0,0 +1,153 @@ +#include "v3/include/AsyncTxnResponse.hpp" +#include "v3/include/AsyncRangeResponse.hpp" + +using etcdserverpb::ResponseOp; + + +etcdv3::AsyncTxnResponse::AsyncTxnResponse(const etcdv3::AsyncTxnResponse& other) +{ + error_code = other.error_code; + error_message = other.error_message; + index = other.index; + action = other.action; + values = other.values; + prev_values = other.prev_values; + +} + +etcdv3::AsyncTxnResponse& etcdv3::AsyncTxnResponse::operator=(const etcdv3::AsyncTxnResponse& other) +{ + error_code = other.error_code; + error_message = other.error_message; + index = other.index; + action = other.action; + values = other.values; + prev_values = other.prev_values; + return *this; +} + +void etcdv3::AsyncTxnResponse::waitForResponse() +{ + void* got_tag; + bool ok = false; + + cq_.Next(&got_tag, &ok); + GPR_ASSERT(got_tag == (void*)this); +} + +etcdv3::AsyncTxnResponse& etcdv3::AsyncTxnResponse::ParseResponse() +{ + + index = reply.header().revision(); + if(!status.ok()) + if(reply.succeeded()) + error_code = status.error_code(); + error_message = status.error_message(); + } + else + { + std::vector range_kvs; + std::vector prev_range_kvs; + for(int index=0; index < reply.responses_size(); index++) + { + auto resp = reply.responses(index); + if(ResponseOp::ResponseCase::kResponseRange == resp.response_case()) + { + AsyncRangeResponse response; + response.reply = resp.response_range(); + auto v3resp = response.ParseResponse(); + + error_code = v3resp.error_code; + error_message = v3resp.error_message; + + if(!v3resp.values.empty()) + { + prev_range_kvs=range_kvs; + range_kvs = v3resp.values; +<<<<<<< 4adff1a7552b34d6c98def525fa38351e37bf47d + } +======= + } + } +>>>>>>> made prev_values a vector. + else if(ResponseOp::ResponseCase::kResponseDeleteRange == resp.response_case()) + { + //do nothing yet + } + + if(!reply.succeeded()) + { + if(action == "create") + { + error_code=105; + error_message="Key already exists"; + } + else if(action == "compareAndSwap" || action == "compareAndDelete") + { + if(!error_code) + { + error_code=101; + error_message="Compare failed"; + } + } + + + prev_values = prev_range_kvs; + + values = range_kvs; + error_message = v3resp.error_message; + + if(action == "delete" || action == "compareAndDelete") + range_kvs.insert(range_kvs.end(), v3resp.values.begin(), v3resp.values.end()); + } + } + } + if(!reply.succeeded()) + { + prev_values = values; + { + } + else if(action == "compareAndSwap") + { + error_code=101; + error_message="Compare failed"; + } + } + +<<<<<<< 4adff1a7552b34d6c98def525fa38351e37bf47d + //find previous value of key + //retain only the last value gotten as the final value. + if(action == "set" || action == "create" || action == "compareAndSwap" || action == "update") + { + if(range_kvs.size() > 1) + { + prev_value = range_kvs.front(); + values.push_back(range_kvs.back()); + } + else + { + values = range_kvs; + } + + } + else + { + values = range_kvs; + } + + } + +======= + prev_values = prev_range_kvs; + + values = range_kvs; + + if(action == "delete") + { + prev_values = values; + } + + } +>>>>>>> made prev_values a vector. + return *this; +}