]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: convert journal classes to templates for unit testing
authorJason Dillaman <dillaman@redhat.com>
Tue, 15 Dec 2015 16:13:34 +0000 (11:13 -0500)
committerJason Dillaman <dillaman@redhat.com>
Fri, 15 Jan 2016 15:40:28 +0000 (10:40 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
12 files changed:
src/librbd/ImageCtx.cc
src/librbd/ImageCtx.h
src/librbd/Journal.cc
src/librbd/Journal.h
src/librbd/exclusive_lock/AcquireRequest.h
src/librbd/exclusive_lock/ReleaseRequest.h
src/librbd/image/RefreshRequest.cc
src/librbd/image/RefreshRequest.h
src/librbd/internal.cc
src/librbd/journal/Replay.cc
src/librbd/journal/Replay.h
src/test/librbd/journal/test_Replay.cc

index 67d98af80e9123afaf75a88f7852bde67a8c74a8..ef7861f332df1801a14e82766d1a29b1bbfb2c6c 100644 (file)
@@ -1004,7 +1004,7 @@ struct C_InvalidateCache : public Context {
     return new ObjectMap(*this, snap_id);
   }
 
-  Journal *ImageCtx::create_journal() {
-    return new Journal(*this);
+  Journal<ImageCtx> *ImageCtx::create_journal() {
+    return new Journal<ImageCtx>(*this);
   }
 }
index 715fcbb56e188c866c3d9c3ec0e7114c36833c15..451d14ff72cea670eceb46b0cf0519d494c98cad 100644 (file)
@@ -47,7 +47,7 @@ namespace librbd {
   template <typename> class ExclusiveLock;
   template <typename> class ImageState;
   class ImageWatcher;
-  class Journal;
+  template <typename> class Journal;
   class LibrbdAdminSocketHook;
   class ObjectMap;
 
@@ -79,7 +79,7 @@ namespace librbd {
     std::string snap_name;
     IoCtx data_ctx, md_ctx;
     ImageWatcher *image_watcher;
-    Journal *journal;
+    Journal<ImageCtx> *journal;
 
     /**
      * Lock ordering:
@@ -270,7 +270,7 @@ namespace librbd {
     void apply_metadata_confs();
 
     ObjectMap *create_object_map(uint64_t snap_id);
-    Journal *create_journal();
+    Journal<ImageCtx> *create_journal();
 
     void clear_pending_completions();
   };
index fa5448e1ea48648c92c79cbbca91dd440cbfa975..44a37d0db6aa92ad74838f1f58214a2b5801406e 100644 (file)
@@ -62,32 +62,71 @@ struct C_ReplayCommitted : public Context {
 
 } // anonymous namespace
 
-Journal::Journal(ImageCtx &image_ctx)
+template <typename I>
+std::ostream &operator<<(std::ostream &os,
+                         const typename Journal<I>::State &state) {
+  switch (state) {
+  case Journal<I>::STATE_UNINITIALIZED:
+    os << "Uninitialized";
+    break;
+  case Journal<I>::STATE_INITIALIZING:
+    os << "Initializing";
+    break;
+  case Journal<I>::STATE_REPLAYING:
+    os << "Replaying";
+    break;
+  case Journal<I>::STATE_RESTARTING_REPLAY:
+    os << "RestartingReplay";
+    break;
+  case Journal<I>::STATE_READY:
+    os << "Ready";
+    break;
+  case Journal<I>::STATE_STOPPING:
+    os << "Stopping";
+    break;
+  case Journal<I>::STATE_CLOSING:
+    os << "Closing";
+    break;
+  case Journal<I>::STATE_CLOSED:
+    os << "Closed";
+    break;
+  default:
+    os << "Unknown (" << static_cast<uint32_t>(state) << ")";
+    break;
+  }
+  return os;
+}
+
+template <typename I>
+Journal<I>::Journal(I &image_ctx)
   : m_image_ctx(image_ctx), m_journaler(NULL),
-    m_lock("Journal::m_lock"), m_state(STATE_UNINITIALIZED),
+    m_lock("Journal<I>::m_lock"), m_state(STATE_UNINITIALIZED),
     m_error_result(0), m_replay_handler(this), m_close_pending(false),
-    m_event_lock("Journal::m_event_lock"), m_event_tid(0),
+    m_event_lock("Journal<I>::m_event_lock"), m_event_tid(0),
     m_blocking_writes(false), m_journal_replay(NULL) {
 
   ldout(m_image_ctx.cct, 5) << this << ": ictx=" << &m_image_ctx << dendl;
 }
 
-Journal::~Journal() {
+template <typename I>
+Journal<I>::~Journal() {
   assert(m_state == STATE_UNINITIALIZED || m_state == STATE_CLOSED);
   assert(m_journaler == NULL);
   assert(m_journal_replay == NULL);
   assert(m_wait_for_state_contexts.empty());
 }
 
-bool Journal::is_journal_supported(ImageCtx &image_ctx) {
+template <typename I>
+bool Journal<I>::is_journal_supported(I &image_ctx) {
   assert(image_ctx.snap_lock.is_locked());
   return ((image_ctx.features & RBD_FEATURE_JOURNALING) &&
           !image_ctx.read_only && image_ctx.snap_id == CEPH_NOSNAP);
 }
 
-int Journal::create(librados::IoCtx &io_ctx, const std::string &image_id,
-                   uint8_t order, uint8_t splay_width,
-                   const std::string &object_pool) {
+template <typename I>
+int Journal<I>::create(librados::IoCtx &io_ctx, const std::string &image_id,
+                      uint8_t order, uint8_t splay_width,
+                      const std::string &object_pool) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 5) << __func__ << ": image=" << image_id << dendl;
 
@@ -122,7 +161,8 @@ int Journal::create(librados::IoCtx &io_ctx, const std::string &image_id,
   return 0;
 }
 
-int Journal::remove(librados::IoCtx &io_ctx, const std::string &image_id) {
+template <typename I>
+int Journal<I>::remove(librados::IoCtx &io_ctx, const std::string &image_id) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 5) << __func__ << ": image=" << image_id << dendl;
 
@@ -157,7 +197,8 @@ int Journal::remove(librados::IoCtx &io_ctx, const std::string &image_id) {
   return 0;
 }
 
-int Journal::reset(librados::IoCtx &io_ctx, const std::string &image_id) {
+template <typename I>
+int Journal<I>::reset(librados::IoCtx &io_ctx, const std::string &image_id) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 5) << __func__ << ": image=" << image_id << dendl;
 
@@ -197,17 +238,20 @@ int Journal::reset(librados::IoCtx &io_ctx, const std::string &image_id) {
   return 0;
 }
 
-bool Journal::is_journal_ready() const {
+template <typename I>
+bool Journal<I>::is_journal_ready() const {
   Mutex::Locker locker(m_lock);
   return (m_state == STATE_READY);
 }
 
-bool Journal::is_journal_replaying() const {
+template <typename I>
+bool Journal<I>::is_journal_replaying() const {
   Mutex::Locker locker(m_lock);
   return (m_state == STATE_REPLAYING);
 }
 
-void Journal::wait_for_journal_ready(Context *on_ready) {
+template <typename I>
+void Journal<I>::wait_for_journal_ready(Context *on_ready) {
   on_ready = util::create_async_context_callback(m_image_ctx, on_ready);
 
   Mutex::Locker locker(m_lock);
@@ -218,7 +262,8 @@ void Journal::wait_for_journal_ready(Context *on_ready) {
   }
 }
 
-void Journal::open(Context *on_finish) {
+template <typename I>
+void Journal<I>::open(Context *on_finish) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << dendl;
 
@@ -230,7 +275,8 @@ void Journal::open(Context *on_finish) {
   create_journaler();
 }
 
-void Journal::close(Context *on_finish) {
+template <typename I>
+void Journal<I>::close(Context *on_finish) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << dendl;
 
@@ -251,11 +297,12 @@ void Journal::close(Context *on_finish) {
   wait_for_steady_state(on_finish);
 }
 
-uint64_t Journal::append_io_event(AioCompletion *aio_comp,
-                                  const journal::EventEntry &event_entry,
-                                  const AioObjectRequests &requests,
-                                  uint64_t offset, size_t length,
-                                  bool flush_entry) {
+template <typename I>
+uint64_t Journal<I>::append_io_event(AioCompletion *aio_comp,
+                                     const journal::EventEntry &event_entry,
+                                     const AioObjectRequests &requests,
+                                     uint64_t offset, size_t length,
+                                     bool flush_entry) {
   assert(m_image_ctx.owner_lock.is_locked());
 
   bufferlist bl;
@@ -293,21 +340,23 @@ uint64_t Journal::append_io_event(AioCompletion *aio_comp,
   return tid;
 }
 
-void Journal::commit_io_event(uint64_t tid, int r) {
+template <typename I>
+void Journal<I>::commit_io_event(uint64_t tid, int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": tid=" << tid << ", "
                  "r=" << r << dendl;
 
   Mutex::Locker event_locker(m_event_lock);
-  Events::iterator it = m_events.find(tid);
+  typename Events::iterator it = m_events.find(tid);
   if (it == m_events.end()) {
     return;
   }
   complete_event(it, r);
 }
 
-void Journal::commit_io_event_extent(uint64_t tid, uint64_t offset,
-                                     uint64_t length, int r) {
+template <typename I>
+void Journal<I>::commit_io_event_extent(uint64_t tid, uint64_t offset,
+                                        uint64_t length, int r) {
   assert(length > 0);
 
   CephContext *cct = m_image_ctx.cct;
@@ -317,7 +366,7 @@ void Journal::commit_io_event_extent(uint64_t tid, uint64_t offset,
                  << "r=" << r << dendl;
 
   Mutex::Locker event_locker(m_event_lock);
-  Events::iterator it = m_events.find(tid);
+  typename Events::iterator it = m_events.find(tid);
   if (it == m_events.end()) {
     return;
   }
@@ -341,7 +390,8 @@ void Journal::commit_io_event_extent(uint64_t tid, uint64_t offset,
   complete_event(it, event.ret_val);
 }
 
-uint64_t Journal::append_op_event(journal::EventEntry &event_entry) {
+template <typename I>
+uint64_t Journal<I>::append_op_event(journal::EventEntry &event_entry) {
   assert(m_image_ctx.owner_lock.is_locked());
 
   uint64_t tid;
@@ -368,7 +418,8 @@ uint64_t Journal::append_op_event(journal::EventEntry &event_entry) {
   return tid;
 }
 
-void Journal::commit_op_event(uint64_t tid, int r) {
+template <typename I>
+void Journal<I>::commit_op_event(uint64_t tid, int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 10) << this << " " << __func__ << ": tid=" << tid << dendl;
 
@@ -385,7 +436,8 @@ void Journal::commit_op_event(uint64_t tid, int r) {
   }
 }
 
-void Journal::flush_event(uint64_t tid, Context *on_safe) {
+template <typename I>
+void Journal<I>::flush_event(uint64_t tid, Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": tid=" << tid << ", "
                  << "on_safe=" << on_safe << dendl;
@@ -401,7 +453,8 @@ void Journal::flush_event(uint64_t tid, Context *on_safe) {
   }
 }
 
-void Journal::wait_event(uint64_t tid, Context *on_safe) {
+template <typename I>
+void Journal<I>::wait_event(uint64_t tid, Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": tid=" << tid << ", "
                  << "on_safe=" << on_safe << dendl;
@@ -410,12 +463,13 @@ void Journal::wait_event(uint64_t tid, Context *on_safe) {
   wait_event(m_lock, tid, on_safe);
 }
 
-::journal::Future Journal::wait_event(Mutex &lock, uint64_t tid,
-                                      Context *on_safe) {
+template <typename I>
+::journal::Future Journal<I>::wait_event(Mutex &lock, uint64_t tid,
+                                         Context *on_safe) {
   assert(m_event_lock.is_locked());
   CephContext *cct = m_image_ctx.cct;
 
-  Events::iterator it = m_events.find(tid);
+  typename Events::iterator it = m_events.find(tid);
   if (it == m_events.end() || it->second.safe) {
     // journal entry already safe
     ldout(cct, 20) << "journal entry already safe" << dendl;
@@ -428,7 +482,8 @@ void Journal::wait_event(uint64_t tid, Context *on_safe) {
   return event.future;
 }
 
-void Journal::create_journaler() {
+template <typename I>
+void Journal<I>::create_journaler() {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << dendl;
 
@@ -442,7 +497,8 @@ void Journal::create_journaler() {
   m_journaler->init(new C_InitJournal(this));
 }
 
-void Journal::destroy_journaler(int r) {
+template <typename I>
+void Journal<I>::destroy_journaler(int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
 
@@ -455,7 +511,8 @@ void Journal::destroy_journaler(int r) {
   m_image_ctx.op_work_queue->queue(new C_DestroyJournaler(this), 0);
 }
 
-void Journal::recreate_journaler(int r) {
+template <typename I>
+void Journal<I>::recreate_journaler(int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
 
@@ -469,7 +526,8 @@ void Journal::recreate_journaler(int r) {
   m_image_ctx.op_work_queue->queue(new C_DestroyJournaler(this), 0);
 }
 
-void Journal::complete_event(Events::iterator it, int r) {
+template <typename I>
+void Journal<I>::complete_event(typename Events::iterator it, int r) {
   assert(m_event_lock.is_locked());
   assert(m_state == STATE_READY);
 
@@ -483,7 +541,8 @@ void Journal::complete_event(Events::iterator it, int r) {
   }
 }
 
-void Journal::handle_initialized(int r) {
+template <typename I>
+void Journal<I>::handle_initialized(int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
 
@@ -498,11 +557,12 @@ void Journal::handle_initialized(int r) {
   }
 
   transition_state(STATE_REPLAYING, 0);
-  m_journal_replay = new journal::Replay(m_image_ctx);
+  m_journal_replay = journal::Replay<I>::create(m_image_ctx);
   m_journaler->start_replay(&m_replay_handler);
 }
 
-void Journal::handle_replay_ready() {
+template <typename I>
+void Journal<I>::handle_replay_ready() {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << dendl;
 
@@ -539,7 +599,8 @@ void Journal::handle_replay_ready() {
   }
 }
 
-void Journal::handle_replay_complete(int r) {
+template <typename I>
+void Journal<I>::handle_replay_complete(int r) {
   CephContext *cct = m_image_ctx.cct;
 
   {
@@ -577,7 +638,8 @@ void Journal::handle_replay_complete(int r) {
   }
 }
 
-void Journal::handle_recording_stopped(int r) {
+template <typename I>
+void Journal<I>::handle_recording_stopped(int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
 
@@ -587,7 +649,8 @@ void Journal::handle_recording_stopped(int r) {
   destroy_journaler(r);
 }
 
-void Journal::handle_journal_destroyed(int r) {
+template <typename I>
+void Journal<I>::handle_journal_destroyed(int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
 
@@ -610,7 +673,8 @@ void Journal::handle_journal_destroyed(int r) {
   transition_state(STATE_CLOSED, r);
 }
 
-void Journal::handle_event_safe(int r, uint64_t tid) {
+template <typename I>
+void Journal<I>::handle_event_safe(int r, uint64_t tid) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": r=" << r << ", "
                  << "tid=" << tid << dendl;
@@ -621,7 +685,7 @@ void Journal::handle_event_safe(int r, uint64_t tid) {
   Contexts on_safe_contexts;
   {
     Mutex::Locker event_locker(m_event_lock);
-    Events::iterator it = m_events.find(tid);
+    typename Events::iterator it = m_events.find(tid);
     assert(it != m_events.end());
 
     Event &event = it->second;
@@ -657,7 +721,8 @@ void Journal::handle_event_safe(int r, uint64_t tid) {
   }
 }
 
-void Journal::stop_recording() {
+template <typename I>
+void Journal<I>::stop_recording() {
   assert(m_lock.is_locked());
   assert(m_journaler != NULL);
 
@@ -668,7 +733,8 @@ void Journal::stop_recording() {
     m_image_ctx, new C_StopRecording(this)));
 }
 
-void Journal::block_writes() {
+template <typename I>
+void Journal<I>::block_writes() {
   assert(m_lock.is_locked());
   if (!m_blocking_writes) {
     m_blocking_writes = true;
@@ -676,7 +742,8 @@ void Journal::block_writes() {
   }
 }
 
-void Journal::unblock_writes() {
+template <typename I>
+void Journal<I>::unblock_writes() {
   assert(m_lock.is_locked());
   if (m_blocking_writes) {
     m_blocking_writes = false;
@@ -684,7 +751,8 @@ void Journal::unblock_writes() {
   }
 }
 
-void Journal::transition_state(State state, int r) {
+template <typename I>
+void Journal<I>::transition_state(State state, int r) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": new state=" << state << dendl;
   assert(m_lock.is_locked());
@@ -702,7 +770,8 @@ void Journal::transition_state(State state, int r) {
   }
 }
 
-bool Journal::is_steady_state() const {
+template <typename I>
+bool Journal<I>::is_steady_state() const {
   assert(m_lock.is_locked());
   switch (m_state) {
   case STATE_READY:
@@ -719,7 +788,8 @@ bool Journal::is_steady_state() const {
   return false;
 }
 
-void Journal::wait_for_steady_state(Context *on_state) {
+template <typename I>
+void Journal<I>::wait_for_steady_state(Context *on_state) {
   assert(m_lock.is_locked());
   assert(!is_steady_state());
 
@@ -729,37 +799,6 @@ void Journal::wait_for_steady_state(Context *on_state) {
   m_wait_for_state_contexts.push_back(on_state);
 }
 
-std::ostream &operator<<(std::ostream &os, const Journal::State &state) {
-  switch (state) {
-  case Journal::STATE_UNINITIALIZED:
-    os << "Uninitialized";
-    break;
-  case Journal::STATE_INITIALIZING:
-    os << "Initializing";
-    break;
-  case Journal::STATE_REPLAYING:
-    os << "Replaying";
-    break;
-  case Journal::STATE_RESTARTING_REPLAY:
-    os << "RestartingReplay";
-    break;
-  case Journal::STATE_READY:
-    os << "Ready";
-    break;
-  case Journal::STATE_STOPPING:
-    os << "Stopping";
-    break;
-  case Journal::STATE_CLOSING:
-    os << "Closing";
-    break;
-  case Journal::STATE_CLOSED:
-    os << "Closed";
-    break;
-  default:
-    os << "Unknown (" << static_cast<uint32_t>(state) << ")";
-    break;
-  }
-  return os;
-}
-
 } // namespace librbd
+
+template class librbd::Journal<librbd::ImageCtx>;
index d9a48dbb76b9ecf18ec69f290c1ef86629563e52..80c0babbd623c4dcaee237c0446fd4f7e67a3566 100644 (file)
@@ -13,6 +13,7 @@
 #include "journal/Future.h"
 #include "journal/ReplayHandler.h"
 #include <algorithm>
+#include <iosfwd>
 #include <list>
 #include <string>
 
@@ -29,50 +30,12 @@ class ImageCtx;
 
 namespace journal {
 class EventEntry;
-class Replay;
+template <typename> class Replay;
 }
 
+template <typename ImageCtxT = ImageCtx>
 class Journal {
 public:
-  typedef std::list<AioObjectRequest *> AioObjectRequests;
-
-  Journal(ImageCtx &image_ctx);
-  ~Journal();
-
-  static bool is_journal_supported(ImageCtx &image_ctx);
-  static int create(librados::IoCtx &io_ctx, const std::string &image_id,
-                   uint8_t order, uint8_t splay_width,
-                   const std::string &object_pool);
-  static int remove(librados::IoCtx &io_ctx, const std::string &image_id);
-  static int reset(librados::IoCtx &io_ctx, const std::string &image_id);
-
-  bool is_journal_ready() const;
-  bool is_journal_replaying() const;
-
-  void wait_for_journal_ready(Context *on_ready);
-
-  void open(Context *on_finish);
-  void close(Context *on_finish);
-
-  uint64_t append_io_event(AioCompletion *aio_comp,
-                           const journal::EventEntry &event_entry,
-                           const AioObjectRequests &requests,
-                           uint64_t offset, size_t length,
-                           bool flush_entry);
-  void commit_io_event(uint64_t tid, int r);
-  void commit_io_event_extent(uint64_t tid, uint64_t offset, uint64_t length,
-                              int r);
-
-  uint64_t append_op_event(journal::EventEntry &event_entry);
-  void commit_op_event(uint64_t tid, int r);
-
-  void flush_event(uint64_t tid, Context *on_safe);
-  void wait_event(uint64_t tid, Context *on_safe);
-
-private:
-  typedef std::list<Context *> Contexts;
-  typedef interval_set<uint64_t> ExtentInterval;
-
   /**
    * @verbatim
    *
@@ -111,6 +74,45 @@ private:
     STATE_CLOSED
   };
 
+  typedef std::list<AioObjectRequest *> AioObjectRequests;
+
+  Journal(ImageCtxT &image_ctx);
+  ~Journal();
+
+  static bool is_journal_supported(ImageCtxT &image_ctx);
+  static int create(librados::IoCtx &io_ctx, const std::string &image_id,
+                   uint8_t order, uint8_t splay_width,
+                   const std::string &object_pool);
+  static int remove(librados::IoCtx &io_ctx, const std::string &image_id);
+  static int reset(librados::IoCtx &io_ctx, const std::string &image_id);
+
+  bool is_journal_ready() const;
+  bool is_journal_replaying() const;
+
+  void wait_for_journal_ready(Context *on_ready);
+
+  void open(Context *on_finish);
+  void close(Context *on_finish);
+
+  uint64_t append_io_event(AioCompletion *aio_comp,
+                           const journal::EventEntry &event_entry,
+                           const AioObjectRequests &requests,
+                           uint64_t offset, size_t length,
+                           bool flush_entry);
+  void commit_io_event(uint64_t tid, int r);
+  void commit_io_event_extent(uint64_t tid, uint64_t offset, uint64_t length,
+                              int r);
+
+  uint64_t append_op_event(journal::EventEntry &event_entry);
+  void commit_op_event(uint64_t tid, int r);
+
+  void flush_event(uint64_t tid, Context *on_safe);
+  void wait_event(uint64_t tid, Context *on_safe);
+
+private:
+  typedef std::list<Context *> Contexts;
+  typedef interval_set<uint64_t> ExtentInterval;
+
   struct Event {
     ::journal::Future future;
     AioCompletion *aio_comp;
@@ -199,7 +201,7 @@ private:
     }
   };
 
-  ImageCtx &m_image_ctx;
+  ImageCtxT &m_image_ctx;
 
   ::journal::Journaler *m_journaler;
   mutable Mutex m_lock;
@@ -217,7 +219,7 @@ private:
 
   bool m_blocking_writes;
 
-  journal::Replay *m_journal_replay;
+  journal::Replay<ImageCtxT> *m_journal_replay;
 
   ::journal::Future wait_event(Mutex &lock, uint64_t tid, Context *on_safe);
 
@@ -225,7 +227,7 @@ private:
   void destroy_journaler(int r);
   void recreate_journaler(int r);
 
-  void complete_event(Events::iterator it, int r);
+  void complete_event(typename Events::iterator it, int r);
 
   void handle_initialized(int r);
 
@@ -247,10 +249,10 @@ private:
 
   bool is_steady_state() const;
   void wait_for_steady_state(Context *on_state);
-
-  friend std::ostream &operator<<(std::ostream &os, const State &state);
 };
 
 } // namespace librbd
 
+extern template class librbd::Journal<librbd::ImageCtx>;
+
 #endif // CEPH_LIBRBD_JOURNAL_H
index 865b3c66bd49fed6bdbbcfb0427d41e1505715f2..d7b717b5336bab22340582e35d0ebf6fc9c91f5a 100644 (file)
@@ -16,7 +16,7 @@ class Context;
 
 namespace librbd {
 
-class Journal;
+template <typename> class Journal;
 
 namespace exclusive_lock {
 
index b23e6c7d879700e9bf7bf37c8343e2a742ac9d90..056d4e78f004f5e01f3c3e0ea96ef59c1114a2d1 100644 (file)
@@ -13,7 +13,7 @@ class Context;
 namespace librbd {
 
 class ImageCtx;
-class Journal;
+template <typename> class Journal;
 
 namespace exclusive_lock {
 
index c06dc1458eae20013cf113a95949bcaa7c1a1df6..d58bced2d2039eb150e7a1479d4cf773bbd94db3 100644 (file)
@@ -460,7 +460,7 @@ Context *RefreshRequest<I>::send_v2_open_journal() {
     klass, &klass::handle_v2_open_journal>(this);
 
   // TODO need safe close
-  m_journal = new Journal(m_image_ctx);
+  m_journal = m_image_ctx.create_journal();
   m_journal->open(ctx);
   return nullptr;
 }
index 25eda668a2fe3098245508d2c132592ff1a984f8..58451f539c85d518770f5ec8118e2ae92c38fc47 100644 (file)
@@ -18,10 +18,7 @@ class Context;
 
 namespace librbd {
 
-template <typename> class ExclusiveLock;
 class ImageCtx;
-class Journal;
-class ObjectMap;
 
 namespace image {
 
index c31da2e9ba2ad55f9866570d13d6a7d9c6b5ca50..4858df06a55417e52dbc0b1bc26ea9eadaa8fd6d 100644 (file)
@@ -1278,8 +1278,8 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
         goto err_remove_object_map;
       }
 
-      r = Journal::create(io_ctx, id, journal_order, journal_splay_width,
-                         journal_pool);
+      r = Journal<>::create(io_ctx, id, journal_order, journal_splay_width,
+                           journal_pool);
       if (r < 0) {
         lderr(cct) << "error creating journal: " << cpp_strerror(r) << dendl;
         goto err_remove_object_map;
@@ -1843,9 +1843,9 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
           }
           features_mask |= RBD_FEATURE_EXCLUSIVE_LOCK;
 
-          r = Journal::create(ictx->md_ctx, ictx->id, ictx->journal_order,
-                           ictx->journal_splay_width,
-                           ictx->journal_pool);
+          r = Journal<>::create(ictx->md_ctx, ictx->id, ictx->journal_order,
+                               ictx->journal_splay_width,
+                               ictx->journal_pool);
           if (r < 0) {
             lderr(cct) << "error creating image journal: " << cpp_strerror(r)
                        << dendl;
@@ -1885,7 +1885,7 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
           disable_flags = RBD_FLAG_FAST_DIFF_INVALID;
         }
         if ((features & RBD_FEATURE_JOURNALING) != 0) {
-          r = Journal::remove(ictx->md_ctx, ictx->id);
+          r = Journal<>::remove(ictx->md_ctx, ictx->id);
           if (r < 0) {
             lderr(cct) << "error removing image journal: " << cpp_strerror(r)
                        << dendl;
@@ -2121,7 +2121,7 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
       }
     }
     if (!old_format) {
-      r = Journal::remove(io_ctx, id);
+      r = Journal<>::remove(io_ctx, id);
       if (r < 0 && r != -ENOENT) {
         lderr(cct) << "error removing image journal" << dendl;
         return r;
index 8cc5375c2b33cf290ddb5edb836aa1b701b9483d..01847f02bd9ff77abce595a0b3cbf31ee4be6cfa 100644 (file)
 namespace librbd {
 namespace journal {
 
-Replay::Replay(ImageCtx &image_ctx)
-  : m_image_ctx(image_ctx), m_lock("Replay::m_lock"), m_ret_val(0) {
+template <typename I>
+Replay<I>::Replay(I &image_ctx)
+  : m_image_ctx(image_ctx), m_lock("Replay<I>::m_lock"), m_ret_val(0) {
 }
 
-Replay::~Replay() {
+template <typename I>
+Replay<I>::~Replay() {
   assert(m_aio_completions.empty());
 }
 
-int Replay::process(bufferlist::iterator it, Context *on_safe) {
+template <typename I>
+int Replay<I>::process(bufferlist::iterator it, Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << dendl;
 
@@ -39,7 +42,8 @@ int Replay::process(bufferlist::iterator it, Context *on_safe) {
   return 0;
 }
 
-int Replay::flush() {
+template <typename I>
+int Replay<I>::flush() {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << dendl;
 
@@ -50,8 +54,9 @@ int Replay::flush() {
   return m_ret_val;
 }
 
-void Replay::handle_event(const journal::AioDiscardEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::AioDiscardEvent &event,
+                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": AIO discard event" << dendl;
 
@@ -60,8 +65,9 @@ void Replay::handle_event(const journal::AioDiscardEvent &event,
                                event.length);
 }
 
-void Replay::handle_event(const journal::AioWriteEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::AioWriteEvent &event,
+                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": AIO write event" << dendl;
 
@@ -71,8 +77,9 @@ void Replay::handle_event(const journal::AioWriteEvent &event,
                              data.c_str(), 0);
 }
 
-void Replay::handle_event(const journal::AioFlushEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::AioFlushEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": AIO flush event" << dendl;
 
@@ -80,76 +87,88 @@ void Replay::handle_event(const journal::AioFlushEvent &event,
   AioImageRequest::aio_flush(&m_image_ctx, aio_comp);
 }
 
-  void Replay::handle_event(const journal::OpFinishEvent &event,
-                                  Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::OpFinishEvent &event,
+                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Op finish event" << dendl;
 }
 
-void Replay::handle_event(const journal::SnapCreateEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapCreateEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap create event" << dendl;
 }
 
-void Replay::handle_event(const journal::SnapRemoveEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapRemoveEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap remove event" << dendl;
 }
 
-void Replay::handle_event(const journal::SnapRenameEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapRenameEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap rename event" << dendl;
 }
 
-void Replay::handle_event(const journal::SnapProtectEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapProtectEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap protect event" << dendl;
 }
 
-void Replay::handle_event(const journal::SnapUnprotectEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapUnprotectEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap unprotect event"
                  << dendl;
 }
 
-void Replay::handle_event(const journal::SnapRollbackEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapRollbackEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap rollback start event"
                  << dendl;
 }
 
-void Replay::handle_event(const journal::RenameEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::RenameEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Rename event" << dendl;
 }
 
-void Replay::handle_event(const journal::ResizeEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::ResizeEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Resize start event" << dendl;
 }
 
-void Replay::handle_event(const journal::FlattenEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::FlattenEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Flatten start event" << dendl;
 }
 
-void Replay::handle_event(const journal::UnknownEvent &event,
-                                Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::UnknownEvent &event,
+                            Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": unknown event" << dendl;
   on_safe->complete(0);
 }
 
-AioCompletion *Replay::create_aio_completion(Context *on_safe) {
+template <typename I>
+AioCompletion *Replay<I>::create_aio_completion(Context *on_safe) {
   Mutex::Locker locker(m_lock);
   AioCompletion *aio_comp = AioCompletion::create(this, aio_completion_callback,
                                                   nullptr);
@@ -158,7 +177,8 @@ AioCompletion *Replay::create_aio_completion(Context *on_safe) {
   return aio_comp;
 }
 
-void Replay::handle_aio_completion(AioCompletion *aio_comp) {
+template <typename I>
+void Replay<I>::handle_aio_completion(AioCompletion *aio_comp) {
   Mutex::Locker locker(m_lock);
 
   AioCompletions::iterator it = m_aio_completions.find(aio_comp);
@@ -182,7 +202,8 @@ void Replay::handle_aio_completion(AioCompletion *aio_comp) {
     m_cond.Signal();
 }
 
-void Replay::aio_completion_callback(completion_t cb, void *arg) {
+template <typename I>
+void Replay<I>::aio_completion_callback(completion_t cb, void *arg) {
   Replay *replay = reinterpret_cast<Replay *>(arg);
   AioCompletion *aio_comp = reinterpret_cast<AioCompletion *>(cb);
 
@@ -192,3 +213,5 @@ void Replay::aio_completion_callback(completion_t cb, void *arg) {
 
 } // namespace journal
 } // namespace librbd
+
+template class librbd::journal::Replay<librbd::ImageCtx>;
index dc82745db1329cf222bc6980bf56d87cdeddf665..64882844bb5d23a9cdb86ae06d8bdf44c7c5d331 100644 (file)
@@ -20,9 +20,13 @@ class ImageCtx;
 
 namespace journal {
 
+template <typename ImageCtxT = ImageCtx>
 class Replay {
 public:
-  Replay(ImageCtx &image_ctx);
+  static Replay *create(ImageCtxT &image_ctx) {
+    return new Replay(image_ctx);
+  }
+
   ~Replay();
 
   int process(bufferlist::iterator it, Context *on_safe = NULL);
@@ -45,7 +49,7 @@ private:
     }
   };
 
-  ImageCtx &m_image_ctx;
+  ImageCtxT &m_image_ctx;
 
   Mutex m_lock;
   Cond m_cond;
@@ -53,6 +57,8 @@ private:
   AioCompletions m_aio_completions;
   int m_ret_val;
 
+  Replay(ImageCtxT &image_ctx);
+
   void handle_event(const AioDiscardEvent &event, Context *on_safe);
   void handle_event(const AioWriteEvent &event, Context *on_safe);
   void handle_event(const AioFlushEvent &event, Context *on_safe);
@@ -77,4 +83,6 @@ private:
 } // namespace journal
 } // namespace librbd
 
+extern template class librbd::journal::Replay<librbd::ImageCtx>;
+
 #endif // CEPH_LIBRBD_JOURNAL_REPLAY_H
index ab8d54e59831ccc92c0a9618f0915462833879ce..cbb895c4b805a900eb76a28b9518684f67bb3e45 100644 (file)
@@ -63,7 +63,7 @@ TEST_F(TestJournalReplay, AioDiscardEvent) {
 
   librbd::journal::EventEntry event_entry(
     librbd::journal::AioDiscardEvent(0, payload.size()));
-  librbd::Journal::AioObjectRequests requests;
+  librbd::Journal<>::AioObjectRequests requests;
   {
     RWLock::RLocker owner_locker(ictx->owner_lock);
     ictx->journal->append_io_event(NULL, event_entry, requests, 0, 0, true);
@@ -94,7 +94,7 @@ TEST_F(TestJournalReplay, AioWriteEvent) {
   payload_bl.append(payload);
   librbd::journal::EventEntry event_entry(
     librbd::journal::AioWriteEvent(0, payload.size(), payload_bl));
-  librbd::Journal::AioObjectRequests requests;
+  librbd::Journal<>::AioObjectRequests requests;
   {
     RWLock::RLocker owner_locker(ictx->owner_lock);
     ictx->journal->append_io_event(NULL, event_entry, requests, 0, 0, true);
@@ -124,14 +124,14 @@ TEST_F(TestJournalReplay, AioFlushEvent) {
 
   librbd::journal::AioFlushEvent aio_flush_event;
   librbd::journal::EventEntry event_entry(aio_flush_event);
-  librbd::Journal::AioObjectRequests requests;
+  librbd::Journal<>::AioObjectRequests requests;
   {
     RWLock::RLocker owner_locker(ictx->owner_lock);
     ictx->journal->append_io_event(NULL, event_entry, requests, 0, 0, true);
   }
 
   // start an AIO write op
-  librbd::Journal *journal = ictx->journal;
+  librbd::Journal<> *journal = ictx->journal;
   ictx->journal = NULL;
 
   std::string payload(m_image_size, '1');