]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: separated queued object IO requests from state machine
authorJason Dillaman <dillaman@redhat.com>
Thu, 15 Feb 2018 18:07:00 +0000 (13:07 -0500)
committerJason Dillaman <dillaman@redhat.com>
Mon, 5 Mar 2018 14:37:58 +0000 (09:37 -0500)
This breaks the tight coupling between the journal and the actual
dispatch of object IO requests.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
21 files changed:
src/librbd/CMakeLists.txt
src/librbd/ImageCtx.cc
src/librbd/ImageCtx.h
src/librbd/Journal.cc
src/librbd/Journal.h
src/librbd/io/ImageRequest.cc
src/librbd/io/ImageRequest.h
src/librbd/io/ObjectDispatchSpec.cc [new file with mode: 0644]
src/librbd/io/ObjectDispatchSpec.h [new file with mode: 0644]
src/librbd/io/ObjectDispatcher.cc [new file with mode: 0644]
src/librbd/io/ObjectDispatcher.h [new file with mode: 0644]
src/librbd/io/ObjectRequest.cc
src/librbd/io/ObjectRequest.h
src/librbd/io/Types.h
src/test/librbd/io/test_mock_ImageRequest.cc
src/test/librbd/io/test_mock_ObjectRequest.cc
src/test/librbd/mock/MockImageCtx.h
src/test/librbd/mock/MockJournal.h
src/test/librbd/mock/io/MockObjectDispatcher.h [new file with mode: 0644]
src/test/librbd/operation/test_mock_TrimRequest.cc
src/test/librbd/test_mock_Journal.cc

