1#pragma once
2
3#include "ZooKeeperHolder.h"
4#include <common/logger_useful.h>
5#include <Common/Exception.h>
6
7namespace zkutil
8{
9 class Lock
10 {
11 public:
12 /// lock_prefix - относительный путь до блокировки в ZK. Начинается со слеша
13 /// lock_name - имя ноды блокировки в ZK
14 Lock(
15 zkutil::ZooKeeperHolderPtr zookeeper_holder_,
16 const std::string & lock_prefix_,
17 const std::string & lock_name_,
18 const std::string & lock_message_ = "",
19 bool create_parent_path_ = false)
20 :
21 zookeeper_holder(zookeeper_holder_),
22 lock_path(lock_prefix_ + "/" + lock_name_),
23 lock_message(lock_message_),
24 log(&Logger::get("zkutil::Lock"))
25 {
26 auto zookeeper = zookeeper_holder->getZooKeeper();
27 if (create_parent_path_)
28 zookeeper->createAncestors(lock_prefix_);
29
30 zookeeper->createIfNotExists(lock_prefix_, "");
31 }
32
33 Lock(const Lock &) = delete;
34 Lock(Lock && lock) = default;
35 Lock & operator=(const Lock &) = delete;
36
37 ~Lock()
38 {
39 try
40 {
41 unlock();
42 }
43 catch (...)
44 {
45 DB::tryLogCurrentException(__PRETTY_FUNCTION__);
46 }
47 }
48
49 enum Status
50 {
51 UNLOCKED,
52 LOCKED_BY_ME,
53 LOCKED_BY_OTHER,
54 };
55
56 /// проверяет создана ли эфемерная нода и кто ее владелец.
57 Status tryCheck() const;
58
59 void unlock();
60 void unlockAssumeLockNodeRemovedManually();
61
62 bool tryLock();
63
64 /// путь к ноде блокировки в zookeeper
65 const std::string & getPath() { return lock_path; }
66
67 private:
68 zkutil::ZooKeeperHolderPtr zookeeper_holder;
69 /// пока храним указатель на хендлер, никто не может переиницализировать сессию с zookeeper
70 using ZooKeeperHandler = zkutil::ZooKeeperHolder::UnstorableZookeeperHandler;
71 std::unique_ptr<ZooKeeperHandler> locked;
72
73 std::string lock_path;
74 std::string lock_message;
75 Logger * log;
76
77 };
78}
79