Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / ManagedLock.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #ifndef CEPH_LIBRBD_MANAGED_LOCK_H
5 #define CEPH_LIBRBD_MANAGED_LOCK_H
6
7 #include "include/int_types.h"
8 #include "include/Context.h"
9 #include "include/rados/librados.hpp"
10 #include "common/AsyncOpTracker.h"
11 #include "common/Mutex.h"
12 #include "cls/lock/cls_lock_types.h"
13 #include "librbd/watcher/Types.h"
14 #include "librbd/managed_lock/Types.h"
15 #include <list>
16 #include <string>
17 #include <utility>
18
19 class ContextWQ;
20
21 namespace librbd {
22
23 struct ImageCtx;
24
25 namespace managed_lock { struct Locker; }
26
27 template <typename ImageCtxT = librbd::ImageCtx>
28 class ManagedLock {
29 private:
30   typedef watcher::Traits<ImageCtxT> TypeTraits;
31   typedef typename TypeTraits::Watcher Watcher;
32
33 public:
34   static ManagedLock *create(librados::IoCtx& ioctx, ContextWQ *work_queue,
35                              const std::string& oid, Watcher *watcher,
36                              managed_lock::Mode mode,
37                              bool blacklist_on_break_lock,
38                              uint32_t blacklist_expire_seconds) {
39     return new ManagedLock(ioctx, work_queue, oid, watcher, mode,
40                            blacklist_on_break_lock, blacklist_expire_seconds);
41   }
42   void destroy() {
43     delete this;
44   }
45
46   ManagedLock(librados::IoCtx& ioctx, ContextWQ *work_queue,
47               const std::string& oid, Watcher *watcher,
48               managed_lock::Mode mode, bool blacklist_on_break_lock,
49               uint32_t blacklist_expire_seconds);
50   virtual ~ManagedLock();
51
52   bool is_lock_owner() const;
53
54   void shut_down(Context *on_shutdown);
55   void acquire_lock(Context *on_acquired);
56   void try_acquire_lock(Context *on_acquired);
57   void release_lock(Context *on_released);
58   void reacquire_lock(Context *on_reacquired = nullptr);
59   void get_locker(managed_lock::Locker *locker, Context *on_finish);
60   void break_lock(const managed_lock::Locker &locker, bool force_break_lock,
61                   Context *on_finish);
62
63   int assert_header_locked();
64
65   bool is_shutdown() const {
66     Mutex::Locker l(m_lock);
67     return is_state_shutdown();
68   }
69
70 protected:
71   mutable Mutex m_lock;
72
73   inline void set_state_uninitialized() {
74     assert(m_lock.is_locked());
75     assert(m_state == STATE_UNLOCKED);
76     m_state = STATE_UNINITIALIZED;
77   }
78   inline void set_state_initializing() {
79     assert(m_lock.is_locked());
80     assert(m_state == STATE_UNINITIALIZED);
81     m_state = STATE_INITIALIZING;
82   }
83   inline void set_state_unlocked() {
84     assert(m_lock.is_locked());
85     assert(m_state == STATE_INITIALIZING || m_state == STATE_RELEASING);
86     m_state = STATE_UNLOCKED;
87   }
88   inline void set_state_waiting_for_lock() {
89     assert(m_lock.is_locked());
90     assert(m_state == STATE_ACQUIRING);
91     m_state = STATE_WAITING_FOR_LOCK;
92   }
93   inline void set_state_post_acquiring() {
94     assert(m_lock.is_locked());
95     assert(m_state == STATE_ACQUIRING);
96     m_state = STATE_POST_ACQUIRING;
97   }
98
99   bool is_state_shutdown() const;
100   inline bool is_state_acquiring() const {
101     assert(m_lock.is_locked());
102     return m_state == STATE_ACQUIRING;
103   }
104   inline bool is_state_post_acquiring() const {
105     assert(m_lock.is_locked());
106     return m_state == STATE_POST_ACQUIRING;
107   }
108   inline bool is_state_releasing() const {
109     assert(m_lock.is_locked());
110     return m_state == STATE_RELEASING;
111   }
112   inline bool is_state_pre_releasing() const {
113     assert(m_lock.is_locked());
114     return m_state == STATE_PRE_RELEASING;
115   }
116   inline bool is_state_locked() const {
117     assert(m_lock.is_locked());
118     return m_state == STATE_LOCKED;
119   }
120   inline bool is_state_waiting_for_lock() const {
121     assert(m_lock.is_locked());
122     return m_state == STATE_WAITING_FOR_LOCK;
123   }
124
125   inline bool is_action_acquire_lock() const {
126     assert(m_lock.is_locked());
127     return get_active_action() == ACTION_ACQUIRE_LOCK;
128   }
129
130   virtual void shutdown_handler(int r, Context *on_finish);
131   virtual void pre_acquire_lock_handler(Context *on_finish);
132   virtual void post_acquire_lock_handler(int r, Context *on_finish);
133   virtual void pre_release_lock_handler(bool shutting_down,
134                                         Context *on_finish);
135   virtual void post_release_lock_handler(bool shutting_down, int r,
136                                           Context *on_finish);
137   virtual void post_reacquire_lock_handler(int r, Context *on_finish);
138
139   void execute_next_action();
140
141 private:
142   /**
143    * @verbatim
144    *
145    *       <start>
146    *          |
147    *          |
148    *          v           (acquire_lock)
149    *       UNLOCKED -----------------------------------------> ACQUIRING
150    *          ^                                                    |
151    *          |                                                    |
152    *      RELEASING                                                |
153    *          |                                                    |
154    *          |                                                    |
155    *          |                    (release_lock)                  v
156    *    PRE_RELEASING <----------------------------------------- LOCKED
157    *
158    * <LOCKED state>
159    *    |
160    *    v
161    * REACQUIRING -------------------------------------> <finish>
162    *    .                                                 ^
163    *    .                                                 |
164    *    . . . > <RELEASE action> ---> <ACQUIRE action> ---/
165    *
166    * <UNLOCKED/LOCKED states>
167    *    |
168    *    |
169    *    v
170    * PRE_SHUTTING_DOWN ---> SHUTTING_DOWN ---> SHUTDOWN ---> <finish>
171    *
172    * @endverbatim
173    */
174   enum State {
175     STATE_UNINITIALIZED,
176     STATE_INITIALIZING,
177     STATE_UNLOCKED,
178     STATE_LOCKED,
179     STATE_ACQUIRING,
180     STATE_POST_ACQUIRING,
181     STATE_WAITING_FOR_REGISTER,
182     STATE_WAITING_FOR_LOCK,
183     STATE_REACQUIRING,
184     STATE_PRE_RELEASING,
185     STATE_RELEASING,
186     STATE_PRE_SHUTTING_DOWN,
187     STATE_SHUTTING_DOWN,
188     STATE_SHUTDOWN,
189   };
190
191   enum Action {
192     ACTION_TRY_LOCK,
193     ACTION_ACQUIRE_LOCK,
194     ACTION_REACQUIRE_LOCK,
195     ACTION_RELEASE_LOCK,
196     ACTION_SHUT_DOWN
197   };
198
199   typedef std::list<Context *> Contexts;
200   typedef std::pair<Action, Contexts> ActionContexts;
201   typedef std::list<ActionContexts> ActionsContexts;
202
203   struct C_ShutDownRelease : public Context {
204     ManagedLock *lock;
205     C_ShutDownRelease(ManagedLock *lock)
206       : lock(lock) {
207     }
208     void finish(int r) override {
209       lock->send_shutdown_release();
210     }
211   };
212
213   librados::IoCtx& m_ioctx;
214   CephContext *m_cct;
215   ContextWQ *m_work_queue;
216   std::string m_oid;
217   Watcher *m_watcher;
218   managed_lock::Mode m_mode;
219   bool m_blacklist_on_break_lock;
220   uint32_t m_blacklist_expire_seconds;
221
222   std::string m_cookie;
223   std::string m_new_cookie;
224
225   State m_state;
226   State m_post_next_state;
227
228   ActionsContexts m_actions_contexts;
229   AsyncOpTracker m_async_op_tracker;
230
231   bool is_lock_owner(Mutex &lock) const;
232   bool is_transition_state() const;
233
234   void append_context(Action action, Context *ctx);
235   void execute_action(Action action, Context *ctx);
236
237   Action get_active_action() const;
238   void complete_active_action(State next_state, int r);
239
240   void send_acquire_lock();
241   void handle_pre_acquire_lock(int r);
242   void handle_acquire_lock(int r);
243   void handle_post_acquire_lock(int r);
244   void revert_to_unlock_state(int r);
245
246   void send_reacquire_lock();
247   void handle_reacquire_lock(int r);
248
249   void send_release_lock();
250   void handle_pre_release_lock(int r);
251   void handle_release_lock(int r);
252   void handle_post_release_lock(int r);
253
254   void send_shutdown();
255   void handle_shutdown(int r);
256   void send_shutdown_release();
257   void handle_shutdown_pre_release(int r);
258   void handle_shutdown_post_release(int r);
259   void wait_for_tracked_ops(int r);
260   void complete_shutdown(int r);
261 };
262
263 } // namespace librbd
264
265 extern template class librbd::ManagedLock<librbd::ImageCtx>;
266
267 #endif // CEPH_LIBRBD_MANAGED_LOCK_H