2018-01-15 19:07:47 +00:00
|
|
|
#include "ZooKeeper.h"
|
|
|
|
|
2017-08-25 16:35:10 +00:00
|
|
|
#include <random>
|
2017-09-09 23:17:38 +00:00
|
|
|
#include <pcg_random.hpp>
|
2014-10-16 01:21:03 +00:00
|
|
|
#include <functional>
|
2018-03-22 12:15:06 +00:00
|
|
|
#include <boost/algorithm/string.hpp>
|
|
|
|
|
2015-09-29 19:19:54 +00:00
|
|
|
#include <common/logger_useful.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Common/ProfileEvents.h>
|
2018-01-15 19:07:47 +00:00
|
|
|
#include <Common/StringUtils/StringUtils.h>
|
2017-10-23 15:08:31 +00:00
|
|
|
#include <Common/PODArray.h>
|
2017-09-09 23:17:38 +00:00
|
|
|
#include <Common/randomSeed.h>
|
2014-10-16 01:21:03 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
#define ZOOKEEPER_CONNECTION_TIMEOUT_MS 1000
|
2018-03-24 23:01:21 +00:00
|
|
|
#define ZOOKEEPER_OPERATION_TIMEOUT_MS 1000
|
2018-03-22 12:15:06 +00:00
|
|
|
|
2014-03-07 13:50:58 +00:00
|
|
|
|
2016-10-24 02:02:37 +00:00
|
|
|
namespace ProfileEvents
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const Event ZooKeeperInit;
|
|
|
|
extern const Event ZooKeeperTransactions;
|
|
|
|
extern const Event ZooKeeperCreate;
|
|
|
|
extern const Event ZooKeeperRemove;
|
|
|
|
extern const Event ZooKeeperExists;
|
|
|
|
extern const Event ZooKeeperMulti;
|
|
|
|
extern const Event ZooKeeperGet;
|
|
|
|
extern const Event ZooKeeperSet;
|
|
|
|
extern const Event ZooKeeperGetChildren;
|
2016-10-24 02:02:37 +00:00
|
|
|
}
|
|
|
|
|
2016-10-24 13:47:15 +00:00
|
|
|
namespace CurrentMetrics
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const Metric ZooKeeperWatch;
|
2016-10-24 13:47:15 +00:00
|
|
|
}
|
|
|
|
|
2016-10-24 02:02:37 +00:00
|
|
|
|
2018-01-19 22:37:50 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int LOGICAL_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-07 13:50:58 +00:00
|
|
|
namespace zkutil
|
|
|
|
{
|
|
|
|
|
2014-06-04 13:48:36 +00:00
|
|
|
const int CreateMode::Persistent = 0;
|
2018-03-19 21:34:56 +00:00
|
|
|
const int CreateMode::Ephemeral = 1;
|
|
|
|
const int CreateMode::PersistentSequential = 2;
|
|
|
|
const int CreateMode::EphemeralSequential = 3;
|
2014-06-04 13:48:36 +00:00
|
|
|
|
2017-09-07 21:04:48 +00:00
|
|
|
|
|
|
|
static void check(int32_t code, const std::string & path)
|
2014-06-04 16:48:55 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
if (code)
|
2017-09-07 21:04:48 +00:00
|
|
|
throw KeeperException(code, path);
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
2014-06-04 13:48:36 +00:00
|
|
|
|
2017-09-07 21:04:48 +00:00
|
|
|
|
2017-11-01 22:59:27 +00:00
|
|
|
void ZooKeeper::init(const std::string & hosts_, const std::string & identity_,
|
2018-03-12 17:45:24 +00:00
|
|
|
int32_t session_timeout_ms_, const std::string & chroot_)
|
2014-03-07 13:50:58 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
log = &Logger::get("ZooKeeper");
|
|
|
|
hosts = hosts_;
|
2017-08-28 17:12:43 +00:00
|
|
|
identity = identity_;
|
2017-04-01 07:20:54 +00:00
|
|
|
session_timeout_ms = session_timeout_ms_;
|
2018-03-12 17:45:24 +00:00
|
|
|
chroot = chroot_;
|
2014-03-13 14:49:17 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
std::vector<std::string> addresses_strings;
|
|
|
|
boost::split(addresses_strings, hosts, boost::is_any_of(","));
|
|
|
|
ZooKeeperImpl::ZooKeeper::Addresses addresses;
|
|
|
|
addresses.reserve(addresses_strings.size());
|
|
|
|
for (const auto & address_string : addresses_strings)
|
|
|
|
addresses.emplace_back(address_string);
|
|
|
|
|
|
|
|
impl = std::make_unique<ZooKeeperImpl::ZooKeeper>(
|
|
|
|
addresses,
|
|
|
|
chroot,
|
|
|
|
identity_.empty() ? "" : "digest",
|
|
|
|
identity_,
|
|
|
|
Poco::Timespan(0, session_timeout_ms_ * 1000),
|
2018-03-24 23:01:21 +00:00
|
|
|
Poco::Timespan(0, ZOOKEEPER_CONNECTION_TIMEOUT_MS * 1000),
|
|
|
|
Poco::Timespan(0, ZOOKEEPER_OPERATION_TIMEOUT_MS * 1000));
|
2017-08-28 16:35:57 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperInit);
|
2017-08-29 19:18:27 +00:00
|
|
|
|
2018-03-12 17:45:24 +00:00
|
|
|
LOG_TRACE(log, "initialized, hosts: " << hosts << (chroot.empty() ? "" : ", chroot: " + chroot));
|
2017-11-01 22:59:27 +00:00
|
|
|
|
2018-03-12 17:45:24 +00:00
|
|
|
if (!chroot.empty() && !exists("/"))
|
2018-03-22 12:15:06 +00:00
|
|
|
throw KeeperException("Zookeeper root doesn't exist. You should create root node " + chroot + " before start.", ZooKeeperImpl::ZooKeeper::ZNONODE);
|
2014-03-07 13:50:58 +00:00
|
|
|
}
|
|
|
|
|
2017-11-01 22:59:27 +00:00
|
|
|
ZooKeeper::ZooKeeper(const std::string & hosts, const std::string & identity,
|
2018-03-12 17:45:24 +00:00
|
|
|
int32_t session_timeout_ms, const std::string & chroot)
|
2014-03-13 14:49:17 +00:00
|
|
|
{
|
2018-03-12 17:45:24 +00:00
|
|
|
init(hosts, identity, session_timeout_ms, chroot);
|
2014-03-13 14:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ZooKeeperArgs
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
ZooKeeperArgs(const Poco::Util::AbstractConfiguration & config, const std::string & config_name)
|
|
|
|
{
|
|
|
|
Poco::Util::AbstractConfiguration::Keys keys;
|
|
|
|
config.keys(config_name, keys);
|
|
|
|
|
|
|
|
std::vector<std::string> hosts_strings;
|
|
|
|
|
|
|
|
session_timeout_ms = DEFAULT_SESSION_TIMEOUT;
|
|
|
|
for (const auto & key : keys)
|
|
|
|
{
|
|
|
|
if (startsWith(key, "node"))
|
|
|
|
{
|
|
|
|
hosts_strings.push_back(
|
2017-08-28 16:35:57 +00:00
|
|
|
config.getString(config_name + "." + key + ".host") + ":"
|
|
|
|
+ config.getString(config_name + "." + key + ".port", "2181")
|
|
|
|
);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else if (key == "session_timeout_ms")
|
|
|
|
{
|
|
|
|
session_timeout_ms = config.getInt(config_name + "." + key);
|
|
|
|
}
|
2017-08-28 16:35:57 +00:00
|
|
|
else if (key == "identity")
|
|
|
|
{
|
|
|
|
identity = config.getString(config_name + "." + key);
|
|
|
|
}
|
2017-08-29 19:18:27 +00:00
|
|
|
else if (key == "root")
|
|
|
|
{
|
2018-03-12 17:45:24 +00:00
|
|
|
chroot = config.getString(config_name + "." + key);
|
2017-08-29 19:18:27 +00:00
|
|
|
}
|
2018-03-22 12:15:06 +00:00
|
|
|
else
|
|
|
|
throw KeeperException(std::string("Unknown key ") + key + " in config file", ZooKeeperImpl::ZooKeeper::ZBADARGUMENTS);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Shuffle the hosts to distribute the load among ZooKeeper nodes.
|
2017-09-09 23:17:38 +00:00
|
|
|
pcg64 rng(randomSeed());
|
|
|
|
std::shuffle(hosts_strings.begin(), hosts_strings.end(), rng);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
for (auto & host : hosts_strings)
|
|
|
|
{
|
|
|
|
if (hosts.size())
|
|
|
|
hosts += ",";
|
2017-08-30 14:01:21 +00:00
|
|
|
hosts += host;
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-08-30 14:01:21 +00:00
|
|
|
|
2018-03-12 17:45:24 +00:00
|
|
|
if (!chroot.empty())
|
2017-08-30 18:04:47 +00:00
|
|
|
{
|
2018-03-12 17:45:24 +00:00
|
|
|
if (chroot.front() != '/')
|
2018-03-22 12:15:06 +00:00
|
|
|
throw KeeperException(std::string("Root path in config file should start with '/', but got ") + chroot, ZooKeeperImpl::ZooKeeper::ZBADARGUMENTS);
|
2018-03-12 17:45:24 +00:00
|
|
|
if (chroot.back() == '/')
|
|
|
|
chroot.pop_back();
|
2017-08-30 18:04:47 +00:00
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string hosts;
|
2017-08-28 16:35:57 +00:00
|
|
|
std::string identity;
|
|
|
|
int session_timeout_ms;
|
2018-03-12 17:45:24 +00:00
|
|
|
std::string chroot;
|
2014-03-13 14:49:17 +00:00
|
|
|
};
|
|
|
|
|
2014-07-08 12:45:10 +00:00
|
|
|
ZooKeeper::ZooKeeper(const Poco::Util::AbstractConfiguration & config, const std::string & config_name)
|
2014-03-13 14:49:17 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
ZooKeeperArgs args(config, config_name);
|
2018-03-12 17:45:24 +00:00
|
|
|
init(args.hosts, args.identity, args.session_timeout_ms, args.chroot);
|
2014-03-13 14:49:17 +00:00
|
|
|
}
|
|
|
|
|
2017-03-17 00:44:00 +00:00
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
static WatchCallback callbackForEvent(const EventPtr & watch)
|
2017-03-17 00:44:00 +00:00
|
|
|
{
|
2018-03-24 23:01:21 +00:00
|
|
|
if (!watch)
|
|
|
|
return {};
|
2018-03-19 21:34:56 +00:00
|
|
|
return [watch](const ZooKeeperImpl::ZooKeeper::WatchResponse &) { watch->set(); };
|
2014-06-30 11:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-04 16:48:55 +00:00
|
|
|
int32_t ZooKeeper::getChildrenImpl(const std::string & path, Strings & res,
|
2018-03-19 21:34:56 +00:00
|
|
|
Stat * stat,
|
2017-04-01 07:20:54 +00:00
|
|
|
WatchCallback watch_callback)
|
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = 0;
|
|
|
|
Poco::Event event;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
auto callback = [&](const ZooKeeperImpl::ZooKeeper::ListResponse & response)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
code = response.error;
|
|
|
|
if (!code)
|
|
|
|
{
|
|
|
|
res = response.names;
|
|
|
|
if (stat)
|
|
|
|
*stat = response.stat;
|
|
|
|
}
|
|
|
|
event.set();
|
|
|
|
};
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->list(path, callback, watch_callback);
|
2018-03-19 21:34:56 +00:00
|
|
|
event.wait();
|
2017-04-01 07:20:54 +00:00
|
|
|
return code;
|
2014-03-07 19:18:48 +00:00
|
|
|
}
|
2018-03-19 21:34:56 +00:00
|
|
|
|
2014-06-04 16:48:55 +00:00
|
|
|
Strings ZooKeeper::getChildren(
|
2017-04-01 07:20:54 +00:00
|
|
|
const std::string & path, Stat * stat, const EventPtr & watch)
|
2014-06-04 16:48:55 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
Strings res;
|
|
|
|
check(tryGetChildren(path, res, stat, watch), path);
|
|
|
|
return res;
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
2014-03-07 19:18:48 +00:00
|
|
|
|
2014-06-04 16:48:55 +00:00
|
|
|
int32_t ZooKeeper::tryGetChildren(const std::string & path, Strings & res,
|
2018-03-19 21:34:56 +00:00
|
|
|
Stat * stat, const EventPtr & watch)
|
2014-03-07 17:57:53 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = getChildrenImpl(path, res, stat, callbackForEvent(watch));
|
2014-06-04 16:48:55 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
if (!(code == ZooKeeperImpl::ZooKeeper::ZOK || code == ZooKeeperImpl::ZooKeeper::ZNONODE))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw KeeperException(code, path);
|
2014-06-04 16:48:55 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return code;
|
2014-03-07 17:57:53 +00:00
|
|
|
}
|
|
|
|
|
2016-04-09 02:03:44 +00:00
|
|
|
int32_t ZooKeeper::createImpl(const std::string & path, const std::string & data, int32_t mode, std::string & path_created)
|
2014-03-07 17:57:53 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = 0;
|
|
|
|
Poco::Event event;
|
2014-03-21 18:58:24 +00:00
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
auto callback = [&](const ZooKeeperImpl::ZooKeeper::CreateResponse & response)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
code = response.error;
|
|
|
|
if (!code)
|
|
|
|
path_created = response.path_created;
|
|
|
|
event.set();
|
|
|
|
};
|
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->create(path, data, mode & 1, mode & 2, {}, callback); /// TODO better mode
|
2018-03-19 21:34:56 +00:00
|
|
|
event.wait();
|
2014-06-04 16:48:55 +00:00
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperCreate);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
2017-04-01 07:20:54 +00:00
|
|
|
return code;
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string ZooKeeper::create(const std::string & path, const std::string & data, int32_t type)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
std::string path_created;
|
|
|
|
check(tryCreate(path, data, type, path_created), path);
|
|
|
|
return path_created;
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
|
|
|
|
2016-04-09 02:03:44 +00:00
|
|
|
int32_t ZooKeeper::tryCreate(const std::string & path, const std::string & data, int32_t mode, std::string & path_created)
|
2014-06-04 16:48:55 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = createImpl(path, data, mode, path_created);
|
2014-06-04 16:48:55 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
if (!(code == ZooKeeperImpl::ZooKeeper::ZOK ||
|
|
|
|
code == ZooKeeperImpl::ZooKeeper::ZNONODE ||
|
|
|
|
code == ZooKeeperImpl::ZooKeeper::ZNODEEXISTS ||
|
|
|
|
code == ZooKeeperImpl::ZooKeeper::ZNOCHILDRENFOREPHEMERALS))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw KeeperException(code, path);
|
2014-06-04 13:48:36 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return code;
|
2014-03-07 17:57:53 +00:00
|
|
|
}
|
|
|
|
|
2014-06-04 13:48:36 +00:00
|
|
|
int32_t ZooKeeper::tryCreate(const std::string & path, const std::string & data, int32_t mode)
|
2014-05-07 13:58:20 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
std::string path_created;
|
|
|
|
return tryCreate(path, data, mode, path_created);
|
2014-05-07 13:58:20 +00:00
|
|
|
}
|
|
|
|
|
2014-06-27 17:52:50 +00:00
|
|
|
void ZooKeeper::createIfNotExists(const std::string & path, const std::string & data)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
std::string path_created;
|
2018-03-21 21:40:53 +00:00
|
|
|
int32_t code = createImpl(path, data, CreateMode::Persistent, path_created);
|
2014-06-27 17:52:50 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
if (code == ZooKeeperImpl::ZooKeeper::ZOK || code == ZooKeeperImpl::ZooKeeper::ZNODEEXISTS)
|
2017-04-01 07:20:54 +00:00
|
|
|
return;
|
|
|
|
else
|
|
|
|
throw KeeperException(code, path);
|
2014-06-27 17:52:50 +00:00
|
|
|
}
|
|
|
|
|
2014-08-11 14:05:38 +00:00
|
|
|
void ZooKeeper::createAncestors(const std::string & path)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t pos = 1;
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
pos = path.find('/', pos);
|
|
|
|
if (pos == std::string::npos)
|
|
|
|
break;
|
|
|
|
createIfNotExists(path.substr(0, pos), "");
|
|
|
|
++pos;
|
|
|
|
}
|
2014-08-11 14:05:38 +00:00
|
|
|
}
|
|
|
|
|
2014-06-04 16:48:55 +00:00
|
|
|
int32_t ZooKeeper::removeImpl(const std::string & path, int32_t version)
|
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = 0;
|
|
|
|
Poco::Event event;
|
|
|
|
|
|
|
|
auto callback = [&](const ZooKeeperImpl::ZooKeeper::RemoveResponse & response)
|
|
|
|
{
|
|
|
|
if (response.error)
|
|
|
|
code = response.error;
|
|
|
|
event.set();
|
|
|
|
};
|
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->remove(path, version, callback);
|
2018-03-19 21:34:56 +00:00
|
|
|
event.wait();
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperRemove);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return code;
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
|
|
|
|
2014-03-07 17:57:53 +00:00
|
|
|
void ZooKeeper::remove(const std::string & path, int32_t version)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
check(tryRemove(path, version), path);
|
2014-03-07 17:57:53 +00:00
|
|
|
}
|
|
|
|
|
2014-06-04 13:48:36 +00:00
|
|
|
int32_t ZooKeeper::tryRemove(const std::string & path, int32_t version)
|
2014-03-07 17:57:53 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
int32_t code = removeImpl(path, version);
|
2018-03-22 12:15:06 +00:00
|
|
|
if (!(code == ZooKeeperImpl::ZooKeeper::ZOK ||
|
|
|
|
code == ZooKeeperImpl::ZooKeeper::ZNONODE ||
|
|
|
|
code == ZooKeeperImpl::ZooKeeper::ZBADVERSION ||
|
|
|
|
code == ZooKeeperImpl::ZooKeeper::ZNOTEMPTY))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw KeeperException(code, path);
|
|
|
|
return code;
|
2014-03-07 17:57:53 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t ZooKeeper::existsImpl(const std::string & path, Stat * stat, WatchCallback watch_callback)
|
2014-07-02 15:04:42 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = 0;
|
|
|
|
Poco::Event event;
|
2014-07-02 15:04:42 +00:00
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
auto callback = [&](const ZooKeeperImpl::ZooKeeper::ExistsResponse & response)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
code = response.error;
|
|
|
|
if (!code && stat)
|
|
|
|
*stat = response.stat;
|
|
|
|
event.set();
|
|
|
|
};
|
2016-04-09 02:03:44 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->exists(path, callback, watch_callback);
|
2018-03-19 21:34:56 +00:00
|
|
|
event.wait();
|
2016-04-09 02:03:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperExists);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return code;
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
bool ZooKeeper::exists(const std::string & path, Stat * stat, const EventPtr & watch)
|
2014-06-04 16:48:55 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
return existsWatch(path, stat, callbackForEvent(watch));
|
2014-03-07 17:57:53 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
bool ZooKeeper::existsWatch(const std::string & path, Stat * stat, const WatchCallback & watch_callback)
|
2017-03-17 00:44:00 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = existsImpl(path, stat, watch_callback);
|
2017-03-17 00:44:00 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
if (!(code == ZooKeeperImpl::ZooKeeper::ZOK || code == ZooKeeperImpl::ZooKeeper::ZNONODE))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw KeeperException(code, path);
|
2018-03-22 12:15:06 +00:00
|
|
|
if (code == ZooKeeperImpl::ZooKeeper::ZNONODE)
|
2017-04-01 07:20:54 +00:00
|
|
|
return false;
|
|
|
|
return true;
|
2017-03-17 00:44:00 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t ZooKeeper::getImpl(const std::string & path, std::string & res, Stat * stat, WatchCallback watch_callback)
|
2014-06-04 16:48:55 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = 0;
|
|
|
|
Poco::Event event;
|
2017-10-18 22:13:42 +00:00
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
auto callback = [&](const ZooKeeperImpl::ZooKeeper::GetResponse & response)
|
|
|
|
{
|
|
|
|
code = response.error;
|
|
|
|
if (!code)
|
|
|
|
{
|
|
|
|
res = response.data;
|
|
|
|
if (stat)
|
|
|
|
*stat = response.stat;
|
|
|
|
}
|
|
|
|
event.set();
|
|
|
|
};
|
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->get(path, callback, watch_callback);
|
2018-03-19 21:34:56 +00:00
|
|
|
event.wait();
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperGet);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return code;
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
|
|
|
|
2017-10-23 15:08:31 +00:00
|
|
|
|
2017-03-17 00:44:00 +00:00
|
|
|
std::string ZooKeeper::get(const std::string & path, Stat * stat, const EventPtr & watch)
|
2014-03-07 17:57:53 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = 0;
|
2017-04-01 07:20:54 +00:00
|
|
|
std::string res;
|
|
|
|
if (tryGet(path, res, stat, watch, &code))
|
|
|
|
return res;
|
|
|
|
else
|
|
|
|
throw KeeperException("Can't get data for node " + path + ": node doesn't exist", code);
|
2014-03-07 17:57:53 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
bool ZooKeeper::tryGet(const std::string & path, std::string & res, Stat * stat, const EventPtr & watch, int * return_code)
|
2017-03-17 00:44:00 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
return tryGetWatch(path, res, stat, callbackForEvent(watch), return_code);
|
2017-03-17 00:44:00 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
bool ZooKeeper::tryGetWatch(const std::string & path, std::string & res, Stat * stat, const WatchCallback & watch_callback, int * return_code)
|
2014-03-07 17:57:53 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = getImpl(path, res, stat, watch_callback);
|
2014-06-04 13:48:36 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
if (!(code == ZooKeeperImpl::ZooKeeper::ZOK || code == ZooKeeperImpl::ZooKeeper::ZNONODE))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw KeeperException(code, path);
|
2014-06-04 13:48:36 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (return_code)
|
|
|
|
*return_code = code;
|
2015-10-01 12:24:44 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
return code == ZooKeeperImpl::ZooKeeper::ZOK;
|
2014-03-07 13:50:58 +00:00
|
|
|
}
|
|
|
|
|
2014-06-04 16:48:55 +00:00
|
|
|
int32_t ZooKeeper::setImpl(const std::string & path, const std::string & data,
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t version, Stat * stat)
|
2014-06-04 16:48:55 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = 0;
|
|
|
|
Poco::Event event;
|
2014-09-11 20:34:41 +00:00
|
|
|
|
2018-03-19 21:34:56 +00:00
|
|
|
auto callback = [&](const ZooKeeperImpl::ZooKeeper::SetResponse & response)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
code = response.error;
|
|
|
|
if (!code && stat)
|
|
|
|
*stat = response.stat;
|
|
|
|
event.set();
|
|
|
|
};
|
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->set(path, data, version, callback);
|
2018-03-19 21:34:56 +00:00
|
|
|
event.wait();
|
|
|
|
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperSet);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
2017-04-01 07:20:54 +00:00
|
|
|
return code;
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
|
|
|
|
2014-03-07 17:57:53 +00:00
|
|
|
void ZooKeeper::set(const std::string & path, const std::string & data, int32_t version, Stat * stat)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
check(trySet(path, data, version, stat), path);
|
2014-03-07 17:57:53 +00:00
|
|
|
}
|
|
|
|
|
2015-06-09 12:30:30 +00:00
|
|
|
void ZooKeeper::createOrUpdate(const std::string & path, const std::string & data, int32_t mode)
|
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = trySet(path, data, -1);
|
2018-03-22 12:15:06 +00:00
|
|
|
if (code == ZooKeeperImpl::ZooKeeper::ZNONODE)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
create(path, data, mode);
|
|
|
|
}
|
2018-03-22 12:15:06 +00:00
|
|
|
else if (code != ZooKeeperImpl::ZooKeeper::ZOK)
|
2018-03-21 21:40:53 +00:00
|
|
|
throw KeeperException(code, path);
|
2015-06-09 12:30:30 +00:00
|
|
|
}
|
|
|
|
|
2014-06-04 13:48:36 +00:00
|
|
|
int32_t ZooKeeper::trySet(const std::string & path, const std::string & data,
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t version, Stat * stat)
|
2014-03-07 19:18:48 +00:00
|
|
|
{
|
2018-03-19 21:34:56 +00:00
|
|
|
int32_t code = setImpl(path, data, version, stat);
|
2014-06-04 16:48:55 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
if (!(code == ZooKeeperImpl::ZooKeeper::ZOK ||
|
|
|
|
code == ZooKeeperImpl::ZooKeeper::ZNONODE ||
|
|
|
|
code == ZooKeeperImpl::ZooKeeper::ZBADVERSION))
|
2017-04-01 07:20:54 +00:00
|
|
|
throw KeeperException(code, path);
|
|
|
|
return code;
|
2014-03-07 19:18:48 +00:00
|
|
|
}
|
|
|
|
|
2018-03-12 17:45:24 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
int32_t ZooKeeper::multiImpl(const Requests & requests, Responses & responses)
|
2014-06-04 13:48:36 +00:00
|
|
|
{
|
2018-03-21 21:40:53 +00:00
|
|
|
if (requests.empty())
|
2018-03-22 12:15:06 +00:00
|
|
|
return ZooKeeperImpl::ZooKeeper::ZOK;
|
2014-07-28 14:31:07 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
int32_t code = 0;
|
|
|
|
Poco::Event event;
|
2014-06-04 13:48:36 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
auto callback = [&](const ZooKeeperImpl::ZooKeeper::MultiResponse & response)
|
2018-03-13 20:36:22 +00:00
|
|
|
{
|
2018-03-21 21:40:53 +00:00
|
|
|
code = response.error;
|
2018-03-25 00:56:08 +00:00
|
|
|
responses = response.responses;
|
2018-03-21 21:40:53 +00:00
|
|
|
event.set();
|
|
|
|
};
|
2018-03-13 20:36:22 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->multi(requests, callback);
|
2018-03-21 21:40:53 +00:00
|
|
|
event.wait();
|
2014-06-04 16:48:55 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperMulti);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
2017-04-01 07:20:54 +00:00
|
|
|
return code;
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
Responses ZooKeeper::multi(const Requests & requests)
|
2014-06-04 16:48:55 +00:00
|
|
|
{
|
2018-03-21 21:40:53 +00:00
|
|
|
Responses responses;
|
|
|
|
int32_t code = multiImpl(requests, responses);
|
|
|
|
KeeperMultiException::check(code, requests, responses);
|
|
|
|
return responses;
|
2014-06-04 16:48:55 +00:00
|
|
|
}
|
|
|
|
|
2018-03-25 00:15:52 +00:00
|
|
|
int32_t ZooKeeper::tryMulti(const Requests & requests, Responses & responses)
|
2014-06-04 16:48:55 +00:00
|
|
|
{
|
2018-03-21 21:40:53 +00:00
|
|
|
int32_t code = multiImpl(requests, responses);
|
2018-03-25 00:15:52 +00:00
|
|
|
if (code && !isUserError(code))
|
2017-10-23 15:08:31 +00:00
|
|
|
throw KeeperException(code);
|
2017-04-01 07:20:54 +00:00
|
|
|
return code;
|
2014-03-07 19:18:48 +00:00
|
|
|
}
|
|
|
|
|
2014-06-30 14:21:39 +00:00
|
|
|
|
2014-05-27 12:08:40 +00:00
|
|
|
void ZooKeeper::removeChildrenRecursive(const std::string & path)
|
2014-03-22 14:44:44 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
Strings children = getChildren(path);
|
|
|
|
while (!children.empty())
|
|
|
|
{
|
2018-03-21 21:40:53 +00:00
|
|
|
Requests ops;
|
2017-08-09 21:09:44 +00:00
|
|
|
for (size_t i = 0; i < MULTI_BATCH_SIZE && !children.empty(); ++i)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
removeChildrenRecursive(path + "/" + children.back());
|
2018-03-25 00:56:08 +00:00
|
|
|
ops.emplace_back(makeRemoveRequest(path + "/" + children.back(), -1));
|
2017-04-01 07:20:54 +00:00
|
|
|
children.pop_back();
|
|
|
|
}
|
|
|
|
multi(ops);
|
|
|
|
}
|
2014-05-19 09:21:57 +00:00
|
|
|
}
|
|
|
|
|
2014-07-07 09:51:42 +00:00
|
|
|
void ZooKeeper::tryRemoveChildrenRecursive(const std::string & path)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
Strings children;
|
2018-03-22 12:15:06 +00:00
|
|
|
if (tryGetChildren(path, children) != ZooKeeperImpl::ZooKeeper::ZOK)
|
2017-04-01 07:20:54 +00:00
|
|
|
return;
|
|
|
|
while (!children.empty())
|
|
|
|
{
|
2018-03-21 21:40:53 +00:00
|
|
|
Requests ops;
|
2017-04-01 07:20:54 +00:00
|
|
|
Strings batch;
|
2017-08-09 21:09:44 +00:00
|
|
|
for (size_t i = 0; i < MULTI_BATCH_SIZE && !children.empty(); ++i)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
batch.push_back(path + "/" + children.back());
|
|
|
|
children.pop_back();
|
|
|
|
tryRemoveChildrenRecursive(batch.back());
|
2018-03-21 21:40:53 +00:00
|
|
|
|
|
|
|
ZooKeeperImpl::ZooKeeper::RemoveRequest request;
|
|
|
|
request.path = batch.back();
|
|
|
|
|
|
|
|
ops.emplace_back(std::make_shared<ZooKeeperImpl::ZooKeeper::RemoveRequest>(std::move(request)));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Try to remove the children with a faster method - in bulk. If this fails,
|
|
|
|
/// this means someone is concurrently removing these children and we will have
|
|
|
|
/// to remove them one by one.
|
2018-03-25 00:15:52 +00:00
|
|
|
Responses responses;
|
|
|
|
if (tryMulti(ops, responses) != ZooKeeperImpl::ZooKeeper::ZOK)
|
2017-04-01 07:20:54 +00:00
|
|
|
for (const std::string & child : batch)
|
|
|
|
tryRemove(child);
|
|
|
|
}
|
2014-07-07 09:51:42 +00:00
|
|
|
}
|
|
|
|
|
2014-05-19 09:21:57 +00:00
|
|
|
void ZooKeeper::removeRecursive(const std::string & path)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
removeChildrenRecursive(path);
|
|
|
|
remove(path);
|
2014-03-22 14:44:44 +00:00
|
|
|
}
|
|
|
|
|
2014-07-07 09:51:42 +00:00
|
|
|
void ZooKeeper::tryRemoveRecursive(const std::string & path)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
tryRemoveChildrenRecursive(path);
|
|
|
|
tryRemove(path);
|
2014-07-07 09:51:42 +00:00
|
|
|
}
|
|
|
|
|
2015-09-11 02:13:59 +00:00
|
|
|
|
|
|
|
void ZooKeeper::waitForDisappear(const std::string & path)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
while (true)
|
|
|
|
{
|
2018-03-21 21:40:53 +00:00
|
|
|
int32_t code = 0;
|
|
|
|
int32_t event_type = 0;
|
|
|
|
Poco::Event event;
|
2015-09-11 02:13:59 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
auto callback = [&](const ZooKeeperImpl::ZooKeeper::ExistsResponse & response)
|
|
|
|
{
|
|
|
|
code = response.error;
|
|
|
|
if (code)
|
|
|
|
event.set();
|
|
|
|
};
|
2015-09-11 02:13:59 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
auto watch = [&](const ZooKeeperImpl::ZooKeeper::WatchResponse & response)
|
|
|
|
{
|
|
|
|
code = response.error;
|
|
|
|
if (!code)
|
|
|
|
event_type = response.type;
|
|
|
|
event.set();
|
|
|
|
};
|
2015-09-11 02:13:59 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->exists(path, callback, watch);
|
2018-03-21 21:40:53 +00:00
|
|
|
event.wait();
|
2014-08-08 12:53:55 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperExists);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
2014-06-04 13:48:36 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
if (code == ZooKeeperImpl::ZooKeeper::ZNONODE)
|
2018-03-21 21:40:53 +00:00
|
|
|
return;
|
2014-08-08 12:53:55 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
if (code)
|
|
|
|
throw KeeperException(code, path);
|
2014-08-08 12:53:55 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
if (event_type == ZooKeeperImpl::ZooKeeper::DELETED)
|
|
|
|
return;
|
|
|
|
}
|
2014-03-07 17:57:53 +00:00
|
|
|
}
|
|
|
|
|
2014-04-25 13:55:15 +00:00
|
|
|
ZooKeeperPtr ZooKeeper::startNewSession() const
|
|
|
|
{
|
2018-03-12 17:45:24 +00:00
|
|
|
return std::make_shared<ZooKeeper>(hosts, identity, session_timeout_ms, chroot);
|
2014-04-25 13:55:15 +00:00
|
|
|
}
|
|
|
|
|
2014-06-04 13:48:36 +00:00
|
|
|
|
2014-06-04 13:51:40 +00:00
|
|
|
std::string ZooKeeper::error2string(int32_t code)
|
2014-06-04 13:48:36 +00:00
|
|
|
{
|
2018-03-21 21:40:53 +00:00
|
|
|
return ZooKeeperImpl::ZooKeeper::errorMessage(code);
|
2014-06-04 13:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ZooKeeper::expired()
|
|
|
|
{
|
2018-03-22 12:15:06 +00:00
|
|
|
return impl->isExpired();
|
2014-06-04 13:48:36 +00:00
|
|
|
}
|
2014-07-03 17:24:17 +00:00
|
|
|
|
2016-10-26 22:27:38 +00:00
|
|
|
Int64 ZooKeeper::getClientID()
|
2014-07-03 17:24:17 +00:00
|
|
|
{
|
2018-03-22 12:15:06 +00:00
|
|
|
return impl->getSessionID();
|
2014-07-03 17:24:17 +00:00
|
|
|
}
|
|
|
|
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
std::future<ZooKeeperImpl::ZooKeeper::GetResponse> ZooKeeper::asyncGet(const std::string & path)
|
2014-10-16 20:05:26 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
/// https://stackoverflow.com/questions/25421346/how-to-create-an-stdfunction-from-a-move-capturing-lambda-expression
|
|
|
|
auto promise = std::make_shared<std::promise<ZooKeeperImpl::ZooKeeper::GetResponse>>();
|
|
|
|
auto future = promise->get_future();
|
2015-10-13 09:57:59 +00:00
|
|
|
|
2018-03-25 04:20:31 +00:00
|
|
|
auto callback = [promise, path](const ZooKeeperImpl::ZooKeeper::GetResponse & response) mutable
|
2018-03-21 21:40:53 +00:00
|
|
|
{
|
|
|
|
if (response.error)
|
2018-03-25 04:20:31 +00:00
|
|
|
promise->set_exception(std::make_exception_ptr(KeeperException(path, response.error)));
|
2018-03-21 21:40:53 +00:00
|
|
|
else
|
2018-03-23 23:15:14 +00:00
|
|
|
promise->set_value(response);
|
2018-03-21 21:40:53 +00:00
|
|
|
};
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->get(path, std::move(callback), {});
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperGet);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return future;
|
2014-10-16 20:05:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
std::future<ZooKeeperImpl::ZooKeeper::GetResponse> ZooKeeper::asyncTryGet(const std::string & path)
|
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
auto promise = std::make_shared<std::promise<ZooKeeperImpl::ZooKeeper::GetResponse>>();
|
|
|
|
auto future = promise->get_future();
|
2015-10-13 09:57:59 +00:00
|
|
|
|
2018-03-25 04:20:31 +00:00
|
|
|
auto callback = [promise, path](const ZooKeeperImpl::ZooKeeper::GetResponse & response) mutable
|
2018-03-21 21:40:53 +00:00
|
|
|
{
|
2018-03-22 12:15:06 +00:00
|
|
|
if (response.error && response.error != ZooKeeperImpl::ZooKeeper::ZNONODE)
|
2018-03-25 04:20:31 +00:00
|
|
|
promise->set_exception(std::make_exception_ptr(KeeperException(path, response.error)));
|
2018-03-21 21:40:53 +00:00
|
|
|
else
|
2018-03-23 23:15:14 +00:00
|
|
|
promise->set_value(response);
|
2018-03-21 21:40:53 +00:00
|
|
|
};
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->get(path, std::move(callback), {});
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperGet);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return future;
|
2014-10-16 20:05:26 +00:00
|
|
|
}
|
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
std::future<ZooKeeperImpl::ZooKeeper::ExistsResponse> ZooKeeper::asyncExists(const std::string & path)
|
2014-10-16 20:05:26 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
auto promise = std::make_shared<std::promise<ZooKeeperImpl::ZooKeeper::ExistsResponse>>();
|
|
|
|
auto future = promise->get_future();
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2018-03-25 04:20:31 +00:00
|
|
|
auto callback = [promise, path](const ZooKeeperImpl::ZooKeeper::ExistsResponse & response) mutable
|
2018-03-21 21:40:53 +00:00
|
|
|
{
|
2018-03-22 12:15:06 +00:00
|
|
|
if (response.error && response.error != ZooKeeperImpl::ZooKeeper::ZNONODE)
|
2018-03-25 04:20:31 +00:00
|
|
|
promise->set_exception(std::make_exception_ptr(KeeperException(path, response.error)));
|
2018-03-21 21:40:53 +00:00
|
|
|
else
|
2018-03-23 23:15:14 +00:00
|
|
|
promise->set_value(response);
|
2018-03-21 21:40:53 +00:00
|
|
|
};
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->exists(path, std::move(callback), {});
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperExists);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return future;
|
2014-10-16 20:05:26 +00:00
|
|
|
}
|
|
|
|
|
2018-03-21 21:40:53 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
std::future<ZooKeeperImpl::ZooKeeper::ListResponse> ZooKeeper::asyncGetChildren(const std::string & path)
|
2014-10-16 20:05:26 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
auto promise = std::make_shared<std::promise<ZooKeeperImpl::ZooKeeper::ListResponse>>();
|
|
|
|
auto future = promise->get_future();
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2018-03-25 04:20:31 +00:00
|
|
|
auto callback = [promise, path](const ZooKeeperImpl::ZooKeeper::ListResponse & response) mutable
|
2018-03-22 12:15:06 +00:00
|
|
|
{
|
|
|
|
if (response.error)
|
2018-03-25 04:20:31 +00:00
|
|
|
promise->set_exception(std::make_exception_ptr(KeeperException(path, response.error)));
|
2018-03-22 12:15:06 +00:00
|
|
|
else
|
2018-03-23 23:15:14 +00:00
|
|
|
promise->set_value(response);
|
2018-03-22 12:15:06 +00:00
|
|
|
};
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->list(path, std::move(callback), {});
|
2014-10-16 20:05:26 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperGetChildren);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return future;
|
2014-10-16 20:05:26 +00:00
|
|
|
}
|
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
std::future<ZooKeeperImpl::ZooKeeper::RemoveResponse> ZooKeeper::asyncRemove(const std::string & path, int32_t version)
|
2015-09-23 20:51:01 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
auto promise = std::make_shared<std::promise<ZooKeeperImpl::ZooKeeper::RemoveResponse>>();
|
|
|
|
auto future = promise->get_future();
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2018-03-25 04:20:31 +00:00
|
|
|
auto callback = [promise, path](const ZooKeeperImpl::ZooKeeper::RemoveResponse & response) mutable
|
2018-03-22 12:15:06 +00:00
|
|
|
{
|
|
|
|
if (response.error)
|
2018-03-25 04:20:31 +00:00
|
|
|
promise->set_exception(std::make_exception_ptr(KeeperException(path, response.error)));
|
2018-03-22 12:15:06 +00:00
|
|
|
else
|
2018-03-23 23:15:14 +00:00
|
|
|
promise->set_value(response);
|
2018-03-22 12:15:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
impl->remove(path, version, std::move(callback));
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperRemove);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return future;
|
2015-09-23 20:51:01 +00:00
|
|
|
}
|
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
std::future<ZooKeeperImpl::ZooKeeper::RemoveResponse> ZooKeeper::asyncTryRemove(const std::string & path, int32_t version)
|
2017-11-15 12:39:33 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
auto promise = std::make_shared<std::promise<ZooKeeperImpl::ZooKeeper::RemoveResponse>>();
|
|
|
|
auto future = promise->get_future();
|
2017-11-15 12:39:33 +00:00
|
|
|
|
2018-03-25 04:20:31 +00:00
|
|
|
auto callback = [promise, path](const ZooKeeperImpl::ZooKeeper::RemoveResponse & response) mutable
|
2018-03-22 12:15:06 +00:00
|
|
|
{
|
|
|
|
if (response.error && response.error != ZooKeeperImpl::ZooKeeper::ZNONODE && response.error != ZooKeeperImpl::ZooKeeper::ZBADVERSION && response.error != ZooKeeperImpl::ZooKeeper::ZNOTEMPTY)
|
2018-03-25 04:20:31 +00:00
|
|
|
promise->set_exception(std::make_exception_ptr(KeeperException(path, response.error)));
|
2018-03-22 12:15:06 +00:00
|
|
|
else
|
2018-03-23 23:15:14 +00:00
|
|
|
promise->set_value(response);
|
2018-03-22 12:15:06 +00:00
|
|
|
};
|
2017-11-15 12:39:33 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->remove(path, version, std::move(callback));
|
2017-11-15 12:39:33 +00:00
|
|
|
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperRemove);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return future;
|
|
|
|
}
|
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
std::future<ZooKeeperImpl::ZooKeeper::MultiResponse> ZooKeeper::tryAsyncMulti(const Requests & ops)
|
2017-08-09 21:09:44 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
auto promise = std::make_shared<std::promise<ZooKeeperImpl::ZooKeeper::MultiResponse>>();
|
|
|
|
auto future = promise->get_future();
|
2017-08-09 21:09:44 +00:00
|
|
|
|
2018-03-23 23:15:14 +00:00
|
|
|
auto callback = [promise](const ZooKeeperImpl::ZooKeeper::MultiResponse & response) mutable
|
2017-08-09 21:09:44 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
promise->set_value(response);
|
2018-03-22 12:15:06 +00:00
|
|
|
};
|
2017-08-09 21:09:44 +00:00
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
impl->multi(ops, std::move(callback));
|
2017-08-09 21:09:44 +00:00
|
|
|
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperMulti);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return future;
|
|
|
|
}
|
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
std::future<ZooKeeperImpl::ZooKeeper::MultiResponse> ZooKeeper::asyncMulti(const Requests & ops)
|
2017-08-09 21:09:44 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
auto promise = std::make_shared<std::promise<ZooKeeperImpl::ZooKeeper::MultiResponse>>();
|
|
|
|
auto future = promise->get_future();
|
2017-08-09 21:09:44 +00:00
|
|
|
|
2018-03-23 23:15:14 +00:00
|
|
|
auto callback = [promise](const ZooKeeperImpl::ZooKeeper::MultiResponse & response) mutable
|
2018-03-22 12:15:06 +00:00
|
|
|
{
|
|
|
|
if (response.error)
|
2018-03-23 23:15:14 +00:00
|
|
|
promise->set_exception(std::make_exception_ptr(KeeperException(response.error)));
|
2018-03-22 12:15:06 +00:00
|
|
|
else
|
2018-03-23 23:15:14 +00:00
|
|
|
promise->set_value(response);
|
2018-03-22 12:15:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
impl->multi(ops, std::move(callback));
|
|
|
|
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperMulti);
|
|
|
|
ProfileEvents::increment(ProfileEvents::ZooKeeperTransactions);
|
|
|
|
return future;
|
2017-08-09 21:09:44 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 22:37:50 +00:00
|
|
|
|
2018-03-25 00:56:08 +00:00
|
|
|
size_t KeeperMultiException::getFailedOpIndex(int32_t code, const Responses & responses) const
|
2018-01-19 22:37:50 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
if (responses.empty())
|
|
|
|
throw DB::Exception("Responses for multi transaction is empty", DB::ErrorCodes::LOGICAL_ERROR);
|
2018-01-19 22:37:50 +00:00
|
|
|
|
2018-03-23 23:15:14 +00:00
|
|
|
for (size_t index = 0, size = responses.size(); index < size; ++index)
|
|
|
|
if (responses[index]->error)
|
2018-01-19 22:37:50 +00:00
|
|
|
return index;
|
|
|
|
|
2018-03-25 00:36:35 +00:00
|
|
|
if (!isUserError(code))
|
|
|
|
throw DB::Exception("There are no failed OPs because '" + ZooKeeper::error2string(code) + "' is not valid response code for that",
|
2018-03-23 23:15:14 +00:00
|
|
|
DB::ErrorCodes::LOGICAL_ERROR);
|
2018-01-19 22:37:50 +00:00
|
|
|
|
|
|
|
throw DB::Exception("There is no failed OpResult", DB::ErrorCodes::LOGICAL_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-23 23:15:14 +00:00
|
|
|
KeeperMultiException::KeeperMultiException(int32_t code, const Requests & requests, const Responses & responses)
|
2018-03-25 00:56:08 +00:00
|
|
|
: KeeperException("Transaction failed at op #" + std::to_string(getFailedOpIndex(code, responses)), code),
|
2018-03-25 00:36:35 +00:00
|
|
|
requests(requests), responses(responses)
|
2018-03-23 23:15:14 +00:00
|
|
|
{
|
|
|
|
}
|
2018-03-13 20:36:22 +00:00
|
|
|
|
2018-03-24 20:00:16 +00:00
|
|
|
std::string KeeperMultiException::getPathForFirstFailedOp() const
|
|
|
|
{
|
|
|
|
return requests[failed_op_index]->getPath();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-03-22 12:15:06 +00:00
|
|
|
void KeeperMultiException::check(int32_t code, const Requests & requests, const Responses & responses)
|
2018-03-13 20:36:22 +00:00
|
|
|
{
|
2018-03-23 23:15:14 +00:00
|
|
|
if (!code)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (isUserError(code))
|
|
|
|
throw KeeperMultiException(code, requests, responses);
|
2018-03-13 20:36:22 +00:00
|
|
|
else
|
|
|
|
throw KeeperException(code);
|
|
|
|
}
|
|
|
|
|
2018-03-24 00:45:04 +00:00
|
|
|
|
|
|
|
RequestPtr makeCreateRequest(const std::string & path, const std::string & data, int create_mode)
|
|
|
|
{
|
|
|
|
auto request = std::make_shared<CreateRequest>();
|
|
|
|
request->path = path;
|
|
|
|
request->data = data;
|
|
|
|
request->is_ephemeral = create_mode == CreateMode::Ephemeral || create_mode == CreateMode::EphemeralSequential;
|
|
|
|
request->is_sequential = create_mode == CreateMode::PersistentSequential || create_mode == CreateMode::EphemeralSequential;
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
|
|
|
RequestPtr makeRemoveRequest(const std::string & path, int version)
|
|
|
|
{
|
|
|
|
auto request = std::make_shared<RemoveRequest>();
|
|
|
|
request->path = path;
|
|
|
|
request->version = version;
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
2018-03-24 01:00:12 +00:00
|
|
|
RequestPtr makeSetRequest(const std::string & path, const std::string & data, int version)
|
2018-03-24 00:45:04 +00:00
|
|
|
{
|
|
|
|
auto request = std::make_shared<SetRequest>();
|
|
|
|
request->path = path;
|
|
|
|
request->data = data;
|
2018-03-24 01:00:12 +00:00
|
|
|
request->version = version;
|
2018-03-24 00:45:04 +00:00
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
|
|
|
RequestPtr makeCheckRequest(const std::string & path, int version)
|
|
|
|
{
|
|
|
|
auto request = std::make_shared<CheckRequest>();
|
|
|
|
request->path = path;
|
|
|
|
request->version = version;
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
2014-03-07 17:57:53 +00:00
|
|
|
}
|