ClickHouse/dbms/src/Common/ZooKeeper/ZooKeeperNodeCache.h
Alexey Zatelepin 601a6af0ec fix ZooKeeperNodeCache becoming unusable after SessionExpired event #2947 #3891
Previously after a SessionExpired event the context->zookeeper field was
reinitialized with the old expired ZooKeeper instance. This led to inability
to get new paths. Better not cache the ZooKeeper instance and get it at the
start of each request.
2018-12-26 20:27:25 +03:00

66 lines
1.6 KiB
C++

#pragma once
#include <unordered_map>
#include <unordered_set>
#include <mutex>
#include <memory>
#include <optional>
#include <Poco/Event.h>
#include "ZooKeeper.h"
#include "Common.h"
namespace DB
{
namespace ErrorCodes
{
extern const int NO_ZOOKEEPER;
}
}
namespace zkutil
{
/// This class allows querying the contents of ZooKeeper nodes and caching the results.
/// Watches are set for cached nodes and for nodes that were nonexistent at the time of query.
/// After a watch fires, the callback or event that was passed by the user is notified.
///
/// NOTE: methods of this class are not thread-safe.
///
/// Intended use case: if you need one thread to watch changes in several nodes.
/// If instead you use simple a watch event for this, watches will accumulate for nodes that do not change
/// or change rarely.
class ZooKeeperNodeCache
{
public:
ZooKeeperNodeCache(GetZooKeeper get_zookeeper);
ZooKeeperNodeCache(const ZooKeeperNodeCache &) = delete;
ZooKeeperNodeCache(ZooKeeperNodeCache &&) = default;
struct ZNode
{
bool exists = false;
std::string contents;
Coordination::Stat stat;
};
ZNode get(const std::string & path, EventPtr watch_event);
ZNode get(const std::string & path, Coordination::WatchCallback watch_callback);
private:
GetZooKeeper get_zookeeper;
struct Context
{
std::mutex mutex;
std::unordered_set<std::string> invalidated_paths;
bool all_paths_invalidated = false;
};
std::shared_ptr<Context> context;
std::unordered_map<std::string, ZNode> path_to_cached_znode;
};
}