]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
hammer: test: add a data-storing MemWriteback for testing ObjectCacher
authorGreg Farnum <gfarnum@redhat.com>
Thu, 23 Jun 2016 20:41:46 +0000 (13:41 -0700)
committerAlexey Sheplyakov <asheplyakov@mirantis.com>
Mon, 21 Nov 2016 15:37:26 +0000 (18:37 +0300)
Signed-off-by: Greg Farnum <gfarnum@redhat.com>
(cherry picked from commit ed5801492bf2850e80a328ce5a61cb1ff2709215)

Hammer specific changes:

* use utime_t instead of ceph::real_time
* ObjectCacher::prepare_write() has no journal_tid argument
* rewrite code in C++98

src/test/CMakeLists.txt
src/test/Makefile.am
src/test/osdc/MemWriteback.cc [new file with mode: 0644]
src/test/osdc/MemWriteback.h [new file with mode: 0644]

index 73e80840949e0109f70ac061ea45776cb3fc9ee5..26831d89a7757f39884c211a1455ed469a0713af 100644 (file)
@@ -1640,6 +1640,7 @@ target_link_libraries(test_stress_watch
 add_executable(test_objectcacher_stress
   osdc/object_cacher_stress.cc
   osdc/FakeWriteback.cc
+  osdc/MemWriteback.cc
   $<TARGET_OBJECTS:heap_profiler_objs>
   )
 target_link_libraries(test_objectcacher_stress
index 4aa9b502d79a440de43707f9b0fc2a350147eb56..401c53d49d6945ea51b790346425674d0229f1f8 100644 (file)
@@ -393,7 +393,8 @@ check_SCRIPTS += test/pybind/test_ceph_argparse.py
 
 ceph_test_objectcacher_stress_SOURCES = \
        test/osdc/object_cacher_stress.cc \
-       test/osdc/FakeWriteback.cc
+       test/osdc/FakeWriteback.cc \
+       test/osdc/MemWriteback.cc
 ceph_test_objectcacher_stress_LDADD = $(LIBOSDC) $(CEPH_GLOBAL)
 bin_DEBUGPROGRAMS += ceph_test_objectcacher_stress
 
@@ -430,6 +431,7 @@ noinst_HEADERS += \
        test/ObjectMap/KeyValueDBMemory.h \
        test/omap_bench.h \
        test/osdc/FakeWriteback.h \
+       test/osdc/MemWriteback.h \
        test/osd/Object.h \
        test/osd/RadosModel.h \
        test/osd/TestOpStat.h \
diff --git a/src/test/osdc/MemWriteback.cc b/src/test/osdc/MemWriteback.cc
new file mode 100644 (file)
index 0000000..15e9cbe
--- /dev/null
@@ -0,0 +1,174 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+#include "common/debug.h"
+#include "common/Cond.h"
+#include "common/Finisher.h"
+#include "common/Mutex.h"
+#include "include/assert.h"
+
+#include "MemWriteback.h"
+
+#define dout_subsys ceph_subsys_objectcacher
+#undef dout_prefix
+#define dout_prefix *_dout << "MemWriteback(" << this << ") "
+
+static void sleep_ns(uint64_t delay_ns) {
+  struct timespec ts, remaining;
+  ts.tv_sec = delay_ns/1000000000ULL;
+  ts.tv_nsec = delay_ns%1000000000ULL;
+  while (nanosleep(&ts, &remaining) != 0) {
+    if (errno != EINTR) {
+      perror("nanosleep");
+      assert(NULL == "nanosleep failed");
+    }
+    memcpy(&ts, &remaining, sizeof(ts));
+  }
+}
+
+class C_DelayRead : public Context {
+  MemWriteback *wb;
+  CephContext *m_cct;
+  Context *m_con;
+  uint64_t m_delay;
+  Mutex *m_lock;
+  object_t m_oid;
+  uint64_t m_off;
+  uint64_t m_len;
+  bufferlist *m_bl;
+
+public:
+  C_DelayRead(MemWriteback *mwb, CephContext *cct, Context *c, Mutex *lock,
+             const object_t& oid, uint64_t off, uint64_t len, bufferlist *pbl,
+             uint64_t delay_ns=0)
+    : wb(mwb), m_cct(cct), m_con(c), m_delay(delay_ns),
+      m_lock(lock), m_oid(oid), m_off(off), m_len(len), m_bl(pbl) { }
+  void finish(int r) {
+    sleep_ns(m_delay);
+    m_lock->Lock();
+    r = wb->read_object_data(m_oid, m_off, m_len, m_bl);
+    if (m_con)
+      m_con->complete(r);
+    m_lock->Unlock();
+  }
+};
+
+class C_DelayWrite : public Context {
+  MemWriteback *wb;
+  CephContext *m_cct;
+  Context *m_con;
+  uint64_t m_delay;
+  Mutex *m_lock;
+  object_t m_oid;
+  uint64_t m_off;
+  uint64_t m_len;
+  const bufferlist& m_bl;
+
+public:
+  C_DelayWrite(MemWriteback *mwb, CephContext *cct, Context *c, Mutex *lock,
+              const object_t& oid, uint64_t off, uint64_t len,
+              const bufferlist& bl, uint64_t delay_ns=0)
+    : wb(mwb), m_cct(cct), m_con(c),
+      m_delay(delay_ns),
+      m_lock(lock), m_oid(oid), m_off(off), m_len(len), m_bl(bl) {}
+  void finish(int r) {
+    sleep_ns(m_delay);
+    m_lock->Lock();
+    wb->write_object_data(m_oid, m_off, m_len, m_bl);
+    if (m_con)
+      m_con->complete(r);
+    m_lock->Unlock();
+  }
+};
+
+MemWriteback::MemWriteback(CephContext *cct, Mutex *lock, uint64_t delay_ns)
+  : m_cct(cct), m_lock(lock), m_delay_ns(delay_ns)
+{
+  m_finisher = new Finisher(cct);
+  m_finisher->start();
+}
+
+MemWriteback::~MemWriteback()
+{
+  m_finisher->stop();
+  delete m_finisher;
+}
+
+void MemWriteback::read(const object_t& oid, uint64_t object_no,
+                        const object_locator_t& oloc,
+                        uint64_t off, uint64_t len, snapid_t snapid,
+                        bufferlist *pbl, uint64_t trunc_size,
+                        __u32 trunc_seq, int op_flags, Context *onfinish)
+{
+  assert(snapid == CEPH_NOSNAP);
+  C_DelayRead *wrapper = new C_DelayRead(this, m_cct, onfinish, m_lock, oid,
+                                        off, len, pbl, m_delay_ns);
+  m_finisher->queue(wrapper, len);
+}
+
+ceph_tid_t MemWriteback::write(const object_t& oid,
+                               const object_locator_t& oloc,
+                               uint64_t off, uint64_t len,
+                               const SnapContext& snapc,
+                               const bufferlist &bl, utime_t mtime,
+                               uint64_t trunc_size, __u32 trunc_seq,
+                               Context *oncommit)
+{
+  assert(snapc.seq == 0);
+  C_DelayWrite *wrapper = new C_DelayWrite(this, m_cct, oncommit, m_lock, oid,
+                                          off, len, bl, m_delay_ns);
+  m_finisher->queue(wrapper, 0);
+  return m_tid.inc();
+}
+
+void MemWriteback::write_object_data(const object_t& oid, uint64_t off, uint64_t len,
+                                    const bufferlist& data_bl)
+{
+  dout(1) << "writing " << oid << " " << off << "~" << len  << dendl;
+  assert(len == data_bl.length());
+  bufferlist& obj_bl = object_data[oid];
+  bufferlist new_obj_bl;
+  // ensure size, or set it if new object
+  if (off + len > obj_bl.length()) {
+    obj_bl.append_zero(off + len - obj_bl.length());
+  }
+
+  // beginning
+  new_obj_bl.substr_of(obj_bl, 0, off);
+  // overwritten bit
+  new_obj_bl.append(data_bl);
+  // tail bit
+  bufferlist tmp;
+  tmp.substr_of(obj_bl, off+len, obj_bl.length()-(off+len));
+  new_obj_bl.append(tmp);
+  obj_bl.swap(new_obj_bl);
+  dout(1) << oid << " final size " << obj_bl.length() << dendl;
+}
+
+int MemWriteback::read_object_data(const object_t& oid, uint64_t off, uint64_t len,
+                                  bufferlist *data_bl)
+{
+  dout(1) << "reading " << oid << " " << off << "~" << len << dendl;
+  std::map<object_t, bufferlist>::iterator obj_i = object_data.find(oid);
+  if (obj_i == object_data.end()) {
+    dout(1) << oid << "DNE!" << dendl;
+    return -ENOENT;
+  }
+
+  const bufferlist& obj_bl = obj_i->second;
+  dout(1) << "reading " << oid << " from total size " << obj_bl.length() << dendl;
+
+  uint64_t read_len = MIN(len, obj_bl.length()-off);
+  data_bl->substr_of(obj_bl, off, read_len);
+  return 0;
+}
+
+bool MemWriteback::may_copy_on_write(const object_t&, uint64_t, uint64_t,
+                                     snapid_t)
+{
+  return false;
+}
diff --git a/src/test/osdc/MemWriteback.h b/src/test/osdc/MemWriteback.h
new file mode 100644 (file)
index 0000000..ac86c2a
--- /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_TEST_OSDC_MEMWRITEBACK_H
+#define CEPH_TEST_OSDC_MEMWRITEBACK_H
+
+#include "include/atomic.h"
+#include "include/Context.h"
+#include "include/types.h"
+#include "osd/osd_types.h"
+#include "osdc/WritebackHandler.h"
+
+class Finisher;
+class Mutex;
+
+class MemWriteback : public WritebackHandler {
+public:
+  MemWriteback(CephContext *cct, Mutex *lock, uint64_t delay_ns);
+  virtual ~MemWriteback();
+
+  virtual void read(const object_t& oid, uint64_t object_no,
+                   const object_locator_t& oloc, uint64_t off, uint64_t len,
+                   snapid_t snapid, bufferlist *pbl, uint64_t trunc_size,
+                   __u32 trunc_seq, int op_flags, Context *onfinish);
+
+  virtual ceph_tid_t write(const object_t& oid, const object_locator_t& oloc,
+                          uint64_t off, uint64_t len,
+                          const SnapContext& snapc, const bufferlist &bl,
+                          utime_t mtime, uint64_t trunc_size,
+                          __u32 trunc_seq,
+                          Context *oncommit);
+
+  using WritebackHandler::write;
+
+  virtual bool may_copy_on_write(const object_t&, uint64_t, uint64_t,
+                                snapid_t);
+  void write_object_data(const object_t& oid, uint64_t off, uint64_t len,
+                        const bufferlist& data_bl);
+  int read_object_data(const object_t& oid, uint64_t off, uint64_t len,
+                      bufferlist *data_bl);
+private:
+  std::map<object_t, bufferlist> object_data;
+  CephContext *m_cct;
+  Mutex *m_lock;
+  uint64_t m_delay_ns;
+  atomic_t m_tid;
+  Finisher *m_finisher;
+};
+
+#endif