First commit
This commit is contained in:
parent
19061bd9e1
commit
e37cb46922
|
|
@ -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 <cpprest/http_client.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <grpc++/grpc++.h>
|
||||||
|
#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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> watch(std::string const & key, int fromIndex, bool recursive = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::unique_ptr<KV::Stub> stub_;
|
||||||
|
std::unique_ptr<Watch::Stub> watchServiceStub;
|
||||||
|
|
||||||
|
std::unique_ptr<KV::Stub> stub_;
|
||||||
|
pplx::task<etcd::Response> send_asyncput(const std::string& key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_asyncadd(std::string const & key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify(std::string const & key, std::string const & value);
|
||||||
|
pplx::task<etcd::Response> send_asyncget(std::string const & key,std::string const& range_end="");
|
||||||
|
pplx::task<etcd::Response> send_put(const std::string& key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_get(std::string const & key);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value);
|
||||||
|
<<<<<<< a592ce75a199b4e275a50c5f29992aa7dc0ff8d1
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify_if(std::string const & key, std::string const & value, int old_index);
|
||||||
|
pplx::task<etcd::Response> send_asyncdelete(std::string const & key, bool recursive);
|
||||||
|
pplx::task<etcd::Response> send_asyncrm_if(std::string const &key, std::string const &old_value);
|
||||||
|
pplx::task<etcd::Response> send_asyncrm_if(std::string const &key, int old_index);
|
||||||
|
pplx::task<etcd::Response> send_asyncwatch(std::string const & key, bool recursive);
|
||||||
|
pplx::task<etcd::Response> send_asyncwatch(std::string const & key, int fromIndex, bool recursive);
|
||||||
|
private:
|
||||||
|
std::shared_ptr<etcdv3::AsyncTxnResponse> initiate_transaction(const std::string &operation,
|
||||||
|
etcdv3::Transaction& transaction);
|
||||||
|
};
|
||||||
|
=======
|
||||||
|
pplx::task<etcd::Response> send_asyncdelete(std::string const & key, bool recursive);
|
||||||
|
|
||||||
|
};
|
||||||
|
>>>>>>> Added delete
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
#ifndef __ETCD_CLIENT_HPP__
|
||||||
|
#define __ETCD_CLIENT_HPP__
|
||||||
|
|
||||||
|
#include "etcd/Response.hpp"
|
||||||
|
|
||||||
|
#include <cpprest/http_client.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <grpc++/grpc++.h>
|
||||||
|
#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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> watch(std::string const & key, int fromIndex, bool recursive = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
pplx::task<Response> send_get_request(web::http::uri_builder & uri);
|
||||||
|
pplx::task<Response> send_del_request(web::http::uri_builder & uri);
|
||||||
|
pplx::task<Response> 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<KV::Stub> stub_;
|
||||||
|
pplx::task<etcd::Response> send_asyncput(const std::string& key, const std::string& value);
|
||||||
|
std::unique_ptr<Watch::Stub> watchServiceStub;
|
||||||
|
pplx::task<etcd::Response> send_asyncget(std::string const & key);
|
||||||
|
pplx::task<etcd::Response> send_asyncadd(std::string const & key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify(std::string const & key, std::string const & value);
|
||||||
|
<<<<<<< b05a30586ef0191ca0d81fb87d79d781fc89f341
|
||||||
|
pplx::task<etcd::Response> send_put(const std::string& key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_get(std::string const & key);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value);
|
||||||
|
|
||||||
|
etcdv3::grpcClient grpcClient;
|
||||||
|
|
||||||
|
private:
|
||||||
|
pplx::task<Response> removeEntryWithKey(std::string const &entryKey);
|
||||||
|
pplx::task<Response> removeEntryWithKeyAndValue(std::string const &entryKey, std::string const &oldValue);
|
||||||
|
pplx::task<Response> removeEntryWithKeyAndIndex(std::string const &entryKey, int oldIndex);
|
||||||
|
pplx::task<Response> modifyEntryWithValueAndOldIndex(std::string const & key, std::string const & value, int old_index);
|
||||||
|
|
||||||
|
=======
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value);
|
||||||
|
>>>>>>> Use Txn
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
#ifndef __ETCD_CLIENT_HPP__
|
||||||
|
#define __ETCD_CLIENT_HPP__
|
||||||
|
|
||||||
|
#include "etcd/Response.hpp"
|
||||||
|
|
||||||
|
#include <cpprest/http_client.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <grpc++/grpc++.h>
|
||||||
|
#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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> watch(std::string const & key, int fromIndex, bool recursive = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
pplx::task<Response> send_get_request(web::http::uri_builder & uri);
|
||||||
|
pplx::task<Response> send_del_request(web::http::uri_builder & uri);
|
||||||
|
pplx::task<Response> send_put_request(web::http::uri_builder & uri, std::string const & key, std::string const & value);
|
||||||
|
|
||||||
|
web::http::client::http_client client;
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> send_asyncput(const std::string& key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_asyncget(std::string const & key);
|
||||||
|
pplx::task<etcd::Response> send_asyncadd(std::string const & key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify(std::string const & key, std::string const & value);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value);
|
||||||
|
|
||||||
|
etcdv3::grpcClient grpcClient;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
#ifndef __ETCD_CLIENT_HPP__
|
||||||
|
#define __ETCD_CLIENT_HPP__
|
||||||
|
|
||||||
|
#include "etcd/Response.hpp"
|
||||||
|
|
||||||
|
#include <cpprest/http_client.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <grpc++/grpc++.h>
|
||||||
|
#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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> watch(std::string const & key, int fromIndex, bool recursive = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
pplx::task<Response> send_get_request(web::http::uri_builder & uri);
|
||||||
|
pplx::task<Response> send_del_request(web::http::uri_builder & uri);
|
||||||
|
pplx::task<Response> 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<KV::Stub> stub_;
|
||||||
|
pplx::task<etcd::Response> send_asyncput(const std::string& key, const std::string& value);
|
||||||
|
std::unique_ptr<Watch::Stub> watchServiceStub;
|
||||||
|
pplx::task<etcd::Response> send_asyncget(std::string const & key);
|
||||||
|
pplx::task<etcd::Response> send_asyncadd(std::string const & key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify(std::string const & key, std::string const & value);
|
||||||
|
pplx::task<etcd::Response> send_put(const std::string& key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_get(std::string const & key);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value);
|
||||||
|
|
||||||
|
etcdv3::grpcClient grpcClient;
|
||||||
|
|
||||||
|
private:
|
||||||
|
pplx::task<Response> removeEntryWithKey(std::string const &entryKey);
|
||||||
|
pplx::task<Response> removeEntryWithKeyAndValue(std::string const &entryKey, std::string const &oldValue);
|
||||||
|
pplx::task<Response> removeEntryWithKeyAndIndex(std::string const &entryKey, int oldIndex);
|
||||||
|
pplx::task<Response> modifyEntryWithValueAndOldIndex(std::string const & key, std::string const & value, int old_index);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
#ifndef __ETCD_CLIENT_HPP__
|
||||||
|
#define __ETCD_CLIENT_HPP__
|
||||||
|
|
||||||
|
#include "etcd/Response.hpp"
|
||||||
|
|
||||||
|
#include <cpprest/http_client.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <grpc++/grpc++.h>
|
||||||
|
#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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> 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<Response> watch(std::string const & key, int fromIndex, bool recursive = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
pplx::task<Response> send_get_request(web::http::uri_builder & uri);
|
||||||
|
pplx::task<Response> send_del_request(web::http::uri_builder & uri);
|
||||||
|
pplx::task<Response> 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<KV::Stub> stub_;
|
||||||
|
pplx::task<etcd::Response> send_asyncput(const std::string& key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_asyncget(std::string const & key);
|
||||||
|
pplx::task<etcd::Response> send_asyncadd(std::string const & key, const std::string& value);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify(std::string const & key, std::string const & value);
|
||||||
|
pplx::task<etcd::Response> send_asyncmodify_if(std::string const & key, std::string const & value, std::string const & old_value);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
#ifndef __ETCD_RESPONSE_HPP__
|
||||||
|
#define __ETCD_RESPONSE_HPP__
|
||||||
|
|
||||||
|
#include <cpprest/http_client.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "etcd/Value.hpp"
|
||||||
|
#include <grpc++/grpc++.h>
|
||||||
|
|
||||||
|
#include "v3/include/V3Response.hpp"
|
||||||
|
#include <grpc++/grpc++.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace etcd
|
||||||
|
{
|
||||||
|
typedef std::vector<std::string> Keys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Reponse object received for the requests of etcd::Client
|
||||||
|
*/
|
||||||
|
class Response
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static pplx::task<Response> create(pplx::task<web::http::http_response> response_task);
|
||||||
|
|
||||||
|
<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77
|
||||||
|
=======
|
||||||
|
static pplx::task<Response> createResponse(const etcdv3::V3Response& response);
|
||||||
|
|
||||||
|
>>>>>>> make templated create with shared_ptr arguement
|
||||||
|
template<typename T>static pplx::task<etcd::Response> create(std::shared_ptr<T> call)
|
||||||
|
{
|
||||||
|
return pplx::task<etcd::Response>([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
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -0,0 +1,553 @@
|
||||||
|
#include <memory>
|
||||||
|
#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 <iostream>
|
||||||
|
|
||||||
|
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> channel = grpc::CreateChannel(stripped_address, grpc::InsecureChannelCredentials());
|
||||||
|
stub_= KV::NewStub(channel);
|
||||||
|
<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77
|
||||||
|
{
|
||||||
|
stripped_address.erase(i,substr.length());
|
||||||
|
}
|
||||||
|
std::shared_ptr<Channel> 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::Response> etcd::Client::get(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncget(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncput(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncadd(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncmodify(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> etcd::Client::rm(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncdelete(key,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::rm_if(std::string const & key, std::string const & old_value)
|
||||||
|
{
|
||||||
|
return send_asyncrm_if(key, old_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::rm_if(std::string const & key, int old_index)
|
||||||
|
{
|
||||||
|
return send_asyncrm_if(key, old_index);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::rmdir(std::string const & key, bool recursive)
|
||||||
|
{
|
||||||
|
|
||||||
|
return send_asyncdelete(key,recursive);
|
||||||
|
|
||||||
|
return send_asyncdelete(key,recursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> etcd::Client::watch(std::string const & key, bool recursive)
|
||||||
|
{
|
||||||
|
return send_asyncwatch(key,recursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::watch(std::string const & key, int fromIndex, bool recursive)
|
||||||
|
{
|
||||||
|
return send_asyncwatch(key, fromIndex, recursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<etcdv3::AsyncTxnResponse> etcd::Client::initiate_transaction(const std::string &operation,
|
||||||
|
etcdv3::Transaction& transaction)
|
||||||
|
{
|
||||||
|
std::shared_ptr<etcdv3::AsyncTxnResponse> 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::Response> 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<etcdv3::AsyncTxnResponse> call = initiate_transaction("create", transaction);
|
||||||
|
return Response::create(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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<etcdv3::AsyncTxnResponse> 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<etcdv3::AsyncTxnResponse> 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::Response> 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<etcdv3::AsyncTxnResponse> call = initiate_transaction("compareAndSwap", transaction);
|
||||||
|
return Response::create(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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<etcdv3::AsyncTxnResponse> call = initiate_transaction("update", transaction);
|
||||||
|
return Response::create(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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<etcdv3::AsyncRangeResponse> 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::Response> 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<etcdv3::AsyncTxnResponse> 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<etcdv3::AsyncTxnResponse> call = initiate_transaction("set", transaction);
|
||||||
|
return Response::create(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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<etcdv3::AsyncTxnResponse> call = initiate_transaction("delete", transaction);
|
||||||
|
return Response::create(call);
|
||||||
|
}
|
||||||
|
req_success->set_allocated_request_range(get_request.release());
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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<etcdv3::AsyncTxnResponse> 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<etcdv3::AsyncTxnResponse> call = initiate_transaction("compareAndDelete", transaction);
|
||||||
|
return Response::create(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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<etcdv3::AsyncRangeResponse> 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<etcdv3::AsyncTxnResponse> call = initiate_transaction("compareAndDelete", transaction);
|
||||||
|
return Response::create(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::send_asyncwatch(std::string const & key, bool recursive)
|
||||||
|
{
|
||||||
|
<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77
|
||||||
|
std::shared_ptr<etcdv3::AsyncWatchResponse> 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<ClientReaderWriter<WatchRequest,WatchResponse>> 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<etcdv3::AsyncTxnResponse> 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::Response> 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<RangeRequest> 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<DeleteRangeRequest> 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<etcdv3::AsyncTxnResponse> call(new etcdv3::AsyncTxnResponse("delete"));
|
||||||
|
|
||||||
|
call->response_reader = stub_->AsyncTxn(&call->context,txn_request,&call->cq_);
|
||||||
|
|
||||||
|
<<<<<<< d262688a8e4d8413a46f5fac4225c549c3039c77
|
||||||
|
pplx::task<etcd::Response> etcd::Client::send_asyncwatch(std::string const & key, int fromIndex, bool recursive)
|
||||||
|
{
|
||||||
|
std::shared_ptr<etcdv3::AsyncWatchResponse> 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);
|
||||||
|
}
|
||||||
|
|
@ -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 <iostream>
|
||||||
|
=======
|
||||||
|
#include "v3/include/AsyncTxnResponse.hpp"
|
||||||
|
#include "v3/include/Utils.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
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::Response> 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::Response> 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::Response> 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::Response> etcd::Client::get(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncget(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncput(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncadd(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncmodify(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> etcd::Client::rm(std::string const & key)
|
||||||
|
{
|
||||||
|
return removeEntryWithKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> etcd::Client::rm_if(std::string const & key, std::string const & old_value)
|
||||||
|
{
|
||||||
|
return removeEntryWithKeyAndValue(key, old_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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 <iostream>
|
||||||
|
=======
|
||||||
|
#include "v3/include/AsyncTxnResponse.hpp"
|
||||||
|
#include "v3/include/Utils.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
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::Response> 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::Response> 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::Response> 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::Response> etcd::Client::get(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncget(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncput(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncadd(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncmodify(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> etcd::Client::rm(std::string const & key)
|
||||||
|
{
|
||||||
|
return removeEntryWithKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> etcd::Client::rm_if(std::string const & key, std::string const & old_value)
|
||||||
|
{
|
||||||
|
return removeEntryWithKeyAndValue(key, old_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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::Response> 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::Response> 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::Response> 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::Response> etcd::Client::get(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncget(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncput(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncadd(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncmodify(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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::Response> 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::Response> 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::Response> 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::Response> etcd::Client::get(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncget(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncput(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncadd(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncmodify(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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 <iostream>
|
||||||
|
|
||||||
|
etcd::Client::Client(std::string const & address)
|
||||||
|
: client(address), grpcClient(address)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> etcd::Client::get(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncget(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncput(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncadd(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncmodify(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> etcd::Client::rm(std::string const & key)
|
||||||
|
{
|
||||||
|
return removeEntryWithKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> etcd::Client::rm_if(std::string const & key, std::string const & old_value)
|
||||||
|
{
|
||||||
|
return removeEntryWithKeyAndValue(key, old_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> etcd::Client::rm_if(std::string const & key, int old_index)
|
||||||
|
{
|
||||||
|
return removeEntryWithKeyAndIndex(key, old_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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 <iostream>
|
||||||
|
|
||||||
|
etcd::Client::Client(std::string const & address)
|
||||||
|
: client(address), grpcClient(address)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> etcd::Client::get(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncget(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncput(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncadd(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncmodify(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> etcd::Client::rm(std::string const & key)
|
||||||
|
{
|
||||||
|
return removeEntryWithKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> etcd::Client::rm_if(std::string const & key, std::string const & old_value)
|
||||||
|
{
|
||||||
|
return removeEntryWithKeyAndValue(key, old_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> etcd::Client::rm_if(std::string const & key, int old_index)
|
||||||
|
{
|
||||||
|
return removeEntryWithKeyAndIndex(key, old_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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 <memory>
|
||||||
|
|
||||||
|
|
||||||
|
using etcdserverpb::TxnRequest;
|
||||||
|
using etcdserverpb::Compare;
|
||||||
|
using etcdserverpb::RequestOp;
|
||||||
|
|
||||||
|
etcd::Client::Client(std::string const & address)
|
||||||
|
: client(address), grpcClient(address)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> etcd::Client::get(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncget(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncput(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncadd(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncmodify(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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 <memory>
|
||||||
|
|
||||||
|
|
||||||
|
using etcdserverpb::TxnRequest;
|
||||||
|
using etcdserverpb::Compare;
|
||||||
|
using etcdserverpb::RequestOp;
|
||||||
|
|
||||||
|
etcd::Client::Client(std::string const & address)
|
||||||
|
: client(address), grpcClient(address)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> etcd::Client::get(std::string const & key)
|
||||||
|
{
|
||||||
|
return send_asyncget(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncput(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncadd(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value)
|
||||||
|
{
|
||||||
|
return send_asyncmodify(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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::Response> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
#include "etcd/Response.hpp"
|
||||||
|
#include "json_constants.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
pplx::task<etcd::Response> etcd::Response::create(pplx::task<web::http::http_response> response_task)
|
||||||
|
{
|
||||||
|
return pplx::task<etcd::Response> (
|
||||||
|
[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];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,304 @@
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#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<etcd::Response> 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<etcd::Response> 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<etcd::Response> 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef __ASYNC_RANGERESPONSE_HPP__
|
||||||
|
#define __ASYNC_RANGERESPONSE_HPP__
|
||||||
|
|
||||||
|
#include <grpc++/grpc++.h>
|
||||||
|
#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<ClientAsyncResponseReader<RangeResponse>> response_reader;
|
||||||
|
<<<<<<< a592ce75a199b4e275a50c5f29992aa7dc0ff8d1
|
||||||
|
=======
|
||||||
|
AsyncRangeResponse& ParseResponse();
|
||||||
|
>>>>>>> Added delete
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
#ifndef __ASYNC_TXNRESPONSE_HPP__
|
||||||
|
#define __ASYNC_TXNRESPONSE_HPP__
|
||||||
|
|
||||||
|
#include <grpc++/grpc++.h>
|
||||||
|
#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<ClientAsyncResponseReader<TxnResponse>> response_reader;
|
||||||
|
<<<<<<< 0cb5bd762aca24c5a8d9e959c5f72590d85ad2b4
|
||||||
|
=======
|
||||||
|
AsyncTxnResponse& ParseResponse();
|
||||||
|
>>>>>>> Use Txn for add()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "v3/include/AsyncPutResponse.hpp"
|
||||||
|
#include "v3/include/Utils.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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<mvccpb::KeyValue> range_kvs;
|
||||||
|
std::vector<mvccpb::KeyValue> 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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue