From ff3635a5457ac89ea0fb02f40f0ca723fe34e87c Mon Sep 17 00:00:00 2001 From: Greg Farnum Date: Thu, 23 Jun 2016 13:41:46 -0700 Subject: [PATCH] hammer: test: add a data-storing MemWriteback for testing ObjectCacher Signed-off-by: Greg Farnum (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 | 1 + src/test/Makefile.am | 4 +- src/test/osdc/MemWriteback.cc | 174 ++++++++++++++++++++++++++++++++++ src/test/osdc/MemWriteback.h | 49 ++++++++++ 4 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 src/test/osdc/MemWriteback.cc create mode 100644 src/test/osdc/MemWriteback.h diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 73e80840949e0..26831d89a7757 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -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_link_libraries(test_objectcacher_stress diff --git a/src/test/Makefile.am b/src/test/Makefile.am index 4aa9b502d79a4..401c53d49d694 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -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 index 0000000000000..15e9cbeb09f50 --- /dev/null +++ b/src/test/osdc/MemWriteback.cc @@ -0,0 +1,174 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include +#include +#include + +#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::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 index 0000000000000..ac86c2ad1b143 --- /dev/null +++ b/src/test/osdc/MemWriteback.h @@ -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_data; + CephContext *m_cct; + Mutex *m_lock; + uint64_t m_delay_ns; + atomic_t m_tid; + Finisher *m_finisher; +}; + +#endif -- 2.39.5