]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/crimson/seastore/onode_tree/test_value.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / crimson / seastore / onode_tree / test_value.h
CommitLineData
20effc67
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
2// vim: ts=8 sw=2 smarttab
3
4#pragma once
5
2a845540
TL
6#include <fmt/format.h>
7
20effc67
TL
8#include "crimson/common/log.h"
9#include "crimson/os/seastore/onode_manager/staged-fltree/value.h"
10
11namespace crimson::os::seastore::onode {
12
13struct test_item_t {
14 using id_t = uint16_t;
15 using magic_t = uint32_t;
16
17 value_size_t size;
18 id_t id;
19 magic_t magic;
20
21 value_size_t get_payload_size() const {
22 assert(size > sizeof(value_header_t));
23 return static_cast<value_size_t>(size - sizeof(value_header_t));
24 }
25
26 static test_item_t create(std::size_t _size, std::size_t _id) {
27 ceph_assert(_size <= std::numeric_limits<value_size_t>::max());
28 ceph_assert(_size > sizeof(value_header_t));
29 value_size_t size = _size;
30
31 ceph_assert(_id <= std::numeric_limits<id_t>::max());
32 id_t id = _id;
33
34 return {size, id, (magic_t)id * 137};
35 }
36};
37inline std::ostream& operator<<(std::ostream& os, const test_item_t& item) {
38 return os << "TestItem(#" << item.id << ", " << item.size << "B)";
39}
40
2a845540
TL
41enum class delta_op_t : uint8_t {
42 UPDATE_ID,
43 UPDATE_TAIL_MAGIC,
44};
45
46inline std::ostream& operator<<(std::ostream& os, const delta_op_t op) {
47 switch (op) {
48 case delta_op_t::UPDATE_ID:
49 return os << "update_id";
50 case delta_op_t::UPDATE_TAIL_MAGIC:
51 return os << "update_tail_magic";
52 default:
53 return os << "unknown";
54 }
55}
56
1e59de90
TL
57} // namespace crimson::os::seastore::onode
58
59#if FMT_VERSION >= 90000
60template<> struct fmt::formatter<crimson::os::seastore::onode::delta_op_t> : fmt::ostream_formatter {};
61#endif
62
63namespace crimson::os::seastore::onode {
64
20effc67
TL
65template <value_magic_t MAGIC,
66 string_size_t MAX_NS_SIZE,
67 string_size_t MAX_OID_SIZE,
68 value_size_t MAX_VALUE_PAYLOAD_SIZE,
69 extent_len_t INTERNAL_NODE_SIZE,
70 extent_len_t LEAF_NODE_SIZE,
71 bool DO_SPLIT_CHECK>
72class TestValue final : public Value {
73 public:
74 static constexpr tree_conf_t TREE_CONF = {
75 MAGIC,
76 MAX_NS_SIZE,
77 MAX_OID_SIZE,
78 MAX_VALUE_PAYLOAD_SIZE,
79 INTERNAL_NODE_SIZE,
80 LEAF_NODE_SIZE,
81 DO_SPLIT_CHECK
82 };
83
84 using id_t = test_item_t::id_t;
85 using magic_t = test_item_t::magic_t;
86 struct magic_packed_t {
87 magic_t value;
88 } __attribute__((packed));
89
90 private:
91 struct payload_t {
92 id_t id;
93 } __attribute__((packed));
94
95 struct Replayable {
96 static void set_id(NodeExtentMutable& payload_mut, id_t id) {
97 auto p_payload = get_write(payload_mut);
98 p_payload->id = id;
99 }
100
101 static void set_tail_magic(NodeExtentMutable& payload_mut, magic_t magic) {
102 auto length = payload_mut.get_length();
103 auto offset_magic = length - sizeof(magic_t);
104 payload_mut.copy_in_relative(offset_magic, magic);
105 }
106
107 private:
108 static payload_t* get_write(NodeExtentMutable& payload_mut) {
109 return reinterpret_cast<payload_t*>(payload_mut.get_write());
110 }
111 };
112
113 public:
114 class Recorder final : public ValueDeltaRecorder {
20effc67
TL
115
116 public:
117 Recorder(ceph::bufferlist& encoded)
118 : ValueDeltaRecorder(encoded) {}
119 ~Recorder() override = default;
120
121 void encode_set_id(NodeExtentMutable& payload_mut, id_t id) {
122 auto& encoded = get_encoded(payload_mut);
123 ceph::encode(delta_op_t::UPDATE_ID, encoded);
124 ceph::encode(id, encoded);
125 }
126
127 void encode_set_tail_magic(NodeExtentMutable& payload_mut, magic_t magic) {
128 auto& encoded = get_encoded(payload_mut);
129 ceph::encode(delta_op_t::UPDATE_TAIL_MAGIC, encoded);
130 ceph::encode(magic, encoded);
131 }
132
133 protected:
134 value_magic_t get_header_magic() const override {
135 return TREE_CONF.value_magic;
136 }
137
138 void apply_value_delta(ceph::bufferlist::const_iterator& delta,
139 NodeExtentMutable& payload_mut,
140 laddr_t value_addr) override {
141 delta_op_t op;
142 try {
143 ceph::decode(op, delta);
144 switch (op) {
145 case delta_op_t::UPDATE_ID: {
146 logger().debug("OTree::TestValue::Replay: decoding UPDATE_ID ...");
147 id_t id;
148 ceph::decode(id, delta);
149 logger().debug("OTree::TestValue::Replay: apply id={} ...", id);
150 Replayable::set_id(payload_mut, id);
151 break;
152 }
153 case delta_op_t::UPDATE_TAIL_MAGIC: {
154 logger().debug("OTree::TestValue::Replay: decoding UPDATE_TAIL_MAGIC ...");
155 magic_t magic;
156 ceph::decode(magic, delta);
157 logger().debug("OTree::TestValue::Replay: apply magic={} ...", magic);
158 Replayable::set_tail_magic(payload_mut, magic);
159 break;
160 }
161 default:
162 logger().error("OTree::TestValue::Replay: got unknown op {} when replay {:#x}+{:#x}",
163 op, value_addr, payload_mut.get_length());
164 ceph_abort();
165 }
166 } catch (buffer::error& e) {
167 logger().error("OTree::TestValue::Replay: got decode error {} when replay {:#x}+{:#x}",
1e59de90 168 e.what(), value_addr, payload_mut.get_length());
20effc67
TL
169 ceph_abort();
170 }
171 }
172
173 private:
174 seastar::logger& logger() {
175 return crimson::get_logger(ceph_subsys_test);
176 }
177 };
178
179 TestValue(NodeExtentManager& nm, const ValueBuilder& vb, Ref<tree_cursor_t>& p_cursor)
180 : Value(nm, vb, p_cursor) {}
181 ~TestValue() override = default;
182
183 id_t get_id() const {
184 return read_payload<payload_t>()->id;
185 }
186 void set_id_replayable(Transaction& t, id_t id) {
187 auto value_mutable = prepare_mutate_payload<payload_t, Recorder>(t);
188 if (value_mutable.second) {
189 value_mutable.second->encode_set_id(value_mutable.first, id);
190 }
191 Replayable::set_id(value_mutable.first, id);
192 }
193
194 magic_t get_tail_magic() const {
195 auto p_payload = read_payload<payload_t>();
196 auto offset_magic = get_payload_size() - sizeof(magic_t);
197 auto p_magic = reinterpret_cast<const char*>(p_payload) + offset_magic;
198 return reinterpret_cast<const magic_packed_t*>(p_magic)->value;
199 }
200 void set_tail_magic_replayable(Transaction& t, magic_t magic) {
201 auto value_mutable = prepare_mutate_payload<payload_t, Recorder>(t);
202 if (value_mutable.second) {
203 value_mutable.second->encode_set_tail_magic(value_mutable.first, magic);
204 }
205 Replayable::set_tail_magic(value_mutable.first, magic);
206 }
207
208 /*
209 * tree_util.h related interfaces
210 */
211
212 using item_t = test_item_t;
213
214 void initialize(Transaction& t, const item_t& item) {
215 ceph_assert(get_payload_size() + sizeof(value_header_t) == item.size);
216 set_id_replayable(t, item.id);
217 set_tail_magic_replayable(t, item.magic);
218 }
219
220 void validate(const item_t& item) const {
221 ceph_assert(get_payload_size() + sizeof(value_header_t) == item.size);
222 ceph_assert(get_id() == item.id);
223 ceph_assert(get_tail_magic() == item.magic);
224 }
225};
226
227using UnboundedValue = TestValue<
228 value_magic_t::TEST_UNBOUND, 4096, 4096, 4096, 4096, 4096, false>;
229using BoundedValue = TestValue<
230 value_magic_t::TEST_BOUNDED, 320, 320, 640, 4096, 4096, true>;
231// should be the same configuration with FLTreeOnode
232using ExtendedValue = TestValue<
233 value_magic_t::TEST_EXTENDED, 256, 2048, 1200, 8192, 16384, true>;
234
235}
1e59de90
TL
236
237#if FMT_VERSION >= 90000
238template<>
239struct fmt::formatter<crimson::os::seastore::onode::test_item_t> : fmt::ostream_formatter {};
240#endif