// -*- 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 #include #include #include "cls/rbd/cls_rbd_types.h" class Context; class RWLock; namespace librbd { class ImageCtx; class ImageUpdateWatchers; class UpdateWatchCtx; template class ImageState { public: ImageState(ImageCtxT *image_ctx); ~ImageState(); int open(bool skip_open_parent); void open(bool skip_open_parent, 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(const cls::rbd::SnapshotNamespace &snap_namespace, const std::string &snap_name, 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; cls::rbd::SnapshotNamespace snap_namespace; std::string snap_name; 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_name == action.snap_name) && (snap_namespace == action.snap_namespace); case ACTION_TYPE_LOCK: return false; default: return true; } } }; typedef std::list Contexts; typedef std::pair ActionContexts; typedef std::list 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; bool m_skip_open_parent_image; 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; #endif // CEPH_LIBRBD_IMAGE_STATE_H