// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #pragma once #include #include "crimson/os/seastore/transaction_manager.h" namespace crimson::os::seastore { struct test_extent_desc_t { size_t len = 0; unsigned checksum = 0; bool operator==(const test_extent_desc_t &rhs) const { return (len == rhs.len && checksum == rhs.checksum); } bool operator!=(const test_extent_desc_t &rhs) const { return !(*this == rhs); } }; struct test_block_delta_t { int8_t val = 0; extent_len_t offset = 0; extent_len_t len = 0; DENC(test_block_delta_t, v, p) { DENC_START(1, 1, p); denc(v.val, p); denc(v.offset, p); denc(v.len, p); DENC_FINISH(p); } }; inline std::ostream &operator<<( std::ostream &lhs, const test_extent_desc_t &rhs) { return lhs << "test_extent_desc_t(len=0x" << std::hex << rhs.len << ", checksum=0x" << rhs.checksum << std::dec << ")"; } struct TestBlock : crimson::os::seastore::LogicalCachedExtent { constexpr static extent_len_t SIZE = 4<<10; using Ref = TCachedExtentRef; std::vector delta = {}; interval_set modified_region; explicit TestBlock(ceph::bufferptr &&ptr) : LogicalCachedExtent(std::move(ptr)) {} explicit TestBlock(extent_len_t length) : LogicalCachedExtent(length) {} TestBlock(const TestBlock &other) : LogicalCachedExtent(other), modified_region(other.modified_region) {} CachedExtentRef duplicate_for_write(Transaction&) final { return CachedExtentRef(new TestBlock(*this)); }; static constexpr extent_types_t TYPE = extent_types_t::TEST_BLOCK; extent_types_t get_type() const final { return TYPE; } ceph::bufferlist get_delta() final; void set_contents(char c, extent_len_t offset, extent_len_t len) { assert(offset + len <= get_length()); assert(len > 0); ::memset(get_bptr().c_str() + offset, c, len); delta.push_back({c, offset, len}); modified_region.union_insert(offset, len); } void set_contents(char c) { set_contents(c, 0, get_length()); } test_extent_desc_t get_desc() { return { get_length(), calc_crc32c() }; } void apply_delta(const ceph::bufferlist &bl) final; std::optional get_modified_region() final { if (modified_region.empty()) { return std::nullopt; } return modified_region_t{modified_region.range_start(), modified_region.range_end() - modified_region.range_start()}; } void clear_modified_region() final { modified_region.clear(); } void logical_on_delta_write() final { delta.clear(); } }; using TestBlockRef = TCachedExtentRef; struct TestBlockPhysical : crimson::os::seastore::CachedExtent{ constexpr static extent_len_t SIZE = 4<<10; using Ref = TCachedExtentRef; std::vector delta = {}; void on_rewrite(Transaction&, CachedExtent&, extent_len_t) final {} explicit TestBlockPhysical(ceph::bufferptr &&ptr) : CachedExtent(std::move(ptr)) {} explicit TestBlockPhysical(extent_len_t length) : CachedExtent(length) {} TestBlockPhysical(const TestBlockPhysical &other) : CachedExtent(other) {} CachedExtentRef duplicate_for_write(Transaction&) final { return CachedExtentRef(new TestBlockPhysical(*this)); }; static constexpr extent_types_t TYPE = extent_types_t::TEST_BLOCK_PHYSICAL; extent_types_t get_type() const final { return TYPE; } void set_contents(char c, extent_len_t offset, extent_len_t len) { ::memset(get_bptr().c_str() + offset, c, len); delta.push_back({c, offset, len}); } void set_contents(char c) { set_contents(c, 0, get_length()); } ceph::bufferlist get_delta() final; void apply_delta_and_adjust_crc(paddr_t, const ceph::bufferlist &bl) final; }; using TestBlockPhysicalRef = TCachedExtentRef; struct test_block_mutator_t { std::uniform_int_distribution contents_distribution = std::uniform_int_distribution( std::numeric_limits::min(), std::numeric_limits::max()); std::uniform_int_distribution offset_distribution = std::uniform_int_distribution( 0, TestBlock::SIZE - 1); std::uniform_int_distribution length_distribution(extent_len_t offset) { return std::uniform_int_distribution( 1, TestBlock::SIZE - offset); } template void mutate(TestBlock &block, generator_t &gen) { auto offset = offset_distribution(gen); block.set_contents( contents_distribution(gen), offset, length_distribution(offset)(gen)); } }; } WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::test_block_delta_t) #if FMT_VERSION >= 90000 template <> struct fmt::formatter : fmt::ostream_formatter {}; template <> struct fmt::formatter : fmt::ostream_formatter {}; template <> struct fmt::formatter : fmt::ostream_formatter {}; #endif