diff options
Diffstat (limited to 'src/librbd/ImageState.h')
-rw-r--r-- | src/librbd/ImageState.h | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/librbd/ImageState.h b/src/librbd/ImageState.h new file mode 100644 index 00000000..7f28d1ee --- /dev/null +++ b/src/librbd/ImageState.h @@ -0,0 +1,145 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_IMAGE_STATE_H +#define CEPH_LIBRBD_IMAGE_STATE_H + +#include "include/int_types.h" +#include "common/Mutex.h" +#include <list> +#include <string> +#include <utility> +#include "cls/rbd/cls_rbd_types.h" + +class Context; +class RWLock; + +namespace librbd { + +class ImageCtx; +class ImageUpdateWatchers; +class UpdateWatchCtx; + +template <typename ImageCtxT = ImageCtx> +class ImageState { +public: + ImageState(ImageCtxT *image_ctx); + ~ImageState(); + + int open(uint64_t flags); + void open(uint64_t flags, Context *on_finish); + + int close(); + void close(Context *on_finish); + + void handle_update_notification(); + + bool is_refresh_required() const; + + int refresh(); + int refresh_if_required(); + void refresh(Context *on_finish); + + void snap_set(uint64_t snap_id, Context *on_finish); + + void prepare_lock(Context *on_ready); + void handle_prepare_lock_complete(); + + int register_update_watcher(UpdateWatchCtx *watcher, uint64_t *handle); + int unregister_update_watcher(uint64_t handle); + void flush_update_watchers(Context *on_finish); + void shut_down_update_watchers(Context *on_finish); + +private: + enum State { + STATE_UNINITIALIZED, + STATE_OPEN, + STATE_CLOSED, + STATE_OPENING, + STATE_CLOSING, + STATE_REFRESHING, + STATE_SETTING_SNAP, + STATE_PREPARING_LOCK + }; + + enum ActionType { + ACTION_TYPE_OPEN, + ACTION_TYPE_CLOSE, + ACTION_TYPE_REFRESH, + ACTION_TYPE_SET_SNAP, + ACTION_TYPE_LOCK + }; + + struct Action { + ActionType action_type; + uint64_t refresh_seq = 0; + uint64_t snap_id = CEPH_NOSNAP; + Context *on_ready = nullptr; + + Action(ActionType action_type) : action_type(action_type) { + } + inline bool operator==(const Action &action) const { + if (action_type != action.action_type) { + return false; + } + switch (action_type) { + case ACTION_TYPE_REFRESH: + return (refresh_seq == action.refresh_seq); + case ACTION_TYPE_SET_SNAP: + return (snap_id == action.snap_id); + case ACTION_TYPE_LOCK: + return false; + default: + return true; + } + } + }; + + typedef std::list<Context *> Contexts; + typedef std::pair<Action, Contexts> ActionContexts; + typedef std::list<ActionContexts> ActionsContexts; + + ImageCtxT *m_image_ctx; + State m_state; + + mutable Mutex m_lock; + ActionsContexts m_actions_contexts; + + uint64_t m_last_refresh; + uint64_t m_refresh_seq; + + ImageUpdateWatchers *m_update_watchers; + + uint64_t m_open_flags; + + bool is_transition_state() const; + bool is_closed() const; + + const Action *find_pending_refresh() const; + + void append_context(const Action &action, Context *context); + void execute_next_action_unlock(); + void execute_action_unlock(const Action &action, Context *context); + void complete_action_unlock(State next_state, int r); + + void send_open_unlock(); + void handle_open(int r); + + void send_close_unlock(); + void handle_close(int r); + + void send_refresh_unlock(); + void handle_refresh(int r); + + void send_set_snap_unlock(); + void handle_set_snap(int r); + + void send_prepare_lock_unlock(); + +}; + +} // namespace librbd + +extern template class librbd::ImageState<librbd::ImageCtx>; + +#endif // CEPH_LIBRBD_IMAGE_STATE_H |