// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab /* * Ceph - scalable distributed file system * * Copyright (C) 2014 Adam Crume * * This is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software * Foundation. See file COPYING. * */ #ifndef _INCLUDED_RBD_REPLAY_ACTIONS_HPP #define _INCLUDED_RBD_REPLAY_ACTIONS_HPP #include #include "include/rbd/librbd.hpp" #include "common/Formatter.h" #include "rbd_replay/ActionTypes.h" #include "rbd_loc.hpp" #include // Stupid Doxygen requires this or else the typedef docs don't appear anywhere. /// @file rbd_replay/actions.hpp namespace rbd_replay { typedef uint64_t imagectx_id_t; typedef uint64_t thread_id_t; /// Even IDs are normal actions, odd IDs are completions. typedef uint32_t action_id_t; class PendingIO; /** %Context through which an Action interacts with its environment. */ class ActionCtx { public: virtual ~ActionCtx() { } /** Returns the image with the given ID. The image must have been previously tracked with put_image(imagectx_id_t,librbd::Image*). */ virtual librbd::Image* get_image(imagectx_id_t imagectx_id) = 0; /** Tracks an image. put_image(imagectx_id_t,librbd::Image*) must not have been called previously with the same ID, and the image must not be NULL. */ virtual void put_image(imagectx_id_t imagectx_id, librbd::Image* image) = 0; /** Stops tracking an Image and release it. This deletes the C++ object, not the image itself. The image must have been previously tracked with put_image(imagectx_id_t,librbd::Image*). */ virtual void erase_image(imagectx_id_t imagectx_id) = 0; virtual librbd::RBD* rbd() = 0; virtual librados::IoCtx* ioctx() = 0; virtual void add_pending(boost::shared_ptr io) = 0; virtual bool readonly() const = 0; virtual void remove_pending(boost::shared_ptr io) = 0; virtual void set_action_complete(action_id_t id) = 0; virtual void stop() = 0; /** Maps an image name from the name in the original trace to the name that should be used when replaying. @param image_name name of the image in the original trace @param snap_name name of the snap in the orginal trace @return image name to replay against */ virtual rbd_loc map_image_name(std::string image_name, std::string snap_name) const = 0; }; /** Performs an %IO or a maintenance action such as starting or stopping a thread. Actions are read from a replay file and scheduled by Replayer. Corresponds to the IO class, except that Actions are executed by rbd-replay, and IOs are used by rbd-replay-prep for processing the raw trace. */ class Action { public: typedef boost::shared_ptr ptr; virtual ~Action() { } virtual void perform(ActionCtx &ctx) = 0; /// Returns the ID of the completion corresponding to this action. action_id_t pending_io_id() { return id() + 1; } // There's probably a better way to do this, but oh well. virtual bool is_start_thread() { return false; } virtual action_id_t id() const = 0; virtual thread_id_t thread_id() const = 0; virtual const action::Dependencies& predecessors() const = 0; virtual std::ostream& dump(std::ostream& o) const = 0; static ptr construct(const action::ActionEntry &action_entry); }; template class TypedAction : public Action { public: explicit TypedAction(const ActionType &action) : m_action(action) { } action_id_t id() const override { return m_action.id; } thread_id_t thread_id() const override { return m_action.thread_id; } const action::Dependencies& predecessors() const override { return m_action.dependencies; } std::ostream& dump(std::ostream& o) const override { o << get_action_name() << ": "; ceph::JSONFormatter formatter(false); formatter.open_object_section(""); m_action.dump(&formatter); formatter.close_section(); formatter.flush(o); return o; } protected: const ActionType m_action; virtual const char *get_action_name() const = 0; }; /// Writes human-readable debug information about the action to the stream. /// @related Action std::ostream& operator<<(std::ostream& o, const Action& a); class StartThreadAction : public TypedAction { public: explicit StartThreadAction(const action::StartThreadAction &action) : TypedAction(action) { } bool is_start_thread() override { return true; } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "StartThreadAction"; } }; class StopThreadAction : public TypedAction { public: explicit StopThreadAction(const action::StopThreadAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "StartThreadAction"; } }; class AioReadAction : public TypedAction { public: explicit AioReadAction(const action::AioReadAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "AioReadAction"; } }; class ReadAction : public TypedAction { public: explicit ReadAction(const action::ReadAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "ReadAction"; } }; class AioWriteAction : public TypedAction { public: explicit AioWriteAction(const action::AioWriteAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "AioWriteAction"; } }; class WriteAction : public TypedAction { public: explicit WriteAction(const action::WriteAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "WriteAction"; } }; class AioDiscardAction : public TypedAction { public: explicit AioDiscardAction(const action::AioDiscardAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "AioDiscardAction"; } }; class DiscardAction : public TypedAction { public: explicit DiscardAction(const action::DiscardAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "DiscardAction"; } }; class OpenImageAction : public TypedAction { public: explicit OpenImageAction(const action::OpenImageAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "OpenImageAction"; } }; class CloseImageAction : public TypedAction { public: explicit CloseImageAction(const action::CloseImageAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "CloseImageAction"; } }; class AioOpenImageAction : public TypedAction { public: explicit AioOpenImageAction(const action::AioOpenImageAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "AioOpenImageAction"; } }; class AioCloseImageAction : public TypedAction { public: explicit AioCloseImageAction(const action::AioCloseImageAction &action) : TypedAction(action) { } void perform(ActionCtx &ctx) override; protected: const char *get_action_name() const override { return "AioCloseImageAction"; } }; } #endif