index 36bb315b7f487ba0d473b29d19a15c5365834e34..aec82f011413f2787666dd66fb012f399fa87ebb 100644 (file)
@@ -60,6 +60,8 @@ set(librbd_internal_srcs
   io/ImageDispatchSpec.cc
   io/ImageRequest.cc
   io/ImageRequestWQ.cc
+  io/ObjectDispatchSpec.cc
+  io/ObjectDispatcher.cc
   io/ObjectRequest.cc
   io/ReadResult.cc
   io/Utils.cc
index 9f8939b39728a320b3ab10221d41903dae5d6a69..98c7892674339b3fdf5f192745c2d624b31bb0e8 100644 (file)
@@ -30,6 +30,7 @@
 #include "librbd/io/AioCompletion.h"
 #include "librbd/io/AsyncOperation.h"
 #include "librbd/io/ImageRequestWQ.h"
+#include "librbd/io/ObjectDispatcher.h"
 #include "librbd/journal/StandardPolicy.h"
 
 #include "osdc/Striper.h"
@@ -215,6 +216,7 @@ struct C_InvalidateCache : public Context {
       this, "librbd::io_work_queue",
       cct->_conf->get_val<int64_t>("rbd_op_thread_timeout"),
       thread_pool);
+    io_object_dispatcher = new io::ObjectDispatcher<>(this);
 
     if (cct->_conf->get_val<bool>("rbd_auto_exclusive_lock_until_manual_request")) {
       exclusive_lock_policy = new exclusive_lock::AutomaticPolicy(this);
@@ -252,6 +254,8 @@ struct C_InvalidateCache : public Context {
     data_ctx.aio_flush();
     io_work_queue->drain();
 
+    delete io_object_dispatcher;
+
     delete journal_policy;
     delete exclusive_lock_policy;
     delete io_work_queue;
index 5c7470f3048acd9bcdff8d3dbef7dd31b368194a..00732e3843c38d2a3ac2aacf4a5557774d7781ca 100644 (file)
@@ -54,6 +54,7 @@ namespace librbd {
   class AsyncOperation;
   template <typename> class CopyupRequest;
   template <typename> class ImageRequestWQ;
+  template <typename> class ObjectDispatcher;
   }
   namespace journal { struct Policy; }
 
@@ -158,6 +159,8 @@ namespace librbd {
     xlist<operation::ResizeRequest<ImageCtx>*> resize_reqs;
 
     io::ImageRequestWQ<ImageCtx> *io_work_queue;
+    io::ObjectDispatcher<ImageCtx> *io_object_dispatcher = nullptr;
+
     xlist<io::AioCompletion*> completed_reqs;
     EventSocket event_socket;
 
index 21eea0ef6eaa3838c9160e6ca912e13d1b3b5b31..848b81dbf142ffa5bac0d88f6de88babc7e451a8 100644 (file)
@@ -15,7 +15,8 @@
 #include "librbd/ExclusiveLock.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/io/ImageRequestWQ.h"
-#include "librbd/io/ObjectRequest.h"
+#include "librbd/io/ObjectDispatchSpec.h"
+#include "librbd/io/ObjectDispatcher.h"
 #include "librbd/journal/CreateRequest.h"
 #include "librbd/journal/DemoteRequest.h"
 #include "librbd/journal/OpenRequest.h"
@@ -1465,14 +1466,14 @@ void Journal<I>::handle_io_event_safe(int r, uint64_t tid) {
 
   ldout(cct, 20) << this << " " << __func__ << ": "
                  << "completing tid=" << tid << dendl;
-  for (IOObjectRequests::iterator it = aio_object_requests.begin();
-       it != aio_object_requests.end(); ++it) {
+  for (auto it = aio_object_requests.begin(); it != aio_object_requests.end();
+       ++it) {
     if (r < 0) {
       // don't send aio requests if the journal fails -- bubble error up
       (*it)->fail(r);
     } else {
       // send any waiting aio requests now that journal entry is safe
-      (*it)->send();
+      (*it)->send(tid);
     }
   }
 
index abe3723381fb35db96d15a9449abcc04a81e290c..088bde522da40d90e460d95b3b7aa3a14ad9ae16 100644 (file)
@@ -37,7 +37,7 @@ namespace librbd {
 
 class ImageCtx;
 
-namespace io { struct ObjectRequestHandle; }
+namespace io { struct ObjectDispatchSpec; }
 namespace journal { template <typename> class Replay; }
 
 template <typename ImageCtxT = ImageCtx>
@@ -91,7 +91,7 @@ public:
   static const std::string LOCAL_MIRROR_UUID;
   static const std::string ORPHAN_MIRROR_UUID;
 
-  typedef std::list<io::ObjectRequestHandle *> IOObjectRequests;
+  typedef std::list<io::ObjectDispatchSpec*> IOObjectRequests;
 
   Journal(ImageCtxT &image_ctx);
   ~Journal();
index ac479b74f9e7a24aac0500d9272f8e98c527a3bb..9ca06eda515e6be77e1886ebcd01e76fa44e8394 100644 (file)
@@ -10,6 +10,8 @@
 #include "librbd/cache/ImageCache.h"
 #include "librbd/io/AioCompletion.h"
 #include "librbd/io/ObjectRequest.h"
+#include "librbd/io/ObjectDispatchSpec.h"
+#include "librbd/io/ObjectDispatcher.h"
 #include "librbd/io/Utils.h"
 #include "librbd/journal/Types.h"
 #include "include/rados/librados.hpp"
@@ -263,7 +265,7 @@ void ImageReadRequest<I>::send_request() {
       auto req_comp = new io::ReadResult::C_ObjectReadRequest(
         aio_comp, extent.offset, extent.length,
         std::move(extent.buffer_extents), true);
-      ObjectReadRequest<I> *req = ObjectReadRequest<I>::create(
+      auto req = ObjectReadRequest<I>::create(
         &image_ctx, extent.oid.name, extent.objectno, extent.offset,
         extent.length, snap_id, m_op_flags, false, this->m_trace,
         &req_comp->bl, &req_comp->extent_map, req_comp);
@@ -376,15 +378,14 @@ void AbstractImageWriteRequest<I>::send_object_requests(
     ldout(cct, 20) << "oid " << p->oid << " " << p->offset << "~" << p->length
                    << " from " << p->buffer_extents << dendl;
     C_AioRequest *req_comp = new C_AioRequest(aio_comp);
-    ObjectRequestHandle *request = create_object_request(*p, snapc,
-                                                            req_comp);
+    auto request = create_object_request(*p, snapc, req_comp);
 
     // if journaling, stash the request for later; otherwise send
     if (request != NULL) {
       if (object_requests != NULL) {
         object_requests->push_back(request);
       } else {
-        request->send();
+        request->send(0);
       }
     }
   }
@@ -470,7 +471,7 @@ void ImageWriteRequest<I>::send_object_requests(
 }
 
 template <typename I>
-ObjectRequestHandle *ImageWriteRequest<I>::create_object_request(
+ObjectDispatchSpec *ImageWriteRequest<I>::create_object_request(
     const ObjectExtent &object_extent, const ::SnapContext &snapc,
     Context *on_finish) {
   I &image_ctx = this->m_image_ctx;
@@ -478,10 +479,10 @@ ObjectRequestHandle *ImageWriteRequest<I>::create_object_request(
 
   bufferlist bl;
   assemble_extent(object_extent, &bl);
-  ObjectRequest<I> *req = ObjectRequest<I>::create_write(
-    &image_ctx, object_extent.oid.name, object_extent.objectno,
-    object_extent.offset, std::move(bl), snapc, m_op_flags, this->m_trace,
-    on_finish);
+  auto req = ObjectDispatchSpec::create_write(
+    &image_ctx, OBJECT_DISPATCH_LAYER_NONE, object_extent.oid.name,
+    object_extent.objectno, object_extent.offset, std::move(bl), snapc,
+    m_op_flags, 0, this->m_trace, on_finish);
   return req;
 }
 
@@ -575,15 +576,14 @@ void ImageDiscardRequest<I>::send_object_cache_requests(
 }
 
 template <typename I>
-ObjectRequestHandle *ImageDiscardRequest<I>::create_object_request(
+ObjectDispatchSpec *ImageDiscardRequest<I>::create_object_request(
     const ObjectExtent &object_extent, const ::SnapContext &snapc,
     Context *on_finish) {
   I &image_ctx = this->m_image_ctx;
-
-  auto req = ObjectRequest<I>::create_discard(
-    &image_ctx, object_extent.oid.name, object_extent.objectno,
-    object_extent.offset, object_extent.length, snapc, true, true,
-    this->m_trace, on_finish);
+  auto req = ObjectDispatchSpec::create_discard(
+    &image_ctx, OBJECT_DISPATCH_LAYER_NONE, object_extent.oid.name,
+    object_extent.objectno, object_extent.offset, object_extent.length, snapc,
+    0, 0, this->m_trace, on_finish);
   return req;
 }
 
@@ -726,26 +726,29 @@ void ImageWriteSameRequest<I>::send_object_requests(
 }
 
 template <typename I>
-ObjectRequestHandle *ImageWriteSameRequest<I>::create_object_request(
+ObjectDispatchSpec *ImageWriteSameRequest<I>::create_object_request(
     const ObjectExtent &object_extent, const ::SnapContext &snapc,
     Context *on_finish) {
   I &image_ctx = this->m_image_ctx;
   assert(image_ctx.object_cacher == NULL);
 
   bufferlist bl;
-  ObjectRequest<I> *req;
+  ObjectDispatchSpec *req;
 
   if (util::assemble_write_same_extent(object_extent, m_data_bl, &bl, false)) {
-    req = ObjectRequest<I>::create_writesame(
-      &image_ctx, object_extent.oid.name, object_extent.objectno,
-      object_extent.offset, object_extent.length,
-      std::move(bl), snapc, m_op_flags, this->m_trace, on_finish);
+    Extents buffer_extents{object_extent.buffer_extents};
+
+    req = ObjectDispatchSpec::create_write_same(
+      &image_ctx, OBJECT_DISPATCH_LAYER_NONE, object_extent.oid.name,
+      object_extent.objectno, object_extent.offset, object_extent.length,
+      std::move(buffer_extents), std::move(bl), snapc, m_op_flags, 0,
+      this->m_trace, on_finish);
     return req;
   }
-  req = ObjectRequest<I>::create_write(
-    &image_ctx, object_extent.oid.name, object_extent.objectno,
-    object_extent.offset, std::move(bl), snapc, m_op_flags, this->m_trace,
-    on_finish);
+  req = ObjectDispatchSpec::create_write(
+    &image_ctx, OBJECT_DISPATCH_LAYER_NONE, object_extent.oid.name,
+    object_extent.objectno, object_extent.offset, std::move(bl), snapc,
+    m_op_flags, 0, this->m_trace, on_finish);
   return req;
 }
 
@@ -815,7 +818,7 @@ void ImageCompareAndWriteRequest<I>::send_image_cache_request() {
 }
 
 template <typename I>
-ObjectRequestHandle *ImageCompareAndWriteRequest<I>::create_object_request(
+ObjectDispatchSpec *ImageCompareAndWriteRequest<I>::create_object_request(
     const ObjectExtent &object_extent,
     const ::SnapContext &snapc,
     Context *on_finish) {
@@ -825,12 +828,11 @@ ObjectRequestHandle *ImageCompareAndWriteRequest<I>::create_object_request(
   // a single object
   bufferlist bl;
   assemble_extent(object_extent, &bl);
-  ObjectRequest<I> *req = ObjectRequest<I>::create_compare_and_write(
-                                  &image_ctx, object_extent.oid.name,
-                                  object_extent.objectno, object_extent.offset,
-                                  std::move(m_cmp_bl), std::move(bl), snapc,
-                                  m_mismatch_offset, m_op_flags, this->m_trace,
-                                  on_finish);
+  auto req = ObjectDispatchSpec::create_compare_and_write(
+    &image_ctx, OBJECT_DISPATCH_LAYER_NONE, object_extent.oid.name,
+    object_extent.objectno, object_extent.offset, std::move(m_cmp_bl),
+    std::move(bl), snapc, m_mismatch_offset, m_op_flags, 0, this->m_trace,
+    on_finish);
   return req;
 }
 
index 0a09b8b5fd91bf1a9f8352587ae9dca48e5ee194..f1d464eaaaa1e9b5c3890023750a10d97093fe5a 100644 (file)
@@ -21,7 +21,7 @@ class ImageCtx;
 namespace io {
 
 class AioCompletion;
-class ObjectRequestHandle;
+class ObjectDispatchSpec;
 class ReadResult;
 
 template <typename ImageCtxT = ImageCtx>
@@ -65,7 +65,7 @@ public:
   }
 
 protected:
-  typedef std::list<ObjectRequestHandle *> ObjectRequests;
+  typedef std::list<ObjectDispatchSpec*> ObjectRequests;
 
   ImageCtxT &m_image_ctx;
   AioCompletion *m_aio_comp;
@@ -151,7 +151,7 @@ protected:
   virtual void send_object_requests(const ObjectExtents &object_extents,
                                     const ::SnapContext &snapc,
                                     ObjectRequests *object_requests);
-  virtual ObjectRequestHandle *create_object_request(
+  virtual ObjectDispatchSpec *create_object_request(
       const ObjectExtent &object_extent, const ::SnapContext &snapc,
       Context *on_finish) = 0;
 
@@ -198,7 +198,7 @@ protected:
                             const ::SnapContext &snapc,
                             ObjectRequests *aio_object_requests) override;
 
-  ObjectRequestHandle *create_object_request(
+  ObjectDispatchSpec *create_object_request(
       const ObjectExtent &object_extent, const ::SnapContext &snapc,
       Context *on_finish) override;
 
@@ -241,7 +241,7 @@ protected:
   void send_object_cache_requests(const ObjectExtents &object_extents,
                                   uint64_t journal_tid) override;
 
-  ObjectRequestHandle *create_object_request(
+  ObjectDispatchSpec *create_object_request(
       const ObjectExtent &object_extent, const ::SnapContext &snapc,
       Context *on_finish) override;
 
@@ -314,7 +314,7 @@ protected:
   void send_object_requests(const ObjectExtents &object_extents,
                             const ::SnapContext &snapc,
                             ObjectRequests *object_requests) override;
-  ObjectRequestHandle *create_object_request(
+  ObjectDispatchSpec *create_object_request(
       const ObjectExtent &object_extent, const ::SnapContext &snapc,
       Context *on_finish) override;
 
@@ -350,9 +350,9 @@ protected:
 
   void assemble_extent(const ObjectExtent &object_extent, bufferlist *bl);
 
-  ObjectRequestHandle *create_object_request(const ObjectExtent &object_extent,
-                                             const ::SnapContext &snapc,
-                                             Context *on_finish) override;
+  ObjectDispatchSpec *create_object_request(
+      const ObjectExtent &object_extent, const ::SnapContext &snapc,
+      Context *on_finish) override;
 
   uint64_t append_journal_event(const ObjectRequests &requests,
                                 bool synchronous) override;
diff --git a/src/librbd/io/ObjectDispatchSpec.cc b/src/librbd/io/ObjectDispatchSpec.cc
new file mode 100644 (file)
index 0000000..14830a5
--- /dev/null
@@ -0,0 +1,66 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/io/ObjectDispatchSpec.h"
+#include "include/Context.h"
+#include "librbd/io/ObjectDispatcher.h"
+#include <boost/variant.hpp>
+
+namespace librbd {
+namespace io {
+
+void ObjectDispatchSpec::C_Dispatcher::complete(int r) {
+  if (r < 0) {
+    finish(r);
+    return;
+  }
+
+  switch (object_dispatch_spec->dispatch_result) {
+  case DISPATCH_RESULT_CONTINUE:
+    object_dispatch_spec->send(0);
+    break;
+  case DISPATCH_RESULT_COMPLETE:
+    finish(r);
+    break;
+  case DISPATCH_RESULT_INVALID:
+    assert(false);
+    break;
+  }
+}
+
+void ObjectDispatchSpec::C_Dispatcher::finish(int r) {
+  on_finish->complete(r);
+  delete object_dispatch_spec;
+}
+
+struct ObjectDispatchSpec::SetJournalTid : public boost::static_visitor<void> {
+  uint64_t journal_tid;
+
+  SetJournalTid(uint64_t journal_tid) : journal_tid(journal_tid) {
+  }
+
+  template <typename T>
+  void operator()(T& t) const {
+  }
+
+  void operator()(WriteRequestBase& write_request_base) const {
+    write_request_base.journal_tid = journal_tid;
+  }
+};
+
+void ObjectDispatchSpec::send(uint64_t journal_tid) {
+  // TODO removed in future commit
+  if (journal_tid != 0) {
+    boost::apply_visitor(SetJournalTid{journal_tid}, request);
+  }
+
+  object_dispatcher->send(this);
+}
+
+void ObjectDispatchSpec::fail(int r) {
+  assert(r < 0);
+  dispatcher_ctx.complete(r);
+}
+
+} // namespace io
+} // namespace librbd
diff --git a/src/librbd/io/ObjectDispatchSpec.h b/src/librbd/io/ObjectDispatchSpec.h
new file mode 100644 (file)
index 0000000..eddff49
--- /dev/null
@@ -0,0 +1,269 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_IO_OBJECT_DISPATCH_SPEC_H
+#define CEPH_LIBRBD_IO_OBJECT_DISPATCH_SPEC_H
+
+#include "include/int_types.h"
+#include "include/buffer.h"
+#include "include/Context.h"
+#include "include/rados/librados.hpp"
+#include "common/snap_types.h"
+#include "common/zipkin_trace.h"
+#include "librbd/io/Types.h"
+#include <boost/variant/variant.hpp>
+
+namespace librbd {
+namespace io {
+
+struct ObjectDispatcherInterface;
+
+struct ObjectDispatchSpec {
+private:
+  // helper to avoid extra heap allocation per object IO
+  struct C_Dispatcher : public Context {
+    ObjectDispatchSpec* object_dispatch_spec;
+    Context* on_finish;
+
+    C_Dispatcher(ObjectDispatchSpec* object_dispatch_spec, Context* on_finish)
+      : object_dispatch_spec(object_dispatch_spec), on_finish(on_finish) {
+    }
+
+    void complete(int r) override;
+    void finish(int r) override;
+  };
+
+public:
+  struct RequestBase {
+    std::string oid;
+    uint64_t object_no;
+    uint64_t object_off;
+
+    RequestBase(const std::string& oid, uint64_t object_no, uint64_t object_off)
+      : oid(oid), object_no(object_no), object_off(object_off) {
+    }
+  };
+
+  struct ReadRequest : public RequestBase {
+    uint64_t object_len;
+    librados::snap_t snap_id;
+    ceph::bufferlist* read_data;
+    ExtentMap* extent_map;
+
+    ReadRequest(const std::string& oid, uint64_t object_no, uint64_t object_off,
+                uint64_t object_len, librados::snap_t snap_id,
+                ceph::bufferlist* read_data, ExtentMap* extent_map)
+      : RequestBase(oid, object_no, object_off),
+        object_len(object_len), snap_id(snap_id), read_data(read_data),
+        extent_map(extent_map) {
+    }
+  };
+
+  struct WriteRequestBase : public RequestBase {
+    ::SnapContext snapc;
+    uint64_t journal_tid;
+
+    WriteRequestBase(const std::string& oid, uint64_t object_no,
+                     uint64_t object_off, const ::SnapContext& snapc,
+                     uint64_t journal_tid)
+      : RequestBase(oid, object_no, object_off), snapc(snapc),
+        journal_tid(journal_tid) {
+    }
+  };
+
+  struct DiscardRequest : public WriteRequestBase {
+    uint64_t object_len;
+    int discard_flags;
+
+    DiscardRequest(const std::string& oid, uint64_t object_no,
+                   uint64_t object_off, uint64_t object_len,
+                   int discard_flags, const ::SnapContext& snapc,
+                   uint64_t journal_tid)
+      : WriteRequestBase(oid, object_no, object_off, snapc, journal_tid),
+        object_len(object_len), discard_flags(discard_flags) {
+    }
+  };
+
+  struct WriteRequest : public WriteRequestBase {
+    ceph::bufferlist data;
+
+    WriteRequest(const std::string& oid, uint64_t object_no,
+                 uint64_t object_off, ceph::bufferlist&& data,
+                 const ::SnapContext& snapc, uint64_t journal_tid)
+      : WriteRequestBase(oid, object_no, object_off, snapc, journal_tid),
+        data(std::move(data)) {
+    }
+  };
+
+  struct WriteSameRequest : public WriteRequestBase {
+    uint64_t object_len;
+    Extents buffer_extents;
+    ceph::bufferlist data;
+
+    WriteSameRequest(const std::string& oid, uint64_t object_no,
+                     uint64_t object_off, uint64_t object_len,
+                     Extents&& buffer_extents, ceph::bufferlist&& data,
+                     const ::SnapContext& snapc, uint64_t journal_tid)
+    : WriteRequestBase(oid, object_no, object_off, snapc, journal_tid),
+      object_len(object_len), buffer_extents(std::move(buffer_extents)),
+      data(std::move(data)) {
+    }
+  };
+
+  struct CompareAndWriteRequest : public WriteRequestBase {
+    ceph::bufferlist cmp_data;
+    ceph::bufferlist data;
+    uint64_t* mismatch_offset;
+
+    CompareAndWriteRequest(const std::string& oid, uint64_t object_no,
+                           uint64_t object_off, ceph::bufferlist&& cmp_data,
+                           ceph::bufferlist&& data, uint64_t* mismatch_offset,
+                           const ::SnapContext& snapc, uint64_t journal_tid)
+      : WriteRequestBase(oid, object_no, object_off, snapc, journal_tid),
+        cmp_data(std::move(cmp_data)), data(std::move(data)),
+        mismatch_offset(mismatch_offset) {
+    }
+  };
+
+  struct FlushRequest {
+    FlushSource flush_source;
+
+    FlushRequest(FlushSource flush_source) : flush_source(flush_source) {
+    }
+  };
+
+  typedef boost::variant<ReadRequest,
+                         DiscardRequest,
+                         WriteRequest,
+                         WriteSameRequest,
+                         CompareAndWriteRequest,
+                         FlushRequest> Request;
+
+  C_Dispatcher dispatcher_ctx;
+
+  ObjectDispatcherInterface* object_dispatcher;
+  ObjectDispatchLayer object_dispatch_layer;
+  int object_dispatch_flags = 0;
+  DispatchResult dispatch_result = DISPATCH_RESULT_INVALID;
+
+  Request request;
+  int op_flags;
+  ZTracer::Trace parent_trace;
+
+  template <typename ImageCtxT>
+  static ObjectDispatchSpec* create_read(
+      ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer,
+      const std::string &oid, uint64_t object_no, uint64_t object_off,
+      uint64_t object_len, librados::snap_t snap_id, int op_flags,
+      const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
+      ExtentMap* extent_map, Context* on_finish) {
+    return new ObjectDispatchSpec(image_ctx->io_object_dispatcher,
+                                  object_dispatch_layer,
+                                  ReadRequest{oid, object_no, object_off,
+                                              object_len, snap_id, read_data,
+                                              extent_map},
+                                  op_flags, parent_trace, on_finish);
+  }
+
+  template <typename ImageCtxT>
+  static ObjectDispatchSpec* create_discard(
+      ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer,
+      const std::string &oid, uint64_t object_no, uint64_t object_off,
+      uint64_t object_len, const ::SnapContext &snapc, int discard_flags,
+      uint64_t journal_tid, const ZTracer::Trace &parent_trace,
+      Context *on_finish) {
+    return new ObjectDispatchSpec(image_ctx->io_object_dispatcher,
+                                  object_dispatch_layer,
+                                  DiscardRequest{oid, object_no, object_off,
+                                                 object_len, discard_flags,
+                                                 snapc, journal_tid},
+                                  0, parent_trace, on_finish);
+  }
+
+  template <typename ImageCtxT>
+  static ObjectDispatchSpec* create_write(
+      ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer,
+      const std::string &oid, uint64_t object_no, uint64_t object_off,
+      ceph::bufferlist&& data, const ::SnapContext &snapc, int op_flags,
+      uint64_t journal_tid, const ZTracer::Trace &parent_trace,
+      Context *on_finish) {
+    return new ObjectDispatchSpec(image_ctx->io_object_dispatcher,
+                                  object_dispatch_layer,
+                                  WriteRequest{oid, object_no, object_off,
+                                               std::move(data), snapc,
+                                               journal_tid},
+                                  op_flags, parent_trace, on_finish);
+  }
+
+  template <typename ImageCtxT>
+  static ObjectDispatchSpec* create_write_same(
+      ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer,
+      const std::string &oid, uint64_t object_no, uint64_t object_off,
+      uint64_t object_len, Extents&& buffer_extents,
+      ceph::bufferlist&& data, const ::SnapContext &snapc, int op_flags,
+      uint64_t journal_tid, const ZTracer::Trace &parent_trace,
+      Context *on_finish) {
+    return new ObjectDispatchSpec(image_ctx->io_object_dispatcher,
+                                  object_dispatch_layer,
+                                  WriteSameRequest{oid, object_no, object_off,
+                                                   object_len,
+                                                   std::move(buffer_extents),
+                                                   std::move(data), snapc,
+                                                   journal_tid},
+                                  op_flags, parent_trace, on_finish);
+  }
+
+  template <typename ImageCtxT>
+  static ObjectDispatchSpec* create_compare_and_write(
+      ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer,
+      const std::string &oid, uint64_t object_no, uint64_t object_off,
+      ceph::bufferlist&& cmp_data, ceph::bufferlist&& write_data,
+      const ::SnapContext &snapc, uint64_t *mismatch_offset, int op_flags,
+      uint64_t journal_tid, const ZTracer::Trace &parent_trace,
+      Context *on_finish) {
+    return new ObjectDispatchSpec(image_ctx->io_object_dispatcher,
+                                  object_dispatch_layer,
+                                  CompareAndWriteRequest{oid, object_no,
+                                                         object_off,
+                                                         std::move(cmp_data),
+                                                         std::move(write_data),
+                                                         mismatch_offset,
+                                                         snapc, journal_tid},
+                                  op_flags, parent_trace, on_finish);
+  }
+
+  template <typename ImageCtxT>
+  static ObjectDispatchSpec* create_flush(
+      ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer,
+      FlushSource flush_source, const ZTracer::Trace &parent_trace,
+      Context *on_finish) {
+    return new ObjectDispatchSpec(image_ctx->io_object_dispatcher,
+                                  object_dispatch_layer,
+                                  FlushRequest{flush_source}, 0,
+                                  parent_trace, on_finish);
+  }
+
+  void send(uint64_t journal_tid /* removed in future commit */);
+  void fail(int r);
+
+private:
+  template <typename> friend class ObjectDispatcher;
+
+  // TODO removed in future commmit
+  struct SetJournalTid;
+
+  ObjectDispatchSpec(ObjectDispatcherInterface* object_dispatcher,
+                     ObjectDispatchLayer object_dispatch_layer,
+                     Request&& request, int op_flags,
+                     const ZTracer::Trace& parent_trace, Context* on_finish)
+    : dispatcher_ctx(this, on_finish), object_dispatcher(object_dispatcher),
+      object_dispatch_layer(object_dispatch_layer), request(std::move(request)),
+      op_flags(op_flags), parent_trace(parent_trace) {
+  }
+
+};
+
+} // namespace io
+} // namespace librbd
+
+#endif // CEPH_LIBRBD_IO_OBJECT_DISPATCH_SPEC_H
diff --git a/src/librbd/io/ObjectDispatcher.cc b/src/librbd/io/ObjectDispatcher.cc
new file mode 100644 (file)
index 0000000..94620b2
--- /dev/null
@@ -0,0 +1,91 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/io/ObjectDispatcher.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/io/ObjectDispatchSpec.h"
+#include "librbd/io/ObjectRequest.h"
+#include <boost/variant.hpp>
+
+namespace librbd {
+namespace io {
+
+// TODO temporary implementation
+template <typename I>
+struct ObjectDispatcher<I>::SendVisitor
+  : public boost::static_visitor<void> {
+  ObjectDispatcher* object_dispatcher;
+  ObjectDispatchSpec* object_dispatch_spec;
+
+  SendVisitor(ObjectDispatcher* object_dispatcher,
+              ObjectDispatchSpec* object_dispatch_spec)
+    : object_dispatcher(object_dispatcher),
+      object_dispatch_spec(object_dispatch_spec)  {
+  }
+
+  void operator()(ObjectDispatchSpec::ReadRequest& read) const {
+    auto req = ObjectReadRequest<I>::create(
+      object_dispatcher->m_image_ctx, read.oid, read.object_no, read.object_off,
+      read.object_len, read.snap_id, object_dispatch_spec->op_flags, false,
+      object_dispatch_spec->parent_trace, read.read_data, read.extent_map,
+      &object_dispatch_spec->dispatcher_ctx);
+    req->send();
+  }
+
+  void operator()(ObjectDispatchSpec::DiscardRequest& discard) const {
+    auto req = ObjectRequest<I>::create_discard(
+      object_dispatcher->m_image_ctx, discard.oid, discard.object_no,
+      discard.object_off, discard.object_len, discard.snapc, true, true,
+      object_dispatch_spec->parent_trace,
+      &object_dispatch_spec->dispatcher_ctx);
+    req->send();
+  }
+
+  void operator()(ObjectDispatchSpec::WriteRequest& write) const {
+    auto req = ObjectRequest<I>::create_write(
+      object_dispatcher->m_image_ctx, write.oid, write.object_no,
+      write.object_off, std::move(write.data), write.snapc,
+      object_dispatch_spec->op_flags, object_dispatch_spec->parent_trace,
+      &object_dispatch_spec->dispatcher_ctx);
+    req->send();
+  }
+
+  void operator()(ObjectDispatchSpec::WriteSameRequest& write_same) const {
+    auto req = ObjectRequest<I>::create_write_same(
+      object_dispatcher->m_image_ctx, write_same.oid, write_same.object_no,
+      write_same.object_off, write_same.object_len, std::move(write_same.data),
+      write_same.snapc, object_dispatch_spec->op_flags,
+      object_dispatch_spec->parent_trace,
+      &object_dispatch_spec->dispatcher_ctx);
+    req->send();
+  }
+
+  void operator()(
+      ObjectDispatchSpec::CompareAndWriteRequest& compare_and_write) const {
+    auto req = ObjectRequest<I>::create_compare_and_write(
+      object_dispatcher->m_image_ctx, compare_and_write.oid,
+      compare_and_write.object_no, compare_and_write.object_off,
+      std::move(compare_and_write.cmp_data), std::move(compare_and_write.data),
+      compare_and_write.snapc, compare_and_write.mismatch_offset,
+      object_dispatch_spec->op_flags, object_dispatch_spec->parent_trace,
+      &object_dispatch_spec->dispatcher_ctx);
+    req->send();
+  }
+
+  void operator()(
+      ObjectDispatchSpec::FlushRequest& flush) const {
+  }
+};
+
+template <typename I>
+void ObjectDispatcher<I>::send(ObjectDispatchSpec* object_dispatch_spec) {
+  // TODO temporary implementation
+  object_dispatch_spec->dispatch_result = DISPATCH_RESULT_COMPLETE;
+  boost::apply_visitor(SendVisitor{this, object_dispatch_spec},
+                       object_dispatch_spec->request);
+}
+
+} // namespace io
+} // namespace librbd
+
+template class librbd::io::ObjectDispatcher<librbd::ImageCtx>;
diff --git a/src/librbd/io/ObjectDispatcher.h b/src/librbd/io/ObjectDispatcher.h
new file mode 100644 (file)
index 0000000..763c996
--- /dev/null
@@ -0,0 +1,49 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_IO_OBJECT_DISPATCHER_H
+#define CEPH_LIBRBD_IO_OBJECT_DISPATCHER_H
+
+#include "include/int_types.h"
+#include "librbd/io/Types.h"
+
+namespace librbd {
+
+struct ImageCtx;
+
+namespace io {
+
+struct ObjectDispatchSpec;
+
+struct ObjectDispatcherInterface {
+public:
+  virtual ~ObjectDispatcherInterface() {
+  }
+
+private:
+  friend class ObjectDispatchSpec;
+
+  virtual void send(ObjectDispatchSpec* object_dispatch_spec) = 0;
+};
+
+template <typename ImageCtxT = ImageCtx>
+class ObjectDispatcher : public ObjectDispatcherInterface {
+public:
+  ObjectDispatcher(ImageCtxT* image_ctx) : m_image_ctx(image_ctx) {
+  }
+
+private:
+  struct SendVisitor;
+
+  ImageCtxT* m_image_ctx;
+
+  void send(ObjectDispatchSpec* object_dispatch_spec);
+
+};
+
+} // namespace io
+} // namespace librbd
+
+extern template class librbd::io::ObjectDispatcher<librbd::ImageCtx>;
+
+#endif // CEPH_LIBRBD_IO_OBJECT_DISPATCHER_H
index e545a45c3632aa901ba1e46689ae6851d270396d..d2eeb1801df3c443b5cba713641b95efb30f9402 100644 (file)
@@ -76,7 +76,7 @@ ObjectRequest<I>::create_discard(I *ictx, const std::string &oid,
 
 template <typename I>
 ObjectRequest<I>*
-ObjectRequest<I>::create_writesame(I *ictx, const std::string &oid,
+ObjectRequest<I>::create_write_same(I *ictx, const std::string &oid,
                                    uint64_t object_no, uint64_t object_off,
                                    uint64_t object_len,
                                    ceph::bufferlist&& data,
index f51263326937d5283e376170ddb1ebccd57e05b2..ebb10f590a8b62f9b8362a17b9196589fd38822c 100644 (file)
@@ -25,74 +25,47 @@ namespace io {
 struct AioCompletion;
 template <typename> class CopyupRequest;
 
-struct ObjectRequestHandle {
-  virtual ~ObjectRequestHandle() {
-  }
-
-  virtual void fail(int r) = 0;
-  virtual void send() = 0;
-};
-
 /**
  * This class represents an I/O operation to a single RBD data object.
  * Its subclasses encapsulate logic for dealing with special cases
  * for I/O due to layering.
  */
 template <typename ImageCtxT = ImageCtx>
-class ObjectRequest : public ObjectRequestHandle {
+class ObjectRequest {
 public:
-  static ObjectRequest* create_write(ImageCtxT *ictx, const std::string &oid,
-                                     uint64_t object_no,
-                                     uint64_t object_off,
-                                     ceph::bufferlist&& data,
-                                     const ::SnapContext &snapc, int op_flags,
-                                    const ZTracer::Trace &parent_trace,
-                                     Context *completion);
-  static ObjectRequest* create_discard(ImageCtxT *ictx, const std::string &oid,
-                                       uint64_t object_no, uint64_t object_off,
-                                       uint64_t object_len,
-                                       const ::SnapContext &snapc,
-                                       bool disable_clone_remove,
-                                       bool update_object_map,
-                                       const ZTracer::Trace &parent_trace,
-                                       Context *completion);
-  static ObjectRequest* create_writesame(ImageCtxT *ictx,
-                                         const std::string &oid,
-                                         uint64_t object_no,
-                                         uint64_t object_off,
-                                         uint64_t object_len,
-                                         ceph::bufferlist&& data,
-                                         const ::SnapContext &snapc,
-                                        int op_flags,
-                                        const ZTracer::Trace &parent_trace,
-                                         Context *completion);
-  static ObjectRequest* create_compare_and_write(ImageCtxT *ictx,
-                                                 const std::string &oid,
-                                                 uint64_t object_no,
-                                                 uint64_t object_off,
-                                                 ceph::bufferlist&& cmp_data,
-                                                 ceph::bufferlist&& write_data,
-                                                 const ::SnapContext &snapc,
-                                                 uint64_t *mismatch_offset, int op_flags,
-                                                 const ZTracer::Trace &parent_trace,
-                                                 Context *completion);
+  static ObjectRequest* create_write(
+      ImageCtxT *ictx, const std::string &oid, uint64_t object_no,
+      uint64_t object_off, ceph::bufferlist&& data, const ::SnapContext &snapc,
+      int op_flags, const ZTracer::Trace &parent_trace, Context *completion);
+  static ObjectRequest* create_discard(
+      ImageCtxT *ictx, const std::string &oid, uint64_t object_no,
+      uint64_t object_off, uint64_t object_len, const ::SnapContext &snapc,
+      bool disable_clone_remove, bool update_object_map,
+      const ZTracer::Trace &parent_trace, Context *completion);
+  static ObjectRequest* create_write_same(
+      ImageCtxT *ictx, const std::string &oid, uint64_t object_no,
+      uint64_t object_off, uint64_t object_len, ceph::bufferlist&& data,
+      const ::SnapContext &snapc, int op_flags,
+      const ZTracer::Trace &parent_trace, Context *completion);
+  static ObjectRequest* create_compare_and_write(
+      ImageCtxT *ictx, const std::string &oid, uint64_t object_no,
+      uint64_t object_off, ceph::bufferlist&& cmp_data,
+      ceph::bufferlist&& write_data, const ::SnapContext &snapc,
+      uint64_t *mismatch_offset, int op_flags,
+      const ZTracer::Trace &parent_trace, Context *completion);
 
   ObjectRequest(ImageCtxT *ictx, const std::string &oid,
                 uint64_t objectno, uint64_t off, uint64_t len,
                 librados::snap_t snap_id, const char *trace_name,
                 const ZTracer::Trace &parent_trace, Context *completion);
-  ~ObjectRequest() override {
+  virtual ~ObjectRequest() {
     m_trace.event("finish");
   }
 
   static void add_write_hint(ImageCtxT& image_ctx,
                              librados::ObjectWriteOperation *wr);
 
-  void fail(int r) {
-    finish(r);
-  }
-
-  void send() override = 0;
+  virtual void send() = 0;
 
   bool has_parent() const {
     return m_has_parent;
index 93bddf8818c467f406759ed233de8156da919426..52a85cedbe9ab35e797041b5f0ffecdb5d9c3ac5 100644 (file)
@@ -36,6 +36,25 @@ enum Direction {
   DIRECTION_BOTH
 };
 
+enum DispatchResult {
+  DISPATCH_RESULT_INVALID,
+  DISPATCH_RESULT_CONTINUE,
+  DISPATCH_RESULT_COMPLETE
+};
+
+enum ObjectDispatchLayer {
+  OBJECT_DISPATCH_LAYER_NONE = 0,
+  OBJECT_DISPATCH_LAYER_CACHE,
+  OBJECT_DISPATCH_LAYER_JOURNAL,
+  OBJECT_DISPATCH_LAYER_CORE,
+  OBJECT_DISPATCH_LAYER_LAST
+};
+
+enum {
+  OBJECT_DISCARD_FLAG_DISABLE_CLONE_REMOVE      = 1UL << 0,
+  OBJECT_DISCARD_FLAG_DISABLE_OBJECT_MAP_UPDATE = 1UL << 1
+};
+
 typedef std::vector<std::pair<uint64_t, uint64_t> > Extents;
 typedef std::map<uint64_t, uint64_t> ExtentMap;
 
index 17ca3abd60463296709e1b47ac2888c349caa2de..34d2cd95a1008c5145eea8432e6fb6850d79b91d 100644 (file)
@@ -8,13 +8,37 @@
 #include "test/librbd/mock/cache/MockImageCache.h"
 #include "librbd/io/ImageRequest.h"
 #include "librbd/io/ObjectRequest.h"
+#include "librbd/io/ObjectDispatchSpec.h"
 
 namespace librbd {
 namespace {
 
+struct MockTestImageCtx;
+
+struct MockTestJournal : public MockJournal {
+  typedef std::list<io::ObjectDispatchSpec*> ObjectRequests;
+
+  MOCK_METHOD5(append_write_event, uint64_t(uint64_t, size_t,
+                                            const bufferlist &,
+                                            const ObjectRequests &, bool));
+  MOCK_METHOD6(append_io_event_mock, uint64_t(const journal::EventEntry&,
+                                              const ObjectRequests &,
+                                              uint64_t, size_t, bool, int));
+  uint64_t append_io_event(journal::EventEntry &&event_entry,
+                           const ObjectRequests &requests,
+                           uint64_t offset, size_t length,
+                           bool flush_entry, int filter_ret_val) {
+    // googlemock doesn't support move semantics
+    return append_io_event_mock(event_entry, requests, offset, length,
+                                flush_entry, filter_ret_val);
+  }
+};
+
 struct MockTestImageCtx : public MockImageCtx {
   MockTestImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
   }
+
+  MockTestJournal* journal;
 };
 
 } // anonymous namespace
@@ -30,88 +54,12 @@ inline ImageCtx *get_image_ctx(MockTestImageCtx *image_ctx) {
 namespace io {
 
 template <>
-struct ObjectRequest<librbd::MockTestImageCtx> : public ObjectRequestHandle {
-  static ObjectRequest* s_instance;
-  Context *on_finish = nullptr;
-
-  static ObjectRequest* create_write(librbd::MockTestImageCtx *ictx,
-                                     const std::string &oid,
-                                     uint64_t object_no,
-                                     uint64_t object_off,
-                                     const ceph::bufferlist &data,
-                                     const ::SnapContext &snapc, int op_flags,
-                                     const ZTracer::Trace &parent_trace,
-                                     Context *completion) {
-    assert(s_instance != nullptr);
-    s_instance->on_finish = completion;
-    return s_instance;
-  }
-
-  static ObjectRequest* create_discard(librbd::MockTestImageCtx *ictx,
-                                       const std::string &oid,
-                                       uint64_t object_no, uint64_t object_off,
-                                       uint64_t object_len,
-                                       const ::SnapContext &snapc,
-                                       bool disable_remove_on_clone,
-                                       bool update_object_map,
-                                       const ZTracer::Trace &parent_trace,
-                                       Context *completion) {
-    assert(s_instance != nullptr);
-    EXPECT_TRUE(disable_remove_on_clone);
-    EXPECT_TRUE(update_object_map);
-    s_instance->on_finish = completion;
-    return s_instance;
-  }
-
-  static ObjectRequest* create_writesame(librbd::MockTestImageCtx *ictx,
-                                         const std::string &oid,
-                                         uint64_t object_no,
-                                         uint64_t object_off,
-                                         uint64_t object_len,
-                                         const ceph::bufferlist &data,
-                                         const ::SnapContext &snapc,
-                                         int op_flags,
-                                         const ZTracer::Trace &parent_trace,
-                                         Context *completion) {
-    assert(s_instance != nullptr);
-    s_instance->on_finish = completion;
-    return s_instance;
-  }
-
-  static ObjectRequest* create_compare_and_write(librbd::MockTestImageCtx *ictx,
-                                                 const std::string &oid,
-                                                 uint64_t object_no,
-                                                 uint64_t object_off,
-                                                 const ceph::bufferlist &cmp_data,
-                                                 const ceph::bufferlist &write_data,
-                                                 const ::SnapContext &snapc,
-                                                 uint64_t *mismatch_offset,
-                                                 int op_flags,
-                                                 const ZTracer::Trace &parent_trace,
-                                                 Context *completion) {
-    assert(s_instance != nullptr);
-    s_instance->on_finish = completion;
-    return s_instance;
-  }
-
-  ObjectRequest() {
-    assert(s_instance == nullptr);
-    s_instance = this;
-  }
-  ~ObjectRequest() override {
-    s_instance = nullptr;
-  }
-
-  MOCK_METHOD0(send, void());
-  MOCK_METHOD1(fail, void(int));
-};
-
-template <>
-struct ObjectReadRequest<librbd::MockTestImageCtx> : public ObjectRequest<librbd::MockTestImageCtx> {
+struct ObjectReadRequest<librbd::MockTestImageCtx> {
   typedef std::vector<std::pair<uint64_t, uint64_t> > Extents;
   typedef std::map<uint64_t, uint64_t> ExtentMap;
 
   static ObjectReadRequest* s_instance;
+  Context* on_finish = nullptr;
 
   static ObjectReadRequest* create(librbd::MockTestImageCtx *ictx,
                                    const std::string &oid,
@@ -129,10 +77,12 @@ struct ObjectReadRequest<librbd::MockTestImageCtx> : public ObjectRequest<librbd
     assert(s_instance == nullptr);
     s_instance = this;
   }
-  ~ObjectReadRequest() override {
+  ~ObjectReadRequest() {
     s_instance = nullptr;
   }
 
+  MOCK_METHOD0(send, void());
+
   MOCK_CONST_METHOD0(get_offset, uint64_t());
   MOCK_CONST_METHOD0(get_length, uint64_t());
   MOCK_METHOD0(data, ceph::bufferlist &());
@@ -141,7 +91,6 @@ struct ObjectReadRequest<librbd::MockTestImageCtx> : public ObjectRequest<librbd
 
 };
 
-ObjectRequest<librbd::MockTestImageCtx>* ObjectRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
 ObjectReadRequest<librbd::MockTestImageCtx>* ObjectReadRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
 
 } // namespace io
@@ -157,6 +106,7 @@ using ::testing::InSequence;
 using ::testing::Invoke;
 using ::testing::Return;
 using ::testing::WithArg;
+using ::testing::WithoutArgs;
 
 struct TestMockIoImageRequest : public TestMockFixture {
   typedef ImageRequest<librbd::MockTestImageCtx> MockImageRequest;
@@ -165,10 +115,9 @@ struct TestMockIoImageRequest : public TestMockFixture {
   typedef ImageFlushRequest<librbd::MockTestImageCtx> MockImageFlushRequest;
   typedef ImageWriteSameRequest<librbd::MockTestImageCtx> MockImageWriteSameRequest;
   typedef ImageCompareAndWriteRequest<librbd::MockTestImageCtx> MockImageCompareAndWriteRequest;
-  typedef ObjectRequest<librbd::MockTestImageCtx> MockObjectRequest;
   typedef ObjectReadRequest<librbd::MockTestImageCtx> MockObjectReadRequest;
 
-  void expect_is_journal_appending(MockJournal &mock_journal, bool appending) {
+  void expect_is_journal_appending(MockTestJournal &mock_journal, bool appending) {
     EXPECT_CALL(mock_journal, is_journal_appending())
       .WillOnce(Return(appending));
   }
@@ -182,13 +131,12 @@ struct TestMockIoImageRequest : public TestMockFixture {
       .WillOnce(WithArg<4>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
   }
 
-  void expect_object_request_send(MockImageCtx &mock_image_ctx,
-                                  MockObjectRequest &mock_object_request,
+  void expect_object_request_send(MockTestImageCtx &mock_image_ctx,
                                   int r) {
-    EXPECT_CALL(mock_object_request, send())
-      .WillOnce(Invoke([&mock_image_ctx, &mock_object_request, r]() {
-                  mock_image_ctx.image_ctx->op_work_queue->queue(
-                    mock_object_request.on_finish, r);
+    EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, send(_))
+      .WillOnce(Invoke([&mock_image_ctx, r](ObjectDispatchSpec* spec) {
+                  spec->dispatch_result = io::DISPATCH_RESULT_COMPLETE;
+                  mock_image_ctx.image_ctx->op_work_queue->queue(&spec->dispatcher_ctx, r);
                 }));
   }
 
@@ -213,9 +161,8 @@ TEST_F(TestMockIoImageRequest, AioWriteJournalAppendDisabled) {
   librbd::ImageCtx *ictx;
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
 
-  MockObjectRequest mock_aio_object_request;
   MockTestImageCtx mock_image_ctx(*ictx);
-  MockJournal mock_journal;
+  MockTestJournal mock_journal;
   mock_image_ctx.journal = &mock_journal;
 
   InSequence seq;
@@ -224,7 +171,7 @@ TEST_F(TestMockIoImageRequest, AioWriteJournalAppendDisabled) {
     expect_write_to_cache(mock_image_ctx, ictx->get_object_name(0),
                           0, 1, 0, 0);
   } else {
-    expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
+    expect_object_request_send(mock_image_ctx, 0);
   }
 
   C_SaferCond aio_comp_ctx;
@@ -248,15 +195,14 @@ TEST_F(TestMockIoImageRequest, AioDiscardJournalAppendDisabled) {
   librbd::ImageCtx *ictx;
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
 
-  MockObjectRequest mock_aio_object_request;
   MockTestImageCtx mock_image_ctx(*ictx);
-  MockJournal mock_journal;
+  MockTestJournal mock_journal;
   mock_image_ctx.journal = &mock_journal;
 
   InSequence seq;
   expect_is_journal_appending(mock_journal, false);
   if (!ictx->skip_partial_discard) {
-    expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
+    expect_object_request_send(mock_image_ctx, 0);
   }
 
   C_SaferCond aio_comp_ctx;
@@ -280,7 +226,7 @@ TEST_F(TestMockIoImageRequest, AioFlushJournalAppendDisabled) {
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
 
   MockTestImageCtx mock_image_ctx(*ictx);
-  MockJournal mock_journal;
+  MockTestJournal mock_journal;
   mock_image_ctx.journal = &mock_journal;
 
   InSequence seq;
@@ -307,9 +253,8 @@ TEST_F(TestMockIoImageRequest, AioWriteSameJournalAppendDisabled) {
   librbd::ImageCtx *ictx;
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
 
-  MockObjectRequest mock_aio_object_request;
   MockTestImageCtx mock_image_ctx(*ictx);
-  MockJournal mock_journal;
+  MockTestJournal mock_journal;
   mock_image_ctx.journal = &mock_journal;
 
   InSequence seq;
@@ -318,7 +263,7 @@ TEST_F(TestMockIoImageRequest, AioWriteSameJournalAppendDisabled) {
     expect_write_to_cache(mock_image_ctx, ictx->get_object_name(0),
                           0, 1, 0, 0);
   } else {
-    expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
+    expect_object_request_send(mock_image_ctx, 0);
   }
 
 
@@ -344,14 +289,13 @@ TEST_F(TestMockIoImageRequest, AioCompareAndWriteJournalAppendDisabled) {
   librbd::ImageCtx *ictx;
   ASSERT_EQ(0, open_image(m_image_name, &ictx));
 
-  MockObjectRequest mock_aio_object_request;
   MockTestImageCtx mock_image_ctx(*ictx);
-  MockJournal mock_journal;
+  MockTestJournal mock_journal;
   mock_image_ctx.journal = &mock_journal;
 
   InSequence seq;
   expect_is_journal_appending(mock_journal, false);
-  expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
+  expect_object_request_send(mock_image_ctx, 0);
 
   C_SaferCond aio_comp_ctx;
   AioCompletion *aio_comp = AioCompletion::create_and_start(
index a90031e6eb04d15b650f6e919d8887f82a138229..ad850ab9dd01dbc70a44f7e363d9ecaef8d99bc4 100644 (file)
@@ -1161,7 +1161,7 @@ TEST_F(TestMockIoObjectRequest, WriteSame) {
   expect_writesame(mock_image_ctx, 0, 4096, 0);
 
   C_SaferCond ctx;
-  auto req = MockObjectWriteSameRequest::create_writesame(
+  auto req = MockObjectWriteSameRequest::create_write_same(
     &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, std::move(bl),
     mock_image_ctx.snapc, 0, {}, &ctx);
   req->send();
index 9c060d32a50bc3b94e838d758a54723decd18a71..1770036698b4c4ccb6af2e34d92785801b3cb4ee 100644 (file)
@@ -14,6 +14,7 @@
 #include "test/librbd/mock/MockOperations.h"
 #include "test/librbd/mock/MockReadahead.h"
 #include "test/librbd/mock/io/MockImageRequestWQ.h"
+#include "test/librbd/mock/io/MockObjectDispatcher.h"
 #include "common/RWLock.h"
 #include "common/WorkQueue.h"
 #include "common/zipkin_trace.h"
@@ -84,6 +85,7 @@ struct MockImageCtx {
       group_spec(image_ctx.group_spec),
       layout(image_ctx.layout),
       io_work_queue(new io::MockImageRequestWQ()),
+      io_object_dispatcher(new io::MockObjectDispatcher()),
       op_work_queue(new MockContextWQ()),
       readahead_max_bytes(image_ctx.readahead_max_bytes),
       event_socket(image_ctx.event_socket),
@@ -132,6 +134,7 @@ struct MockImageCtx {
     delete image_watcher;
     delete op_work_queue;
     delete io_work_queue;
+    delete io_object_dispatcher;
   }
 
   void wait_for_async_requests() {
@@ -287,6 +290,7 @@ struct MockImageCtx {
   std::map<uint64_t, io::CopyupRequest<MockImageCtx>*> copyup_list;
 
   io::MockImageRequestWQ *io_work_queue;
+  io::MockObjectDispatcher *io_object_dispatcher;
   MockContextWQ *op_work_queue;
 
   cache::MockImageCache *image_cache = nullptr;
index a0909e34c1d4fb16d808398f12be7dcb7ff5233d..60a316bbf0af15cf4ee59150944ff4433611ebc9 100644 (file)
@@ -16,11 +16,8 @@ namespace librados { class IoCtx; }
 namespace librbd {
 
 struct ImageCtx;
-namespace io { struct ObjectRequestHandle; }
 
 struct MockJournal {
-  typedef std::list<io::ObjectRequestHandle *> ObjectRequests;
-
   static MockJournal *s_instance;
   static MockJournal *get_instance() {
     assert(s_instance != nullptr);
@@ -68,21 +65,6 @@ struct MockJournal {
 
   MOCK_METHOD0(allocate_op_tid, uint64_t());
 
-  MOCK_METHOD5(append_write_event, uint64_t(uint64_t, size_t,
-                                            const bufferlist &,
-                                            const ObjectRequests &, bool));
-  MOCK_METHOD6(append_io_event_mock, uint64_t(const journal::EventEntry&,
-                                              const ObjectRequests &,
-                                              uint64_t, size_t, bool, int));
-  uint64_t append_io_event(journal::EventEntry &&event_entry,
-                           const ObjectRequests &requests,
-                           uint64_t offset, size_t length,
-                           bool flush_entry, int filter_ret_val) {
-    // googlemock doesn't support move semantics
-    return append_io_event_mock(event_entry, requests, offset, length,
-                                flush_entry, filter_ret_val);
-  }
-
   MOCK_METHOD3(append_op_event_mock, void(uint64_t, const journal::EventEntry&,
                                           Context *));
   void append_op_event(uint64_t op_tid, journal::EventEntry &&event_entry,
diff --git a/src/test/librbd/mock/io/MockObjectDispatcher.h b/src/test/librbd/mock/io/MockObjectDispatcher.h
new file mode 100644 (file)
index 0000000..1c8f9b9
--- /dev/null
@@ -0,0 +1,27 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_TEST_LIBRBD_MOCK_IO_OBJECT_DISPATCHER_H
+#define CEPH_TEST_LIBRBD_MOCK_IO_OBJECT_DISPATCHER_H
+
+#include "gmock/gmock.h"
+#include "include/Context.h"
+#include "librbd/io/ObjectDispatcher.h"
+#include "librbd/io/ObjectDispatchSpec.h"
+#include "librbd/io/Types.h"
+
+class Context;
+
+namespace librbd {
+namespace io {
+
+struct MockObjectDispatcher : public ObjectDispatcherInterface {
+public:
+  MOCK_METHOD1(send, void(ObjectDispatchSpec*));
+
+};
+
+} // namespace io
+} // namespace librbd
+
+#endif // CEPH_TEST_LIBRBD_MOCK_IO_OBJECT_DISPATCHER_H
index 9509b203fda1a050d3771764c3be722b61648469..d66681005217ed23008b849de0da701d8127d0c9 100644 (file)
@@ -67,7 +67,7 @@ struct AsyncRequest<librbd::MockTestImageCtx> {
 namespace io {
 
 template <>
-struct ObjectRequest<librbd::MockTestImageCtx> : public ObjectRequestHandle {
+struct ObjectRequest<librbd::MockTestImageCtx> {
   static ObjectRequest* s_instance;
   Context *on_finish = nullptr;
 
@@ -94,7 +94,6 @@ struct ObjectRequest<librbd::MockTestImageCtx> : public ObjectRequestHandle {
 
   MOCK_METHOD3(construct, void(uint64_t, uint64_t, bool));
   MOCK_METHOD0(send, void());
-  MOCK_METHOD1(fail, void(int));
 };
 
 ObjectRequest<librbd::MockTestImageCtx>* ObjectRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
index 7cf231d679b364530fde7e121b714a7e7785bf84..bcc31a2706b511fb4681d8f8ed385377ea78c6bc 100644 (file)
@@ -13,7 +13,7 @@
 #include "librbd/Journal.h"
 #include "librbd/Utils.h"
 #include "librbd/io/AioCompletion.h"
-#include "librbd/io/ObjectRequest.h"
+#include "librbd/io/ObjectDispatchSpec.h"
 #include "librbd/journal/Replay.h"
 #include "librbd/journal/RemoveRequest.h"
 #include "librbd/journal/CreateRequest.h"
@@ -426,7 +426,7 @@ public:
 
   uint64_t when_append_io_event(MockJournalImageCtx &mock_image_ctx,
                                 MockJournal &mock_journal,
-                                io::ObjectRequest<> *object_request,
+                                io::ObjectDispatchSpec *object_request,
                                 int filter_ret_val) {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
     MockJournal::IOObjectRequests object_requests;
@@ -1032,9 +1032,9 @@ TEST_F(TestMockJournal, EventCommitError) {
   };
 
   C_SaferCond object_request_ctx;
-  auto object_request = new io::ObjectDiscardRequest<>(
-    ictx, "oid", 0, 0, ictx->layout.object_size, {}, true, true, {},
-    &object_request_ctx);
+  auto object_request = io::ObjectDispatchSpec::create_discard(
+    &mock_image_ctx, io::OBJECT_DISPATCH_LAYER_NONE, "object0", 0, 0, 0, {}, 0,
+    0, {}, &object_request_ctx);
 
   ::journal::MockFuture mock_future;
   Context *on_journal_safe;
@@ -1074,9 +1074,9 @@ TEST_F(TestMockJournal, EventCommitErrorWithPendingWriteback) {
   };
 
   C_SaferCond object_request_ctx;
-  auto object_request = new io::ObjectDiscardRequest<>(
-    ictx, "oid", 0, 0, ictx->layout.object_size, {}, true, true, {},
-    &object_request_ctx);
+  auto object_request = io::ObjectDispatchSpec::create_discard(
+    &mock_image_ctx, io::OBJECT_DISPATCH_LAYER_NONE, "object0", 0, 0, 0, {}, 0,
+    0, {}, &object_request_ctx);
 
   ::journal::MockFuture mock_future;
   Context *on_journal_safe;