729 lines
27 KiB
C++
729 lines
27 KiB
C++
#if defined(_WIN32)
|
|
// see also: https://stackoverflow.com/questions/2561368/illegal-token-on-right-side-of
|
|
#define NOMINMAX
|
|
#endif
|
|
|
|
#include <pplx/pplxtasks.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include "etcd/SyncClient.hpp"
|
|
#include "etcd/Value.hpp"
|
|
|
|
#if defined(_WIN32)
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#else
|
|
#include <netdb.h>
|
|
#include <sys/socket.h>
|
|
#endif
|
|
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <limits>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <sstream>
|
|
#include <thread>
|
|
#include <utility>
|
|
|
|
#include <boost/algorithm/string.hpp>
|
|
|
|
#include <grpc++/grpc++.h>
|
|
#include <grpc++/security/credentials.h>
|
|
#include "proto/rpc.grpc.pb.h"
|
|
#include "proto/v3lock.grpc.pb.h"
|
|
#include "proto/v3election.grpc.pb.h"
|
|
|
|
#include "etcd/Client.hpp"
|
|
#include "etcd/KeepAlive.hpp"
|
|
#include "etcd/Watcher.hpp"
|
|
#include "etcd/v3/action_constants.hpp"
|
|
#include "etcd/v3/Action.hpp"
|
|
#include "etcd/v3/AsyncRangeResponse.hpp"
|
|
#include "etcd/v3/AsyncWatchResponse.hpp"
|
|
#include "etcd/v3/AsyncDeleteResponse.hpp"
|
|
#include "etcd/v3/AsyncPutResponse.hpp"
|
|
#include "etcd/v3/AsyncLockResponse.hpp"
|
|
#include "etcd/v3/AsyncElectionResponse.hpp"
|
|
#include "etcd/v3/AsyncTxnResponse.hpp"
|
|
#include "etcd/v3/Transaction.hpp"
|
|
|
|
#include "etcd/v3/AsyncSetAction.hpp"
|
|
#include "etcd/v3/AsyncCompareAndSwapAction.hpp"
|
|
#include "etcd/v3/AsyncCompareAndDeleteAction.hpp"
|
|
#include "etcd/v3/AsyncUpdateAction.hpp"
|
|
#include "etcd/v3/AsyncHeadAction.hpp"
|
|
#include "etcd/v3/AsyncRangeAction.hpp"
|
|
#include "etcd/v3/AsyncDeleteAction.hpp"
|
|
#include "etcd/v3/AsyncPutAction.hpp"
|
|
#include "etcd/v3/AsyncWatchAction.hpp"
|
|
#include "etcd/v3/AsyncLeaseAction.hpp"
|
|
#include "etcd/v3/AsyncLockAction.hpp"
|
|
#include "etcd/v3/AsyncElectionAction.hpp"
|
|
#include "etcd/v3/AsyncTxnAction.hpp"
|
|
|
|
etcd::Client::Client(etcd::SyncClient *client): client(client)
|
|
{
|
|
this->own_client = false;
|
|
}
|
|
|
|
etcd::Client* WithClient(etcd::SyncClient *client)
|
|
{
|
|
return new etcd::Client(client);
|
|
}
|
|
|
|
etcd::Client::Client(std::string const & address,
|
|
std::string const & load_balancer)
|
|
{
|
|
this->own_client = true;
|
|
this->client = new SyncClient(address, load_balancer);
|
|
}
|
|
|
|
etcd::Client::Client(std::string const & address,
|
|
grpc::ChannelArguments const & arguments)
|
|
{
|
|
this->own_client = true;
|
|
this->client = new SyncClient(address, arguments);
|
|
}
|
|
|
|
etcd::Client *etcd::Client::WithUrl(std::string const & etcd_url,
|
|
std::string const & load_balancer) {
|
|
return new etcd::Client(etcd_url, load_balancer);
|
|
}
|
|
|
|
etcd::Client *etcd::Client::WithUrl(std::string const & etcd_url,
|
|
grpc::ChannelArguments const & arguments) {
|
|
return new etcd::Client(etcd_url, arguments);
|
|
}
|
|
|
|
etcd::Client::Client(std::string const & address,
|
|
std::string const & username,
|
|
std::string const & password,
|
|
int const auth_token_ttl,
|
|
std::string const & load_balancer)
|
|
{
|
|
this->own_client = true;
|
|
this->client = new SyncClient(address, username, password, auth_token_ttl, load_balancer);
|
|
}
|
|
|
|
etcd::Client::Client(std::string const & address,
|
|
std::string const & username,
|
|
std::string const & password,
|
|
int const auth_token_ttl,
|
|
grpc::ChannelArguments const & arguments)
|
|
{
|
|
this->own_client = true;
|
|
this->client = new SyncClient(address, username, password, auth_token_ttl, arguments);
|
|
}
|
|
|
|
etcd::Client *etcd::Client::WithUser(std::string const & etcd_url,
|
|
std::string const & username,
|
|
std::string const & password,
|
|
int const auth_token_ttl,
|
|
std::string const & load_balancer) {
|
|
return new etcd::Client(etcd_url, username, password, auth_token_ttl, load_balancer);
|
|
}
|
|
|
|
etcd::Client *etcd::Client::WithUser(std::string const & etcd_url,
|
|
std::string const & username,
|
|
std::string const & password,
|
|
int const auth_token_ttl,
|
|
grpc::ChannelArguments const & arguments) {
|
|
return new etcd::Client(etcd_url, username, password, auth_token_ttl, arguments);
|
|
}
|
|
|
|
|
|
etcd::Client::Client(std::string const & address,
|
|
std::string const & ca,
|
|
std::string const & cert,
|
|
std::string const & privkey,
|
|
std::string const & target_name_override,
|
|
std::string const & load_balancer)
|
|
{
|
|
this->own_client = true;
|
|
this->client = new SyncClient(address, ca, cert, privkey, target_name_override, load_balancer);
|
|
}
|
|
|
|
etcd::Client::Client(std::string const & address,
|
|
std::string const & ca,
|
|
std::string const & cert,
|
|
std::string const & privkey,
|
|
std::string const & target_name_override,
|
|
grpc::ChannelArguments const & arguments)
|
|
{
|
|
this->own_client = true;
|
|
this->client = new SyncClient(address, ca, cert, privkey, target_name_override, arguments);
|
|
}
|
|
|
|
etcd::Client *etcd::Client::WithSSL(std::string const & etcd_url,
|
|
std::string const & ca,
|
|
std::string const & cert,
|
|
std::string const & privkey,
|
|
std::string const & target_name_override,
|
|
std::string const & load_balancer) {
|
|
return new etcd::Client(etcd_url, ca, cert, privkey, target_name_override, load_balancer);
|
|
}
|
|
|
|
etcd::Client *etcd::Client::WithSSL(std::string const & etcd_url,
|
|
grpc::ChannelArguments const & arguments,
|
|
std::string const & ca,
|
|
std::string const & cert,
|
|
std::string const & privkey,
|
|
std::string const & target_name_override) {
|
|
return new etcd::Client(etcd_url, ca, cert, privkey, target_name_override, arguments);
|
|
}
|
|
|
|
etcd::Client::~Client() {
|
|
if (this->own_client) {
|
|
delete this->client;
|
|
}
|
|
}
|
|
|
|
|
|
namespace etcd {
|
|
namespace detail {
|
|
|
|
// Pass rvalue reference to lambda,
|
|
//
|
|
// Inspired by: https://stackoverflow.com/a/20669290/5080177
|
|
|
|
template <typename A, typename F>
|
|
class capture_impl
|
|
{
|
|
mutable A a;
|
|
mutable F f;
|
|
public:
|
|
capture_impl(A && a, F && f)
|
|
: a{std::forward<A>(a)}, f{std::forward<F>(f)}
|
|
{}
|
|
|
|
template <typename ...Ts> auto operator()( Ts&&...args )
|
|
-> decltype(std::forward<F>(f)(std::forward<A>(a), std::forward<Ts>(args)... ))
|
|
{
|
|
return std::forward<F>(f)(std::forward<A>(a), std::forward<Ts>(args)... );
|
|
}
|
|
|
|
template <typename ...Ts> auto operator()( Ts&&...args ) const
|
|
-> decltype(std::forward<F>(f)(std::forward<A>(a), std::forward<Ts>(args)... ))
|
|
{
|
|
return std::forward<F>(f)(std::forward<A>(a), std::forward<Ts>(args)... );
|
|
}
|
|
};
|
|
|
|
template <typename A, typename F>
|
|
static capture_impl<A, F> capture(A && a, F && f)
|
|
{
|
|
return capture_impl<A, F>(std::forward<A>(a), std::forward<F>(f));
|
|
}
|
|
|
|
template <typename F, typename Params, typename... Ts>
|
|
static auto asyncify(F && fn, Params && params, Ts... args) -> pplx::task<decltype(capture(std::forward<Params>(params), std::bind(std::forward<F>(fn), std::placeholders::_1, std::forward<Ts>(args)...))())> {
|
|
return pplx::task<decltype(capture(std::forward<Params>(params), std::bind(std::forward<F>(fn), std::placeholders::_1, std::forward<Ts>(args)...))())>(capture(std::forward<Params>(params), std::bind(std::forward<F>(fn), std::placeholders::_1, std::forward<Ts>(args)...)));
|
|
}
|
|
|
|
} // namespace detail
|
|
|
|
template <typename T>
|
|
using responser_t = etcd::Response (*)(std::shared_ptr<T>);
|
|
|
|
} // namespace etcd
|
|
|
|
pplx::task<etcd::Response> etcd::Client::head()
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<etcd::responser_t<etcdv3::AsyncHeadAction>>(Response::create),
|
|
this->client->head_internal());
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::get(std::string const & key)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<etcd::responser_t<etcdv3::AsyncRangeAction>>(Response::create),
|
|
this->client->get_internal(key));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value, int ttl)
|
|
{
|
|
if (ttl > 0) {
|
|
return this->leasegrant(ttl).then([this, key, value](pplx::task<etcd::Response> const &task) {
|
|
auto resp = task.get();
|
|
if (resp.error_code() == 0) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncSetAction>>(Response::create),
|
|
this->client->set_internal(key, value, resp.value().lease()));
|
|
} else {
|
|
return pplx::task_from_result(resp);
|
|
}
|
|
});
|
|
} else {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncSetAction>>(Response::create),
|
|
this->client->set_internal(key, value, 0));
|
|
}
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::string const & value, int64_t leaseid)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncSetAction>>(Response::create),
|
|
this->client->set_internal(key, value, leaseid));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value, int ttl)
|
|
{
|
|
if (ttl > 0) {
|
|
return this->leasegrant(ttl).then([this, key, value](pplx::task<etcd::Response> const &task) {
|
|
auto resp = task.get();
|
|
if (resp.error_code() == 0) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncSetAction>>(Response::create),
|
|
this->client->add_internal(key, value, resp.value().lease()));
|
|
} else {
|
|
return pplx::task_from_result(resp);
|
|
}
|
|
});
|
|
} else {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncSetAction>>(Response::create),
|
|
this->client->add_internal(key, value, 0));
|
|
}
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::add(std::string const & key, std::string const & value, int64_t leaseid)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncSetAction>>(Response::create),
|
|
this->client->add_internal(key, value, leaseid));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::put(std::string const & key, std::string const & value) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncPutAction>>(Response::create),
|
|
this->client->put_internal(key, value));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value, int ttl)
|
|
{
|
|
if (ttl > 0) {
|
|
return this->leasegrant(ttl).then([this, key, value](pplx::task<etcd::Response> const &task) {
|
|
auto resp = task.get();
|
|
if (resp.error_code() == 0) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncUpdateAction>>(Response::create),
|
|
this->client->modify_internal(key, value, resp.value().lease()));
|
|
} else {
|
|
return pplx::task_from_result(resp);
|
|
}
|
|
});
|
|
} else {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncUpdateAction>>(Response::create),
|
|
this->client->modify_internal(key, value, 0));
|
|
}
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::modify(std::string const & key, std::string const & value, int64_t leaseid)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncUpdateAction>>(Response::create),
|
|
this->client->modify_internal(key, value, leaseid));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value, int ttl)
|
|
{
|
|
if (ttl > 0) {
|
|
return this->leasegrant(ttl).then([this, key, value, old_value](pplx::task<etcd::Response> const &task) {
|
|
auto resp = task.get();
|
|
if (resp.error_code() == 0) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncCompareAndSwapAction>>(Response::create),
|
|
this->client->modify_if_internal(key, value, 0, old_value, resp.value().lease(), etcdv3::AtomicityType::PREV_VALUE));
|
|
} else {
|
|
return pplx::task_from_result(resp);
|
|
}
|
|
});
|
|
} else {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncCompareAndSwapAction>>(Response::create),
|
|
this->client->modify_if_internal(key, value, 0, old_value, 0, etcdv3::AtomicityType::PREV_VALUE));
|
|
}
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::modify_if(std::string const & key, std::string const & value, std::string const & old_value, int64_t leaseid)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncCompareAndSwapAction>>(Response::create),
|
|
this->client->modify_if_internal(key, value, 0, old_value, leaseid, etcdv3::AtomicityType::PREV_VALUE));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::modify_if(std::string const & key, std::string const & value, int64_t old_index, int ttl)
|
|
{
|
|
if (ttl > 0) {
|
|
return this->leasegrant(ttl).then([this, key, value, old_index](pplx::task<etcd::Response> const &task) {
|
|
auto resp = task.get();
|
|
if (resp.error_code() == 0) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncCompareAndSwapAction>>(Response::create),
|
|
this->client->modify_if_internal(key, value, old_index, "", resp.value().lease(), etcdv3::AtomicityType::PREV_INDEX));
|
|
} else {
|
|
return pplx::task_from_result(resp);
|
|
}
|
|
});
|
|
} else {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncCompareAndSwapAction>>(Response::create),
|
|
this->client->modify_if_internal(key, value, old_index, "", 0, etcdv3::AtomicityType::PREV_INDEX));
|
|
}
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::modify_if(std::string const & key, std::string const & value, int64_t old_index, int64_t leaseid)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncCompareAndSwapAction>>(Response::create),
|
|
this->client->modify_if_internal(key, value, old_index, "", leaseid, etcdv3::AtomicityType::PREV_INDEX));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::rm(std::string const & key)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncDeleteAction>>(Response::create),
|
|
this->client->rm_internal(key));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::rm_if(std::string const & key, std::string const & old_value)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncCompareAndDeleteAction>>(Response::create),
|
|
this->client->rm_if_internal(key, 0, old_value, etcdv3::AtomicityType::PREV_VALUE));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::rm_if(std::string const & key, int64_t old_index)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncCompareAndDeleteAction>>(Response::create),
|
|
this->client->rm_if_internal(key, old_index, "", etcdv3::AtomicityType::PREV_INDEX));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::rmdir(std::string const & key, bool recursive)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncDeleteAction>>(Response::create),
|
|
this->client->rmdir_internal(key, recursive));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::rmdir(std::string const & key, const char *range_end)
|
|
{
|
|
return this->rmdir(key, std::string(range_end));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::rmdir(std::string const & key, std::string const &range_end)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncDeleteAction>>(Response::create),
|
|
this->client->rmdir_internal(key, range_end));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::ls(std::string const & key)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncRangeAction>>(Response::create),
|
|
this->client->ls_internal(key, 0));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::ls(std::string const & key, size_t const limit)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncRangeAction>>(Response::create),
|
|
this->client->ls_internal(key, limit));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::ls(std::string const & key, std::string const &range_end)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncRangeAction>>(Response::create),
|
|
this->client->ls_internal(key, range_end, 0));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::ls(std::string const & key, std::string const &range_end, size_t const limit)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncRangeAction>>(Response::create),
|
|
this->client->ls_internal(key, range_end, limit));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::keys(std::string const & key)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncRangeAction>>(Response::create),
|
|
this->client->ls_internal(key, 0, true));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::keys(std::string const & key, size_t const limit)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncRangeAction>>(Response::create),
|
|
this->client->ls_internal(key, limit, true));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::keys(std::string const & key, std::string const &range_end)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncRangeAction>>(Response::create),
|
|
this->client->ls_internal(key, range_end, 0, true));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::keys(std::string const & key, std::string const &range_end, size_t const limit)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncRangeAction>>(Response::create),
|
|
this->client->ls_internal(key, range_end, limit, true));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::watch(std::string const & key, bool recursive)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncWatchAction>>(Response::create),
|
|
this->client->watch_internal(key, 0, recursive));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::watch(std::string const & key, int64_t fromIndex, bool recursive)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncWatchAction>>(Response::create),
|
|
this->client->watch_internal(key, fromIndex, recursive));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::watch(std::string const & key, const char *range_end)
|
|
{
|
|
return this->watch(key, std::string(range_end));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::watch(std::string const & key, std::string const & range_end)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncWatchAction>>(Response::create),
|
|
this->client->watch_internal(key, range_end, 0));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::watch(std::string const & key, std::string const & range_end, int64_t fromIndex)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncWatchAction>>(Response::create),
|
|
this->client->watch_internal(key, range_end, fromIndex));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::leasegrant(int ttl)
|
|
{
|
|
// See Note [lease with TTL and issue the actual request]
|
|
return pplx::task<etcd::Response>([this, ttl]() {
|
|
return this->client->leasegrant(ttl);
|
|
});
|
|
}
|
|
|
|
pplx::task<std::shared_ptr<etcd::KeepAlive>> etcd::Client::leasekeepalive(int ttl) {
|
|
// See Note [lease with TTL and issue the actual request]
|
|
return pplx::task<std::shared_ptr<etcd::KeepAlive>>([this, ttl]() {
|
|
return this->client->leasekeepalive(ttl);
|
|
});
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::leaserevoke(int64_t lease_id)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncLeaseRevokeAction>>(Response::create),
|
|
this->client->leaserevoke_internal(lease_id));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::leasetimetolive(int64_t lease_id)
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncLeaseTimeToLiveAction>>(Response::create),
|
|
this->client->leasetimetolive_internal(lease_id));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::leases()
|
|
{
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncLeaseLeasesAction>>(Response::create),
|
|
this->client->leases_internal());
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::lock(std::string const &key) {
|
|
static const int DEFAULT_LEASE_TTL_FOR_LOCK = 10; // see also etcd::SyncClient::lock
|
|
return this->lock(key, DEFAULT_LEASE_TTL_FOR_LOCK);
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::lock(std::string const &key,
|
|
const bool sync) {
|
|
static const int DEFAULT_LEASE_TTL_FOR_LOCK = 10; // see also etcd::SyncClient::lock
|
|
return this->lock(key, DEFAULT_LEASE_TTL_FOR_LOCK, sync);
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::lock(std::string const &key,
|
|
int lease_ttl) {
|
|
// See Note [lease with TTL and issue the actual request]
|
|
// See also SyncClient::lock
|
|
//
|
|
// We don't separate the keepalive step and lock step to avoid leaving many
|
|
// busy-waiting keepalive tasks when waiting for the locks due to the contention
|
|
// of async threadpool.
|
|
return pplx::task<etcd::Response>([this, key, lease_ttl]() {
|
|
return this->client->lock(key, lease_ttl);
|
|
});
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::lock(std::string const &key,
|
|
int lease_ttl,
|
|
const bool sync) {
|
|
if (sync) {
|
|
pplx::task_completion_event<etcd::Response> event;
|
|
event.set(this->client->lock(key, lease_ttl));
|
|
return pplx::task<etcd::Response>(event);
|
|
} else {
|
|
return this->lock(key, lease_ttl);
|
|
}
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::lock_with_lease(std::string const &key,
|
|
int64_t lease_id) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncLockAction>>(Response::create),
|
|
this->client->lock_with_lease_internal(key, lease_id));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::lock_with_lease(std::string const &key,
|
|
int64_t lease_id,
|
|
const bool sync) {
|
|
if (sync) {
|
|
pplx::task_completion_event<etcd::Response> event;
|
|
event.set(this->client->lock_with_lease(key, lease_id));
|
|
return pplx::task<etcd::Response>(event);
|
|
} else {
|
|
return this->lock_with_lease(key, lease_id);
|
|
}
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::unlock(std::string const &lock_key) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncUnlockAction>>(Response::create),
|
|
this->client->unlock_internal(lock_key));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::txn(etcdv3::Transaction const &txn) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncTxnAction>>(Response::create),
|
|
this->client->txn_internal(txn));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::campaign(
|
|
std::string const &name, int64_t lease_id, std::string const &value) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncCampaignAction>>(Response::create),
|
|
this->client->campaign_internal(name, lease_id, value));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::proclaim(
|
|
std::string const &name, int64_t lease_id,
|
|
std::string const &key, int64_t revision, std::string const &value) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncProclaimAction>>(Response::create),
|
|
this->client->proclaim_internal(name, lease_id, key, revision, value));
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::leader(std::string const &name) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncLeaderAction>>(Response::create),
|
|
this->client->leader_internal(name));
|
|
}
|
|
|
|
std::unique_ptr<etcd::Client::Observer> etcd::Client::observe(std::string const &name) {
|
|
return this->client->observe(name);
|
|
}
|
|
|
|
pplx::task<etcd::Response> etcd::Client::resign(
|
|
std::string const &name, int64_t lease_id, std::string const &key, int64_t revision) {
|
|
return etcd::detail::asyncify(
|
|
static_cast<responser_t<etcdv3::AsyncResignAction>>(Response::create),
|
|
this->client->resign_internal(name, lease_id, key, revision));
|
|
}
|
|
|
|
const std::string &etcd::Client::current_auth_token() const {
|
|
return this->client->current_auth_token();
|
|
}
|
|
|
|
std::shared_ptr<grpc::Channel> etcd::Client::grpc_channel() const {
|
|
return this->client->grpc_channel();
|
|
}
|
|
|
|
etcd::SyncClient* etcd::Client::sync_client() const {
|
|
return this->client;
|
|
}
|
|
|
|
// watchers from the async client
|
|
|
|
etcd::Watcher::Watcher(Client const &client, std::string const & key,
|
|
std::function<void(Response)> callback,
|
|
std::function<void(bool)> wait_callback,
|
|
bool recursive):
|
|
Watcher(*client.sync_client(), key, callback, wait_callback, recursive) {
|
|
}
|
|
|
|
etcd::Watcher::Watcher(Client const &client, std::string const & key,
|
|
std::string const &range_end,
|
|
std::function<void(Response)> callback,
|
|
std::function<void(bool)> wait_callback):
|
|
Watcher(*client.sync_client(), key, range_end, callback, wait_callback) {
|
|
}
|
|
|
|
etcd::Watcher::Watcher(Client const &client, std::string const & key, int64_t fromIndex,
|
|
std::function<void(Response)> callback,
|
|
std::function<void(bool)> wait_callback,
|
|
bool recursive):
|
|
Watcher(*client.sync_client(), key, fromIndex, callback, wait_callback, recursive) {
|
|
}
|
|
|
|
etcd::Watcher::Watcher(Client const &client, std::string const & key,
|
|
std::string const &range_end, int64_t fromIndex,
|
|
std::function<void(Response)> callback,
|
|
std::function<void(bool)> wait_callback):
|
|
Watcher(*client.sync_client(), key, range_end, fromIndex, callback, wait_callback) {
|
|
}
|
|
|
|
etcd::Watcher::Watcher(Client const &client, std::string const & key,
|
|
std::function<void(Response)> callback,
|
|
bool recursive):
|
|
Watcher(*client.sync_client(), key, callback, recursive) {
|
|
}
|
|
|
|
etcd::Watcher::Watcher(Client const &client, std::string const & key,
|
|
std::string const &range_end,
|
|
std::function<void(Response)> callback):
|
|
Watcher(*client.sync_client(), key, range_end, callback) {
|
|
}
|
|
|
|
etcd::Watcher::Watcher(Client const &client, std::string const & key, int64_t fromIndex,
|
|
std::function<void(Response)> callback,
|
|
bool recursive):
|
|
Watcher(*client.sync_client(), key, fromIndex, callback, recursive) {
|
|
}
|
|
|
|
etcd::Watcher::Watcher(Client const &client, std::string const & key,
|
|
std::string const &range_end, int64_t fromIndex,
|
|
std::function<void(Response)> callback):
|
|
Watcher(*client.sync_client(), key, range_end, fromIndex, callback) {
|
|
}
|
|
|
|
// keepalive from then async client
|
|
|
|
etcd::KeepAlive::KeepAlive(Client const &client, int ttl, int64_t lease_id):
|
|
KeepAlive(*client.sync_client(), ttl, lease_id) {
|
|
}
|
|
|
|
etcd::KeepAlive::KeepAlive(Client const &client,
|
|
std::function<void (std::exception_ptr)> const &handler,
|
|
int ttl, int64_t lease_id):
|
|
KeepAlive(*client.sync_client(), handler, ttl, lease_id) {
|
|
}
|