1#pragma once
2
3#include "ZooKeeper.h"
4#include <mutex>
5#include <boost/noncopyable.hpp>
6
7namespace zkutil
8{
9class Lock;
10
11class ZooKeeperHolder : public boost::noncopyable
12{
13 friend class zkutil::Lock;
14
15protected:
16 class UnstorableZookeeperHandler;
17
18public:
19 ZooKeeperHolder() = default;
20
21 /// вызывать из одного потока - не thread safe
22 template <typename... Args>
23 void init(Args &&... args);
24 /// был ли класс инициализирован
25 bool isInitialized() const { return ptr != nullptr; }
26
27 /// Workaround for zkutil::Lock
28 void initFromInstance(const ZooKeeper::Ptr & zookeeper_ptr);
29
30 UnstorableZookeeperHandler getZooKeeper();
31 bool replaceZooKeeperSessionToNewOne();
32
33 bool isSessionExpired() const;
34
35protected:
36 /** Хендлер для подсчета количества используемых ссылок на ZooKeeper
37 *
38 * Запрещается переинициализировать ZooKeeper пока, хранится хотя бы один хендлер на него.
39 * Большинство классов должны хранить хендлер на стеке и не хранить как член класса.
40 * Т.е. хранить holder и запрашивать хендлер перед каждым использованием.
41 * Поэтому класс специально объявлен, как protected.
42 *
43 * Исключение - классы, работающие с эфимерными нодами. Пример: zkutil::Lock
44 *
45 * Как использовать:
46 * auto zookeeper = zookeeper_holder->getZooKeeper();
47 * zookeeper->get(path);
48 */
49 class UnstorableZookeeperHandler
50 {
51 public:
52 UnstorableZookeeperHandler(ZooKeeper::Ptr zk_ptr_);
53
54 explicit operator bool() const { return bool(zk_ptr); }
55 bool operator==(std::nullptr_t) const { return zk_ptr == nullptr; }
56 bool operator!=(std::nullptr_t) const { return !(*this == nullptr); }
57
58 /// в случае nullptr методы разыменования кидают исключение,
59 /// с более подробным текстом, чем просто nullptr
60 ZooKeeper * operator->();
61 const ZooKeeper * operator->() const;
62 ZooKeeper & operator*();
63 const ZooKeeper & operator*() const;
64
65 private:
66 ZooKeeper::Ptr zk_ptr;
67 };
68
69private:
70 mutable std::mutex mutex;
71 ZooKeeper::Ptr ptr;
72
73 Logger * log = &Logger::get("ZooKeeperHolder");
74
75 static std::string nullptr_exception_message;
76};
77
78template <typename... Args>
79void ZooKeeperHolder::init(Args &&... args)
80{
81 ptr = std::make_shared<ZooKeeper>(std::forward<Args>(args)...);
82}
83
84using ZooKeeperHolderPtr = std::shared_ptr<ZooKeeperHolder>;
85
86}
87