From 9e2422d5e3608f979662e64d772bb1d229bc82ab Mon Sep 17 00:00:00 2001 From: Michael Kolupaev Date: Tue, 22 Apr 2014 15:19:56 +0400 Subject: [PATCH] zkutil: not blocking calls if session is expired. [#METR-10202] --- libs/libzkutil/include/zkutil/ZooKeeper.h | 6 ++++++ libs/libzkutil/src/ZooKeeper.cpp | 25 +++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/libs/libzkutil/include/zkutil/ZooKeeper.h b/libs/libzkutil/include/zkutil/ZooKeeper.h index 042d6b1831d..55abf4401e0 100644 --- a/libs/libzkutil/include/zkutil/ZooKeeper.h +++ b/libs/libzkutil/include/zkutil/ZooKeeper.h @@ -130,6 +130,12 @@ private: SessionState::type session_state; void stateChanged(WatchEvent::type event, SessionState::type state, const std::string& path); + + /** Бросает исключение, если сессия истекла. Почему-то zkcpp этого не делает, а вместо этого виснет (смотри zkcpp_expiration_test). + * Не очень надежно: возможно, вызов к zkcpp все же может повиснуть, если между проверкой и вызовом состояние успеет поменяться. + * Если это окажется проблемой, возможно, стоит избавиться от zkcpp. + */ + void checkNotExpired(); }; diff --git a/libs/libzkutil/src/ZooKeeper.cpp b/libs/libzkutil/src/ZooKeeper.cpp index c1b5ad91b8a..f332265dc73 100644 --- a/libs/libzkutil/src/ZooKeeper.cpp +++ b/libs/libzkutil/src/ZooKeeper.cpp @@ -118,6 +118,12 @@ void ZooKeeper::stateChanged(WatchEvent::type event, SessionState::type state, c (*state_watch)(event, state, path); } +void ZooKeeper::checkNotExpired() +{ + if (disconnected()) + throw KeeperException(ReturnCode::SessionExpired); +} + bool ZooKeeper::disconnected() { Poco::ScopedLock lock(mutex); @@ -142,6 +148,7 @@ ACLs ZooKeeper::getDefaultACL() Strings ZooKeeper::getChildren( const std::string & path, Stat * stat, WatchFuture * watch) { + checkNotExpired(); Stat s; Strings res; CHECKED(impl.getChildren(path, watchForFuture(watch), res, s), path); @@ -153,6 +160,7 @@ Strings ZooKeeper::getChildren( bool ZooKeeper::tryGetChildren(const std::string & path, Strings & res, Stat * stat, WatchFuture * watch) { + checkNotExpired(); Stat s; ReturnCode::type code = impl.getChildren(path, watchForFuture(watch), res, s); if (!( code == ReturnCode::Ok || @@ -167,18 +175,18 @@ bool ZooKeeper::tryGetChildren(const std::string & path, Strings & res, std::string ZooKeeper::create(const std::string & path, const std::string & data, CreateMode::type mode) { - Poco::ScopedLock lock(mutex); + checkNotExpired(); std::string res; - CHECKED(impl.create(path, data, default_acl, mode, res), path); + CHECKED(impl.create(path, data, getDefaultACL(), mode, res), path); return res; } ReturnCode::type ZooKeeper::tryCreate(const std::string & path, const std::string & data, CreateMode::type mode, std::string & pathCreated) { - Poco::ScopedLock lock(mutex); + checkNotExpired(); - ReturnCode::type code = impl.create(path, data, default_acl, mode, pathCreated); + ReturnCode::type code = impl.create(path, data, getDefaultACL(), mode, pathCreated); if (!( code == ReturnCode::Ok || code == ReturnCode::NoNode || code == ReturnCode::NodeExists || @@ -189,11 +197,13 @@ ReturnCode::type ZooKeeper::tryCreate(const std::string & path, const std::strin void ZooKeeper::remove(const std::string & path, int32_t version) { + checkNotExpired(); CHECKED(impl.remove(path, version), path); } ReturnCode::type ZooKeeper::tryRemove(const std::string & path, int32_t version) { + checkNotExpired(); ReturnCode::type code = impl.remove(path, version); if (!( code == ReturnCode::Ok || code == ReturnCode::NoNode || @@ -205,6 +215,7 @@ ReturnCode::type ZooKeeper::tryRemove(const std::string & path, int32_t version) bool ZooKeeper::exists(const std::string & path, Stat * stat, WatchFuture * watch) { + checkNotExpired(); Stat s; ReturnCode::type code = impl.exists(path, watchForFuture(watch), s); if (!( code == ReturnCode::Ok || @@ -219,6 +230,7 @@ bool ZooKeeper::exists(const std::string & path, Stat * stat, WatchFuture * watc std::string ZooKeeper::get(const std::string & path, Stat * stat, WatchFuture * watch) { + checkNotExpired(); std::string res; Stat s; CHECKED(impl.get(path, watchForFuture(watch), res, s), path); @@ -229,6 +241,7 @@ std::string ZooKeeper::get(const std::string & path, Stat * stat, WatchFuture * bool ZooKeeper::tryGet(const std::string & path, std::string & res, Stat * stat, WatchFuture * watch) { + checkNotExpired(); Stat s; ReturnCode::type code = impl.get(path, watchForFuture(watch), res, s); if (!( code == ReturnCode::Ok || @@ -243,6 +256,7 @@ bool ZooKeeper::tryGet(const std::string & path, std::string & res, Stat * stat, void ZooKeeper::set(const std::string & path, const std::string & data, int32_t version, Stat * stat) { + checkNotExpired(); Stat s; CHECKED(impl.set(path, data, version, s), path); if (stat) @@ -252,6 +266,7 @@ void ZooKeeper::set(const std::string & path, const std::string & data, int32_t ReturnCode::type ZooKeeper::trySet(const std::string & path, const std::string & data, int32_t version, Stat * stat) { + checkNotExpired(); Stat s; ReturnCode::type code = impl.set(path, data, version, s); if (!( code == ReturnCode::Ok || @@ -265,6 +280,7 @@ ReturnCode::type ZooKeeper::trySet(const std::string & path, const std::string & OpResultsPtr ZooKeeper::multi(const Ops & ops) { + checkNotExpired(); OpResultsPtr res = std::make_shared(); CHECKED_WITHOUT_PATH(impl.multi(ops, *res)); for (size_t i = 0; i < res->size(); ++i) @@ -277,6 +293,7 @@ OpResultsPtr ZooKeeper::multi(const Ops & ops) ReturnCode::type ZooKeeper::tryMulti(const Ops & ops, OpResultsPtr * out_results) { + checkNotExpired(); OpResultsPtr results = std::make_shared(); ReturnCode::type code = impl.multi(ops, *results); if (out_results)