libzkutil: working. [#METR-10202]

This commit is contained in:
Michael Kolupaev 2014-03-07 21:57:53 +04:00
parent 5ceab75c8a
commit 7ea73ab849
4 changed files with 214 additions and 14 deletions

View File

@ -11,9 +11,9 @@ class KeeperException : public Poco::Exception
public:
KeeperException(const std::string & msg) : Poco::Exception(msg), code(ReturnCode::Ok) {}
KeeperException(const std::string & msg, ReturnCode::type code_)
: Poco::Exception(msg + " (" + ReturnCode::toString(code) + ")"), code(code_) {}
: Poco::Exception(msg + " (" + ReturnCode::toString(code_) + ")"), code(code_) {}
KeeperException(ReturnCode::type code_)
: Poco::Exception(ReturnCode::toString(code)), code(code_) {}
: Poco::Exception(ReturnCode::toString(code_)), code(code_) {}
ReturnCode::type code;
};

View File

@ -49,7 +49,11 @@ class ZooKeeper
public:
ZooKeeper(const std::string & hosts, int32_t sessionTimeoutMs = DEFAULT_SESSION_TIMEOUT, WatchFunction * watch = nullptr);
/// Возвращает true, если сессия навсегда завершена.
/** Возвращает true, если сессия навсегда завершена.
* Это возможно только если соединение было установлено, а потом разорвалось. Это достаточно редкая ситуация.
* С другой стороны, если, например, указан неправильный сервер или порт, попытки соединения будут продолжаться бесконечно,
* disconnected() будет возвращать false, и все вызовы будут выбрасывать исключение ConnectionLoss.
*/
bool disconnected();
void setDefaultACL(ACLs & acl);
@ -80,7 +84,7 @@ public:
bool exists(const std::string & path, Stat * stat = nullptr, WatchFuture * watch = nullptr);
std::string get(const std::string & path, WatchFuture * watch, Stat * stat);
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);
@ -92,6 +96,8 @@ public:
Stat * stat = nullptr,
WatchFuture * watch = nullptr);
void close();
boost::ptr_vector<zk::OpResult> & multi(const boost::ptr_vector<zk::Op> & ops);
private:

View File

@ -3,7 +3,7 @@
#include <boost/make_shared.hpp>
#define CHECKED(x) { ReturnCode::type code = x; if (code) throw KeeperException(code); }
#define CHECKED(x) { ReturnCode::type code = x; if (code != ReturnCode::Ok) throw KeeperException(code); }
namespace zkutil
{
@ -73,7 +73,7 @@ void ZooKeeper::setDefaultACL(ACLs & acl)
default_acl = acl;
}
std::vector<std::string> ZooKeeper::getChildren(
Strings ZooKeeper::getChildren(
const std::string & path, Stat * stat, WatchFuture * watch)
{
Stat s;
@ -84,5 +84,88 @@ std::vector<std::string> ZooKeeper::getChildren(
return res;
}
std::string ZooKeeper::create(const std::string & path, const std::string & data, CreateMode::type mode)
{
std::string res;
CHECKED(impl.create(path, data, default_acl, mode, res));
return res;
}
ReturnCode::type ZooKeeper::tryCreate(const std::string & path, const std::string & data, CreateMode::type mode, std::string & pathCreated)
{
ReturnCode::type code = impl.create(path, data, default_acl, mode, pathCreated);
if (!( code == ReturnCode::Ok ||
code == ReturnCode::NoNode ||
code == ReturnCode::NodeExists ||
code == ReturnCode::NoChildrenForEphemerals))
return code;
throw KeeperException(code);
}
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);
if (!( code == ReturnCode::Ok ||
code == ReturnCode::NoNode ||
code == ReturnCode::BadVersion ||
code == ReturnCode::NotEmpty))
return code;
throw KeeperException(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)
throw KeeperException(code);
if (stat)
*stat = s;
return code == ReturnCode::Ok;
}
std::string ZooKeeper::get(const std::string & path, Stat * stat, WatchFuture * watch)
{
std::string res;
Stat s;
CHECKED(impl.get(path, watchForFuture(watch), res, s));
if (stat)
*stat = s;
return res;
}
bool ZooKeeper::tryGet(const std::string & path, std::string & data, Stat * stat, WatchFuture * watch)
{
Stat s;
ReturnCode::type code = impl.get(path, watchForFuture(watch), data, s);
if (code == ReturnCode::NoNode)
return false;
if (stat)
*stat = s;
return true;
}
void ZooKeeper::set(const std::string & path, const std::string & data, int32_t version, Stat * stat)
{
Stat s;
CHECKED(impl.set(path, data, version, s));
if (stat)
*stat = s;
}
void ZooKeeper::close()
{
CHECKED(impl.close());
}
}

