From: Sage Weil Date: Fri, 11 Dec 2015 19:12:03 +0000 (-0500) Subject: db/log_test: add recycle log test X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ef126d8e614946702e44cf3902767cc19177fcaf;p=rocksdb.git db/log_test: add recycle log test This currently fails because we do not properly map a corrupt header to the logical end of the log. Signed-off-by: Sage Weil --- diff --git a/db/log_test.cc b/db/log_test.cc index 41f4c8223..a69c5ece8 100644 --- a/db/log_test.cc +++ b/db/log_test.cc @@ -174,6 +174,8 @@ class LogTest : public ::testing::TestWithParam { 3 * header_size; } + Slice* get_reader_contents() { return &reader_contents_; } + void Write(const std::string& msg) { writer_.AddRecord(Slice(msg)); } @@ -690,6 +692,29 @@ TEST_P(LogTest, ClearEofError2) { ASSERT_EQ("OK", MatchError("read error")); } +TEST_P(LogTest, Recycle) { + if (!GetParam()) { + return; // test is only valid for recycled logs + } + Write("foo"); + Write("bar"); + Write("baz"); + Write("bif"); + Write("blitz"); + while (get_reader_contents()->size() < log::kBlockSize * 2) { + Write("xxxxxxxxxxxxxxxx"); + } + unique_ptr dest_holder(test::GetWritableFileWriter( + new test::OverwritingStringSink(get_reader_contents()))); + Writer recycle_writer(std::move(dest_holder), 123, true); + recycle_writer.AddRecord(Slice("foooo")); + recycle_writer.AddRecord(Slice("bar")); + ASSERT_GE(get_reader_contents()->size(), log::kBlockSize * 2); + ASSERT_EQ("foooo", Read()); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("EOF", Read()); +} + INSTANTIATE_TEST_CASE_P(bool, LogTest, ::testing::Values(0, 2)); } // namespace log diff --git a/util/testutil.h b/util/testutil.h index 68e2f8c9e..e50b50ff7 100644 --- a/util/testutil.h +++ b/util/testutil.h @@ -231,6 +231,47 @@ class StringSink: public WritableFile { size_t last_flush_; }; +class OverwritingStringSink : public WritableFile { + public: + std::string contents_; + + explicit OverwritingStringSink(Slice* reader_contents) + : WritableFile(), + contents_(""), + reader_contents_(reader_contents), + last_flush_(0) {} + + const std::string& contents() const { return contents_; } + + virtual Status Truncate(uint64_t size) override { + contents_.resize(static_cast(size)); + return Status::OK(); + } + virtual Status Close() override { return Status::OK(); } + virtual Status Flush() override { + if (last_flush_ < contents_.size()) { + assert(reader_contents_->size() >= contents_.size()); + memcpy((char*)reader_contents_->data() + last_flush_, + contents_.data() + last_flush_, contents_.size() - last_flush_); + last_flush_ = contents_.size(); + } + return Status::OK(); + } + virtual Status Sync() override { return Status::OK(); } + virtual Status Append(const Slice& slice) override { + contents_.append(slice.data(), slice.size()); + return Status::OK(); + } + void Drop(size_t bytes) { + contents_.resize(contents_.size() - bytes); + if (last_flush_ > contents_.size()) last_flush_ = contents_.size(); + } + + private: + Slice* reader_contents_; + size_t last_flush_; +}; + class StringSource: public RandomAccessFile { public: explicit StringSource(const Slice& contents, uint64_t uniq_id = 0,