libzkutil: added multi; many fixes. [#METR-10202]

This commit is contained in:
Michael Kolupaev 2014-03-07 23:18:48 +04:00
parent ee9345707f
commit 3411d3db64
4 changed files with 174 additions and 51 deletions

View File

@ -1,6 +1,6 @@
#pragma once
#include <Poco/Exception.h>
#include <zkutil/ZooKeeper.h>
#include <zkutil/Types.h>
namespace zkutil

View File

@ -0,0 +1,44 @@
#pragma once
#include <zookeeper/zookeeper.hh>
#include <Yandex/Common.h>
#include <boost/function.hpp>
#include <future>
namespace zkutil
{
namespace zk = org::apache::zookeeper;
namespace CreateMode = zk::CreateMode;
namespace ReturnCode = zk::ReturnCode;
namespace SessionState = zk::SessionState;
namespace WatchEvent = zk::WatchEvent;
typedef zk::data::Stat Stat;
typedef zk::data::ACL ACL;
typedef zk::Op Op;
typedef zk::OpResult OpResult;
typedef std::vector<ACL> ACLs;
typedef boost::ptr_vector<Op> Ops;
typedef boost::ptr_vector<OpResult> OpResults;
typedef std::shared_ptr<boost::ptr_vector<OpResult> > OpResultsPtr;
typedef std::vector<std::string> Strings;
typedef boost::function<void (WatchEvent::type event, SessionState::type state,
const std::string & path)> WatchFunction;
struct WatchEventInfo
{
WatchEvent::type event;
SessionState::type state;
std::string path;
WatchEventInfo() {}
WatchEventInfo(WatchEvent::type event_, SessionState::type state_, const std::string & path_)
: event(event_), state(state_), path(path_) {}
};
typedef std::future<WatchEventInfo> WatchFuture;
}

View File

@ -1,8 +1,6 @@
#pragma once
#include <zookeeper/zookeeper.hh>
#include <Yandex/Common.h>
#include <boost/function.hpp>
#include <future>
#include <zkutil/Types.h>
#include <zkutil/KeeperException.h>
namespace zkutil
@ -10,38 +8,10 @@ namespace zkutil
const UInt32 DEFAULT_SESSION_TIMEOUT = 30000;
namespace zk = org::apache::zookeeper;
namespace CreateMode = zk::CreateMode;
namespace ReturnCode = zk::ReturnCode;
namespace SessionState = zk::SessionState;
namespace WatchEvent = zk::WatchEvent;
typedef zk::data::Stat Stat;
typedef zk::data::ACL ACL;
typedef std::vector<ACL> ACLs;
typedef std::vector<std::string> Strings;
typedef boost::function<void (WatchEvent::type event, SessionState::type state,
const std::string & path)> WatchFunction;
struct WatchEventInfo
{
WatchEvent::type event;
SessionState::type state;
std::string path;
WatchEventInfo() {}
WatchEventInfo(WatchEvent::type event_, SessionState::type state_, const std::string & path_)
: event(event_), state(state_), path(path_) {}
};
typedef std::future<WatchEventInfo> WatchFuture;
/** Сессия в ZooKeeper. Интерфейс существенно отличается от обычного API ZooKeeper.
* Вместо callback-ов для watch-ей используются std::future.
* Методы с названиями, не начинающимися с try, бросают исключение при любой ошибке.
* Методы с названиями, начинающимися с try, не бросают исключение только при некторых видах ошибок.
* Методы с названиями, начинающимися с try, не бросают исключение только при перечисленных видах ошибок.
* Например, исключение бросается в любом случае, если сессия разорвалась или если не хватает прав или ресурсов.
*/
class ZooKeeper
@ -58,6 +28,8 @@ public:
void setDefaultACL(ACLs & acl);
ACLs getDefaultACL();
/** Создать znode. Используется ACL, выставленный вызовом setDefaultACL (по умолчанию, всем полный доступ).
* Если что-то пошло не так, бросить исключение.
*/
@ -86,19 +58,41 @@ public:
std::string get(const std::string & path, Stat * stat, WatchFuture * watch);
/// Возвращает false, если нет такой ноды. При остальных ошибках бросает исключение.
bool tryGet(const std::string & path, std::string & data, Stat * stat = nullptr, WatchFuture * watch = nullptr);
/** Не бросает исключение при следующих ошибках:
* - Такой ноды нет. В таком случае возвращает false.
*/
bool tryGet(const std::string & path, std::string & res, Stat * stat = nullptr, WatchFuture * watch = nullptr);
void set(const std::string & path, const std::string & data,
int32_t version = -1, Stat * stat = nullptr);
/** Не бросает исключение при следующих ошибках:
* - Такой ноды нет.
* - У ноды другая версия.
*/
ReturnCode::type trySet(const std::string & path, const std::string & data,
int32_t version = -1, Stat * stat = nullptr);
Strings getChildren(const std::string & path,
Stat * stat = nullptr,
WatchFuture * watch = nullptr);
/** Не бросает исключение при следующих ошибках:
* - Такой ноды нет. В таком случае возвращает false.
*/
bool tryGetChildren(const std::string & path, Strings & res,
Stat * stat = nullptr,
WatchFuture * watch = nullptr);
void close();
boost::ptr_vector<zk::OpResult> & multi(const boost::ptr_vector<zk::Op> & ops);
/** Транзакционно выполняет несколько операций. При любой ошибке бросает исключение.
*/
OpResultsPtr multi(const Ops & ops);
/** Бросает исключение только если какая-нибудь операция вернула "неожиданную" ошибку - такую ошибку,
* увидев которую соответствующий метод try* бросил бы исключение. */
OpResultsPtr tryMulti(const Ops & ops);
private:
friend struct StateWatch;

View File

@ -1,5 +1,4 @@
#include <zkutil/ZooKeeper.h>
#include <zkutil/KeeperException.h>
#include <boost/make_shared.hpp>
@ -73,6 +72,11 @@ void ZooKeeper::setDefaultACL(ACLs & acl)
default_acl = acl;
}
ACLs ZooKeeper::getDefaultACL()
{
return default_acl;
}
Strings ZooKeeper::getChildren(
const std::string & path, Stat * stat, WatchFuture * watch)
{
@ -84,6 +88,21 @@ Strings ZooKeeper::getChildren(
return res;
}
bool ZooKeeper::tryGetChildren(const std::string & path, Strings & res,
Stat * stat, WatchFuture * watch)
{
Stat s;
ReturnCode::type code = impl.getChildren(path, watchForFuture(watch), res, s);
if (!( code == ReturnCode::Ok ||
code == ReturnCode::NoNode))
throw KeeperException(code);
if (code == ReturnCode::NoNode)
return false;
if (stat)
*stat = s;
return true;
}
std::string ZooKeeper::create(const std::string & path, const std::string & data, CreateMode::type mode)
{
std::string res;
@ -98,8 +117,8 @@ ReturnCode::type ZooKeeper::tryCreate(const std::string & path, const std::strin
code == ReturnCode::NoNode ||
code == ReturnCode::NodeExists ||
code == ReturnCode::NoChildrenForEphemerals))
return code;
throw KeeperException(code);
throw KeeperException(code);
return code;
}
void ZooKeeper::remove(const std::string & path, int32_t version)
@ -107,11 +126,6 @@ void ZooKeeper::remove(const std::string & path, int32_t version)
CHECKED(impl.remove(path, version));
}
/** Не бросает исключение при следующих ошибках:
* - Такой ноды нет.
* - У ноды другая версия.
* - У ноды есть дети.
*/
ReturnCode::type ZooKeeper::tryRemove(const std::string & path, int32_t version)
{
ReturnCode::type code = impl.remove(path, version);
@ -119,19 +133,22 @@ ReturnCode::type ZooKeeper::tryRemove(const std::string & path, int32_t version)
code == ReturnCode::NoNode ||
code == ReturnCode::BadVersion ||
code == ReturnCode::NotEmpty))
return code;
throw KeeperException(code);
throw KeeperException(code);
return code;
}
bool ZooKeeper::exists(const std::string & path, Stat * stat, WatchFuture * watch)
{
Stat s;
ReturnCode::type code = impl.exists(path, watchForFuture(watch), s);
if (code != ReturnCode::Ok && code != ReturnCode::NoNode)
if (!( code == ReturnCode::Ok ||
code == ReturnCode::NoNode))
throw KeeperException(code);
if (code == ReturnCode::NoNode)
return false;
if (stat)
*stat = s;
return code == ReturnCode::Ok;
return true;
}
std::string ZooKeeper::get(const std::string & path, Stat * stat, WatchFuture * watch)
@ -144,10 +161,13 @@ std::string ZooKeeper::get(const std::string & path, Stat * stat, WatchFuture *
return res;
}
bool ZooKeeper::tryGet(const std::string & path, std::string & data, Stat * stat, WatchFuture * watch)
bool ZooKeeper::tryGet(const std::string & path, std::string & res, Stat * stat, WatchFuture * watch)
{
Stat s;
ReturnCode::type code = impl.get(path, watchForFuture(watch), data, s);
ReturnCode::type code = impl.get(path, watchForFuture(watch), res, s);
if (!( code == ReturnCode::Ok ||
code == ReturnCode::NoNode))
throw KeeperException(code);
if (code == ReturnCode::NoNode)
return false;
if (stat)
@ -163,6 +183,71 @@ void ZooKeeper::set(const std::string & path, const std::string & data, int32_t
*stat = s;
}
ReturnCode::type ZooKeeper::trySet(const std::string & path, const std::string & data,
int32_t version, Stat * stat)
{
Stat s;
ReturnCode::type code = impl.set(path, data, version, s);
if (!( code == ReturnCode::Ok ||
code == ReturnCode::NoNode ||
code == ReturnCode::BadVersion))
throw KeeperException(code);
if (stat)
*stat = s;
return code;
}
OpResultsPtr ZooKeeper::multi(const Ops & ops)
{
OpResultsPtr res = std::make_shared<OpResults>();
CHECKED(impl.multi(ops, *res));
for (size_t i = 0; i < res->size(); ++i)
{
if ((*res)[i].getReturnCode() != ReturnCode::Ok)
throw KeeperException((*res)[i].getReturnCode());
}
return res;
}
OpResultsPtr ZooKeeper::tryMulti(const Ops & ops)
{
OpResultsPtr res = std::make_shared<OpResults>();
CHECKED(impl.multi(ops, *res));
for (size_t i = 0; i < res->size(); ++i)
{
ReturnCode::type code = (*res)[i].getReturnCode();
if (code != ReturnCode::Ok)
{
bool ok = false;
switch (ops[i].getType())
{
case zk::OpCode::Create:
ok |= code == ReturnCode::NoNode;
ok |= code == ReturnCode::NodeExists;
ok |= code == ReturnCode::NoChildrenForEphemerals;
break;
case zk::OpCode::Remove:
ok |= code == ReturnCode::NoNode;
ok |= code == ReturnCode::BadVersion;
ok |= code == ReturnCode::NotEmpty;
break;
case zk::OpCode::SetData:
case zk::OpCode::Check:
ok |= code == ReturnCode::NoNode;
ok |= code == ReturnCode::BadVersion;
break;
default:
throw KeeperException("Unexpected op type");
}
if (!ok)
throw KeeperException(code);
}
}
return res;
}
void ZooKeeper::close()
{
CHECKED(impl.close());