View File

@ -3,6 +3,32 @@
#include <iostream>
#include <readline/readline.h>
#include <sstream>
#include <Poco/ConsoleChannel.h>
#include <Yandex/logger_useful.h>
void printStat(const zkutil::Stat & s)
{
std::cout << "Stat:\n";
std::cout << " czxid: " << s.getczxid() << '\n';
std::cout << " mzxid: " << s.getmzxid() << '\n';
std::cout << " ctime: " << s.getctime() << '\n';
std::cout << " mtime: " << s.getmtime() << '\n';
std::cout << " version: " << s.getversion() << '\n';
std::cout << " cversion: " << s.getcversion() << '\n';
std::cout << " aversion: " << s.getaversion() << '\n';
std::cout << " ephemeralOwner: " << s.getephemeralOwner() << '\n';
std::cout << " dataLength: " << s.getdataLength() << '\n';
std::cout << " numChildren: " << s.getnumChildren() << '\n';
std::cout << " pzxid: " << s.getpzxid() << std::endl;
}
void waitForWatch(zkutil::WatchFuture & future)
{
std::cout << "waiting for watch" << std::endl;
zkutil::WatchEventInfo res = future.get();
std::cout << "event: " << zkutil::WatchEvent::toString(res.event) << std::endl;
}
int main(int argc, char ** argv)
@ -15,42 +41,127 @@ int main(int argc, char ** argv)
return 2;
}
Logger::root().setChannel(new Poco::ConsoleChannel(std::cout));
Logger::root().setLevel("trace");
zkutil::ZooKeeper zk(argv[1]);
while (char * line = readline(":3 "))
{
if (zk.disconnected())
{
std::cerr << "Disconnected" << std::endl;
break;
}
try
{
std::stringstream ss(line);
std::string cmd;
if (!(ss >> cmd))
continue;
ss >> cmd;
if (cmd == "q" || cmd == "quit" || cmd == "exit" || cmd == ":q")
break;
if (cmd == "help")
{
std::cout << "commands: q, ls (not yet: stat, get, set, create, remove)" << std::endl;
continue;
}
std::string path;
ss >> path;
if (cmd == "ls")
{
std::vector<std::string> v = zk.getChildren(path);
std::string w;
ss >> w;
bool watch = w == "w";
zkutil::WatchFuture future;
std::vector<std::string> v = zk.getChildren(path, nullptr, watch ? &future : nullptr);
for (size_t i = 0; i < v.size(); ++i)
{
std::cout << v[i] << std::endl;
}
if (watch)
waitForWatch(future);
}
else if (cmd == "create")
{
std::string data, mode;
ss >> data >> mode;
zkutil::CreateMode::type m;
if (mode == "p")
m = zkutil::CreateMode::Persistent;
else if (mode == "ps")
m = zkutil::CreateMode::PersistentSequential;
else if (mode == "e")
m = zkutil::CreateMode::Ephemeral;
else if (mode == "es")
m = zkutil::CreateMode::EphemeralSequential;
else
{
std::cout << "Bad create mode" << std::endl;
continue;
}
std::cout << zk.create(path, data, m) << std::endl;
}
else if (cmd == "remove")
{
zk.remove(path);
}
else if (cmd == "exists")
{
std::string w;
ss >> w;
bool watch = w == "w";
zkutil::WatchFuture future;
zkutil::Stat stat;
bool e = zk.exists(path, &stat, watch ? &future : nullptr);
if (e)
printStat(stat);
else
std::cout << path << " does not exist" << std::endl;
if (watch)
waitForWatch(future);
}
else if (cmd == "get")
{
std::string w;
ss >> w;
bool watch = w == "w";
zkutil::WatchFuture future;
zkutil::Stat stat;
std::string data = zk.get(path, &stat, watch ? &future : nullptr);
std::cout << "Data: " << data << std::endl;
printStat(stat);
if (watch)
waitForWatch(future);
}
else if (cmd == "set")
{
std::string data;
int version = -1;
ss >> data >> version;
zkutil::Stat stat;
zk.set(path, data, version, &stat);
printStat(stat);
}
else if (cmd != "")
{
std::cout << "commands:\n";
std::cout << " q\n";
std::cout << " ls path [w]\n";
std::cout << " create path data (p|ps|e|es)\n";
std::cout << " remove path\n";
std::cout << " exists path [w]\n";
std::cout << " get path [w]\n";
std::cout << " set path data [version]" << std::endl;
continue;
}
}
catch (zkutil::KeeperException & e)
{
std::cerr << "KeeperException: " << e.displayText() << std::endl;
}
}
zk.close();
}
catch (zkutil::KeeperException & e)
{