Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / ImageState.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_IMAGE_STATE_H
5 #define CEPH_LIBRBD_IMAGE_STATE_H
6
7 #include "include/int_types.h"
8 #include "common/Mutex.h"
9 #include <list>
10 #include <string>
11 #include <utility>
12 #include "cls/rbd/cls_rbd_types.h"
13
14 class Context;
15 class RWLock;
16
17 namespace librbd {
18
19 class ImageCtx;
20 class ImageUpdateWatchers;
21 class UpdateWatchCtx;
22
23 template <typename ImageCtxT = ImageCtx>
24 class ImageState {
25 public:
26   ImageState(ImageCtxT *image_ctx);
27   ~ImageState();
28
29   int open(bool skip_open_parent);
30   void open(bool skip_open_parent, Context *on_finish);
31
32   int close();
33   void close(Context *on_finish);
34
35   void handle_update_notification();
36
37   bool is_refresh_required() const;
38
39   int refresh();
40   int refresh_if_required();
41   void refresh(Context *on_finish);
42
43   void snap_set(const cls::rbd::SnapshotNamespace &snap_namespace,
44                 const std::string &snap_name,
45                 Context *on_finish);
46
47   void prepare_lock(Context *on_ready);
48   void handle_prepare_lock_complete();
49
50   int register_update_watcher(UpdateWatchCtx *watcher, uint64_t *handle);
51   int unregister_update_watcher(uint64_t handle);
52   void flush_update_watchers(Context *on_finish);
53   void shut_down_update_watchers(Context *on_finish);
54
55 private:
56   enum State {
57     STATE_UNINITIALIZED,
58     STATE_OPEN,
59     STATE_CLOSED,
60     STATE_OPENING,
61     STATE_CLOSING,
62     STATE_REFRESHING,
63     STATE_SETTING_SNAP,
64     STATE_PREPARING_LOCK
65   };
66
67   enum ActionType {
68     ACTION_TYPE_OPEN,
69     ACTION_TYPE_CLOSE,
70     ACTION_TYPE_REFRESH,
71     ACTION_TYPE_SET_SNAP,
72     ACTION_TYPE_LOCK
73   };
74
75   struct Action {
76     ActionType action_type;
77     uint64_t refresh_seq = 0;
78     cls::rbd::SnapshotNamespace snap_namespace;
79     std::string snap_name;
80     Context *on_ready = nullptr;
81
82     Action(ActionType action_type) : action_type(action_type) {
83     }
84     inline bool operator==(const Action &action) const {
85       if (action_type != action.action_type) {
86         return false;
87       }
88       switch (action_type) {
89       case ACTION_TYPE_REFRESH:
90         return (refresh_seq == action.refresh_seq);
91       case ACTION_TYPE_SET_SNAP:
92         return (snap_name == action.snap_name) && (snap_namespace == action.snap_namespace);
93       case ACTION_TYPE_LOCK:
94         return false;
95       default:
96         return true;
97       }
98     }
99   };
100
101   typedef std::list<Context *> Contexts;
102   typedef std::pair<Action, Contexts> ActionContexts;
103   typedef std::list<ActionContexts> ActionsContexts;
104
105   ImageCtxT *m_image_ctx;
106   State m_state;
107
108   mutable Mutex m_lock;
109   ActionsContexts m_actions_contexts;
110
111   uint64_t m_last_refresh;
112   uint64_t m_refresh_seq;
113
114   ImageUpdateWatchers *m_update_watchers;
115
116   bool m_skip_open_parent_image;
117
118   bool is_transition_state() const;
119   bool is_closed() const;
120
121   const Action *find_pending_refresh() const;
122
123   void append_context(const Action &action, Context *context);
124   void execute_next_action_unlock();
125   void execute_action_unlock(const Action &action, Context *context);
126   void complete_action_unlock(State next_state, int r);
127
128   void send_open_unlock();
129   void handle_open(int r);
130
131   void send_close_unlock();
132   void handle_close(int r);
133
134   void send_refresh_unlock();
135   void handle_refresh(int r);
136
137   void send_set_snap_unlock();
138   void handle_set_snap(int r);
139
140   void send_prepare_lock_unlock();
141
142 };
143
144 } // namespace librbd
145
146 extern template class librbd::ImageState<librbd::ImageCtx>;
147
148 #endif // CEPH_LIBRBD_IMAGE_STATE_H