1 | #pragma once |
2 | |
3 | #include <unordered_map> |
4 | #include <unordered_set> |
5 | #include <mutex> |
6 | #include <memory> |
7 | #include <optional> |
8 | #include <Poco/Event.h> |
9 | #include "ZooKeeper.h" |
10 | #include "Common.h" |
11 | |
12 | namespace DB |
13 | { |
14 | namespace ErrorCodes |
15 | { |
16 | extern const int NO_ZOOKEEPER; |
17 | } |
18 | } |
19 | |
20 | namespace zkutil |
21 | { |
22 | |
23 | /// This class allows querying the contents of ZooKeeper nodes and caching the results. |
24 | /// Watches are set for cached nodes and for nodes that were nonexistent at the time of query. |
25 | /// After a watch fires, the callback or event that was passed by the user is notified. |
26 | /// |
27 | /// NOTE: methods of this class are not thread-safe. |
28 | /// |
29 | /// Intended use case: if you need one thread to watch changes in several nodes. |
30 | /// If instead you use simple a watch event for this, watches will accumulate for nodes that do not change |
31 | /// or change rarely. |
32 | class ZooKeeperNodeCache |
33 | { |
34 | public: |
35 | ZooKeeperNodeCache(GetZooKeeper get_zookeeper); |
36 | |
37 | ZooKeeperNodeCache(const ZooKeeperNodeCache &) = delete; |
38 | ZooKeeperNodeCache(ZooKeeperNodeCache &&) = default; |
39 | |
40 | struct ZNode |
41 | { |
42 | bool exists = false; |
43 | std::string contents; |
44 | Coordination::Stat stat{}; |
45 | }; |
46 | |
47 | ZNode get(const std::string & path, EventPtr watch_event); |
48 | ZNode get(const std::string & path, Coordination::WatchCallback watch_callback); |
49 | |
50 | private: |
51 | GetZooKeeper get_zookeeper; |
52 | |
53 | struct Context |
54 | { |
55 | std::mutex mutex; |
56 | std::unordered_set<std::string> invalidated_paths; |
57 | bool all_paths_invalidated = false; |
58 | }; |
59 | |
60 | std::shared_ptr<Context> context; |
61 | |
62 | std::unordered_map<std::string, ZNode> path_to_cached_znode; |
63 | }; |
64 | |
65 | } |
66 | |