#pragma once #include #include #include namespace zkutil { class Lock { public: /// lock_prefix - относительный путь до блокировки в ZK. Начинается со слеша /// lock_name - имя ноды блокировки в ZK Lock( zkutil::ZooKeeperHolderPtr zookeeper_holder_, const std::string & lock_prefix_, const std::string & lock_name_, const std::string & lock_message_ = "", bool create_parent_path_ = false) : zookeeper_holder(zookeeper_holder_), lock_path(lock_prefix_ + "/" + lock_name_), lock_message(lock_message_), log(&Logger::get("zkutil::Lock")) { auto zookeeper = zookeeper_holder->getZooKeeper(); if (create_parent_path_) zookeeper->createAncestors(lock_prefix_); zookeeper->createIfNotExists(lock_prefix_, ""); } Lock(const Lock &) = delete; Lock(Lock && lock) = default; Lock & operator=(const Lock &) = delete; ~Lock() { try { unlock(); } catch (const zkutil::KeeperException & e) { DB::tryLogCurrentException(__PRETTY_FUNCTION__); } } enum Status { UNLOCKED, LOCKED_BY_ME, LOCKED_BY_OTHER, END }; std::string status2String(Status status); /// проверяет создана ли эфемерная нода и кто ее владелец. Status tryCheck() const; void unlock(); void unlockOrMoveIfFailed(std::vector & failed_to_unlock_locks); bool tryLock(); /// путь к ноде блокировки в zookeeper const std::string & getPath() { return lock_path; } private: zkutil::ZooKeeperHolderPtr zookeeper_holder; /// пока храним указатель на хендлер, никто не может переиницализировать сессию с zookeeper using ZooKeeperHandler = zkutil::ZooKeeperHolder::UnstorableZookeeperHandler; std::unique_ptr locked; std::string lock_path; std::string lock_message; Logger * log; }; }