]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-replay: Add code documentation 2475/head
authorAdam Crume <adamcrume@gmail.com>
Thu, 11 Sep 2014 17:44:59 +0000 (10:44 -0700)
committerAdam Crume <adamcrume@gmail.com>
Thu, 11 Sep 2014 23:48:08 +0000 (16:48 -0700)
Signed-off-by: Adam Crume <adamcrume@gmail.com>
src/rbd_replay/BoundedBuffer.hpp
src/rbd_replay/Deser.hpp
src/rbd_replay/ImageNameMap.hpp
src/rbd_replay/PendingIO.cc
src/rbd_replay/PendingIO.hpp
src/rbd_replay/Replayer.hpp
src/rbd_replay/Ser.hpp
src/rbd_replay/actions.hpp
src/rbd_replay/ios.hpp
src/rbd_replay/rbd_loc.hpp

index 540fd317e2164a93965386db135589ff6f6c66c5..e4df483c1f67301080f005e4b3a2f68623651a93 100644 (file)
@@ -9,7 +9,10 @@
 #include <boost/thread/condition.hpp>
 #include <boost/thread/mutex.hpp>
 
-// Taken from http://www.boost.org/doc/libs/1_55_0/libs/circular_buffer/example/circular_buffer_bound_example.cpp
+/**
+   Blocking, fixed-capacity, thread-safe FIFO queue useful for communicating between threads.
+   This code was taken from the Boost docs: http://www.boost.org/doc/libs/1_55_0/libs/circular_buffer/example/circular_buffer_bound_example.cpp
+ */
 template <class T>
 class BoundedBuffer {
 public:
@@ -21,6 +24,10 @@ public:
   explicit BoundedBuffer(size_type capacity) : m_unread(0), m_container(capacity) {
   }
 
+  /**
+     Inserts an element into the queue.
+     Blocks if the queue is full.
+   */
   void push_front(typename boost::call_traits<value_type>::param_type item) {
     // `param_type` represents the "best" way to pass a parameter of type `value_type` to a method.
     boost::mutex::scoped_lock lock(m_mutex);
@@ -31,6 +38,10 @@ public:
     m_not_empty.notify_one();
   }
 
+  /**
+     Removes an element from the queue.
+     Blocks if the queue is empty.
+  */
   void pop_back(value_type* pItem) {
     boost::mutex::scoped_lock lock(m_mutex);
     m_not_empty.wait(lock, boost::bind(&BoundedBuffer<value_type>::is_not_empty, this));
index d5fad5ae6650e7ba6f3f61cf1a4b0ad73c93b225..b466acec6628527f68f12d7b34e3973c87a4c698 100644 (file)
 
 namespace rbd_replay {
 
+/**
+   Helper for deserializing data in an architecture-indepdendent way.
+   Everything is read big-endian.
+   @see Ser
+*/
 class Deser {
 public:
   Deser(std::istream &in);
index 00de76552cdf88c4bcf0a47b15a01d552aec9725..45cdaf68694786ff2f9cd15ce5556cbdd7ada4b1 100644 (file)
 
 namespace rbd_replay {
 
+/**
+   Maps image names.
+ */
 class ImageNameMap {
 public:
   typedef std::pair<rbd_loc, rbd_loc> Mapping;
 
+  /**
+     Parses a mapping.
+     If parsing fails, the contents of \c mapping are undefined.
+     @param[in] mapping_string string representation of the mapping
+     @param[out] mapping stores the parsed mapping
+     @retval true parsing was successful
+   */
   bool parse_mapping(std::string mapping_string, Mapping *mapping) const;
 
   void add_mapping(const Mapping& mapping);
 
+  /**
+     Maps an image name.
+     If no mapping matches the name, it is returned unmodified.
+   */
   rbd_loc map(const rbd_loc& name) const;
 
 private:
index 6c41001e11f00763245f60063f650ac23958233a..bbf0a204c210ae88a905246483a2c45e3c5634f2 100644 (file)
@@ -20,7 +20,7 @@ using namespace std;
 using namespace rbd_replay;
 
 extern "C"
-void pending_io_callback(librbd::completion_t cb, void *arg) {
+void rbd_replay_pending_io_callback(librbd::completion_t cb, void *arg) {
   PendingIO *io = static_cast<PendingIO*>(arg);
   io->completed(cb);
 }
@@ -28,7 +28,7 @@ void pending_io_callback(librbd::completion_t cb, void *arg) {
 PendingIO::PendingIO(action_id_t id,
                     ActionCtx &worker)
   : m_id(id),
-    m_completion(new librbd::RBD::AioCompletion(this, pending_io_callback)),
+    m_completion(new librbd::RBD::AioCompletion(this, rbd_replay_pending_io_callback)),
     m_worker(worker) {
     }
 
index 3f0120744e9ef6c130f8347ee49972d9194d3fbb..3942d5f6fd9d9f2ebccf694a5d37d98aa546001e 100644 (file)
 #include <boost/enable_shared_from_this.hpp>
 #include "actions.hpp"
 
+/// Do not call outside of rbd_replay::PendingIO.
+extern "C"
+void rbd_replay_pending_io_callback(librbd::completion_t cb, void *arg);
+
 namespace rbd_replay {
 
+/**
+   A PendingIO is an I/O operation that has been started but not completed.
+*/
 class PendingIO : public boost::enable_shared_from_this<PendingIO> {
 public:
   typedef boost::shared_ptr<PendingIO> ptr;
@@ -29,8 +36,6 @@ public:
 
   ~PendingIO();
 
-  void completed(librbd::completion_t cb);
-
   action_id_t id() const {
     return m_id;
   }
@@ -44,6 +49,10 @@ public:
   }
 
 private:
+  void completed(librbd::completion_t cb);
+
+  friend void ::rbd_replay_pending_io_callback(librbd::completion_t cb, void *arg);
+
   const action_id_t m_id;
   ceph::bufferlist m_bl;
   librbd::RBD::AioCompletion *m_completion;
index 1cbecc2fe7a3ba47bd871d384b02d620ad38b357..538e7fddd4df31d1207282b6dc17095b0625c018 100644 (file)
@@ -25,13 +25,16 @@ namespace rbd_replay {
 
 class Replayer;
 
+/**
+   Performs Actions within a single thread.
+ */
 class Worker : public ActionCtx {
 public:
   explicit Worker(Replayer &replayer);
 
   void start();
 
-  // Should only be called by StopThreadAction
+  /// Should only be called by StopThreadAction
   void stop();
 
   void join();
@@ -123,7 +126,7 @@ public:
 
 private:
   struct action_tracker_d {
-    // Maps an action ID to the time the action completed
+    /// Maps an action ID to the time the action completed
     std::map<action_id_t, boost::system_time> actions;
     boost::shared_mutex mutex;
     boost::condition condition;
@@ -133,8 +136,9 @@ private:
 
   action_tracker_d &tracker_for(action_id_t id);
 
-  // Disallow assignment and copying
+  /// Disallow copying
   Replayer(const Replayer& rhs);
+  /// Disallow assignment
   const Replayer& operator=(const Replayer& rhs);
 
   librbd::RBD* m_rbd;
@@ -148,9 +152,9 @@ private:
   std::map<imagectx_id_t, librbd::Image*> m_images;
   boost::shared_mutex m_images_mutex;
 
-  // Actions are hashed across the trackers by ID.
-  // Number of trackers should probably be larger than the number of cores and prime.
-  // Should definitely be odd.
+  /// Actions are hashed across the trackers by ID.
+  /// Number of trackers should probably be larger than the number of cores and prime.
+  /// Should definitely be odd.
   const int m_num_action_trackers;
   action_tracker_d* m_action_trackers;
 };
index 2bada8f70bc298fa98ec82d848f0a290f504d8f7..130465dc4392ec6a1409d7db906b20eb1c90cde3 100644 (file)
 
 namespace rbd_replay {
 
+/**
+   Helper for serializing data in an architecture-indepdendent way.
+   Everything is written big-endian.
+   @see Deser
+*/
 class Ser {
 public:
   Ser(std::ostream &out);
index 5d3f4dc4cd45ba952f95f0340796e1e632afcf03..068e4dc413944ee378a48d067b8f5ae04484bebb 100644 (file)
 #include "Deser.hpp"
 #include "rbd_loc.hpp"
 
+// 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
+/// Even IDs are normal actions, odd IDs are completions.
 typedef uint32_t action_id_t;
 
+/**
+   Dependencies link actions to earlier actions or completions.
+   If an action has a dependency \c d then it waits until \c d.time_delta nanoseconds after the action or completion with ID \c d.id has fired.
+*/
 struct dependency_d {
+  /// ID of the action or completion to wait for.
   action_id_t id;
 
+  /// Nanoseconds of delay to wait until after the action or completion fires.
   uint64_t time_delta;
 
+  /**
+     @param id ID of the action or completion to wait for.
+     @param time_delta Nanoseconds of delay to wait after the action or completion fires.
+   */
   dependency_d(action_id_t id,
               uint64_t time_delta)
     : id(id),
@@ -56,15 +69,32 @@ enum io_type {
 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;
@@ -81,10 +111,22 @@ public:
 
   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<Action> ptr;
@@ -99,6 +141,7 @@ public:
 
   virtual void perform(ActionCtx &ctx) = 0;
 
+  /// Returns the ID of the completion corresponding to this action.
   action_id_t pending_io_id() {
     return m_id + 1;
   }
@@ -120,6 +163,7 @@ public:
     return m_predecessors;
   }
 
+  /// Reads and constructs an action from the replay file.
   static ptr read_from(Deser &d);
 
 protected:
@@ -137,9 +181,15 @@ private:
   const std::vector<dependency_d> m_predecessors;
 };
 
+/// Writes human-readable debug information about the action to the stream.
+/// @related Action
 std::ostream& operator<<(std::ostream& o, const Action& a);
 
 
+/**
+   Placeholder for partially-constructed actions.
+   Does nothing, and does not appear in the replay file.
+ */
 class DummyAction : public Action {
 public:
   DummyAction(action_id_t id,
@@ -157,6 +207,7 @@ private:
   std::ostream& dump(std::ostream& o) const;
 };
 
+
 class StopThreadAction : public Action {
 public:
   explicit StopThreadAction(Action &src);
index ad9ff2a5c99205cab5066a82e9910794486fb45d..5bebcd71731d58a3a4434eade548bd28bc6df1bc 100644 (file)
@@ -35,14 +35,40 @@ typedef std::set<boost::shared_ptr<IO> > io_set_t;
 
 typedef std::map<action_id_t, boost::shared_ptr<IO> > io_map_t;
 
+/**
+   Calculates reachability of IOs in the dependency graph.
+   All IOs in \c deps which are not transitive dependencies of anything in \c base
+   is added to \c unreachable.
+   In other words, for every IO \c x in \c deps: if nothing in \c base depends on \c x,
+   and nothing in \c base has dependencies that depend on \c x, etc.,
+   then \c x is added to \c unreachable.
+   Note that \c unreachable is \em not cleared, so the same set can be used across multiple
+   calls to collect dependencies.
+   @param[in] deps IOs to search for
+   @param[in] base root set of IOs to search from
+   @param[out] unreachable collects unreachable IOs
+   @related IO
+*/
 void batch_unreachable_from(const io_set_t& deps, const io_set_t& base, io_set_t* unreachable);
 
+
+/**
+   Used by rbd-replay-prep for processing the raw trace.
+   Corresponds to the Action class, except that Actions are executed by rbd-replay,
+   and IOs are used by rbd-replay-prep for processing the raw trace.
+ */
 class IO : public boost::enable_shared_from_this<IO> {
 public:
   typedef boost::shared_ptr<IO> ptr;
 
   typedef boost::weak_ptr<IO> weak_ptr;
 
+  /**
+     @param ionum ID of this %IO
+     @param start_time time the %IO started, in nanoseconds
+     @param thread_id ID of the thread that issued the %IO
+     @param prev previously issued %IO on the same thread.  NULL for the first %IO on a thread.
+   */
   IO(action_id_t ionum,
      uint64_t start_time,
      thread_id_t thread_id,
@@ -73,13 +99,14 @@ public:
 
   void add_dependencies(const io_set_t& deps);
 
+  /**
+     Returns the completion's number of successors, or 0 if the %IO does not have a completion.
+   */
   uint64_t num_completion_successors() const {
     ptr c(m_completion.lock());
     return c ? c->m_num_successors : 0;
   }
 
-  void write_to(Ser& out, io_type iotype) const;
-
   virtual void write_to(Ser& out) const = 0;
 
   virtual bool is_completion() const {
@@ -106,13 +133,20 @@ public:
     return m_num_successors;
   }
 
-  void write_debug_base(std::ostream& out, std::string iotype) const;
-
   virtual void write_debug(std::ostream& out) const = 0;
 
-  // The result must be stored somewhere, or else m_completion will expire
+  /**
+     Creates the completion for this IO.
+     This may only be called once per IO, and may not be called on completion IOs.
+     The completion must be stored, or else m_completion will expire.
+   */
   ptr create_completion(uint64_t start_time, thread_id_t thread_id);
 
+protected:
+  void write_to(Ser& out, io_type iotype) const;
+
+  void write_debug_base(std::ostream& out, std::string iotype) const;
+
 private:
   action_id_t m_ionum;
   uint64_t m_start_time;
@@ -123,6 +157,8 @@ private:
   ptr m_prev;
 };
 
+/// Used for dumping debug info.
+/// @related IO
 std::ostream& operator<<(std::ostream& out, IO::ptr io);
 
 
@@ -327,6 +363,7 @@ public:
   }
 };
 
+/// @related IO
 bool compare_io_ptrs_by_start_time(IO::ptr p1, IO::ptr p2);
 
 }
index fab159ae7157dc50bdbfb2a32084615097edb943..9865962fd3ef307d7081a2ba8c0f2258f00690e3 100644 (file)
 
 namespace rbd_replay {
 
+/**
+   Stores a pool, image name, and snap name triple.
+   rbd_locs can be converted to/from strings with the format pool/image\@snap.
+   The slash and at signs can be omitted if the pool and snap are empty, respectively.
+   Backslashes can be used to escape slashes and at signs in names.
+   Examples:
+
+   |Pool  | Image | Snap | String             |
+   |------|-------|------|--------------------|
+   |rbd   | vm    | 1    | rbd/vm\@1          |
+   |rbd   | vm    |      | rbd/vm             |
+   |      | vm    | 1    | vm\@1              |
+   |      | vm    |      | vm                 |
+   |rbd   |       | 1    | rbd/\@1            |
+   |rbd\@x| vm/y  | 1    | rbd\\\@x/vm\\/y\@1 |
+
+   (The empty string should obviously be avoided as the image name.)
+
+   Note that the non-canonical forms /vm\@1 and rbd/vm\@ can also be parsed,
+   although they will be formatted as vm\@1 and rbd/vm.
+ */
 struct rbd_loc {
+  /**
+     Constructs an rbd_loc with the empty string for the pool, image, and snap.
+   */
   rbd_loc();
 
+  /**
+     Constructs an rbd_loc with the given pool, image, and snap.
+   */
   rbd_loc(std::string pool, std::string image, std::string snap);
 
+  /**
+     Parses an rbd_loc from the given string.
+     If parsing fails, the contents are unmodified.
+     @retval true if parsing succeeded
+   */
   bool parse(std::string name_string);
 
+  /**
+     Returns the string representation of the locator.
+   */
   std::string str() const;
 
+  /**
+     Compares the locators lexicographically by pool, then image, then snap.
+   */
   int compare(const rbd_loc& rhs) const;
 
+  /**
+     Returns true if the locators have identical pool, image, and snap.
+   */
   bool operator==(const rbd_loc& rhs) const;
 
+  /**
+     Compares the locators lexicographically by pool, then image, then snap.
+   */
   bool operator<(const rbd_loc& rhs) const;
 
   std::string pool;