]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/cache/pwl/test_WriteLogMap.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / librbd / cache / pwl / test_WriteLogMap.cc
CommitLineData
f67539c2
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "test/librbd/test_fixture.h"
5#include "test/librbd/test_support.h"
6
7#include "librbd/cache/pwl/LogMap.cc"
8
9void register_test_write_log_map() {
10}
11
12namespace librbd {
13namespace cache {
14namespace pwl {
15
20effc67
TL
16using namespace std;
17
f67539c2
TL
18struct TestLogEntry {
19 uint64_t image_offset_bytes;
20 uint64_t write_bytes;
21 uint32_t referring_map_entries = 0;
22 TestLogEntry(const uint64_t image_offset_bytes, const uint64_t write_bytes)
23 : image_offset_bytes(image_offset_bytes), write_bytes(write_bytes) {
24 }
25 uint64_t get_offset_bytes() {
26 return image_offset_bytes;
27 }
28 uint64_t get_write_bytes() {
29 return write_bytes;
30 }
31 BlockExtent block_extent() {
32 return BlockExtent(image_offset_bytes, image_offset_bytes + write_bytes);
33 }
34 uint32_t get_map_ref() {
35 return referring_map_entries;
36 }
37 void inc_map_ref() {
38 referring_map_entries++;
39 }
40 void dec_map_ref() {
41 referring_map_entries--;
42 }
43 friend std::ostream &operator<<(std::ostream &os,
44 const TestLogEntry &entry) {
45 os << "referring_map_entries=" << entry.referring_map_entries << ", "
46 << "image_offset_bytes=" << entry.image_offset_bytes << ", "
47 << "write_bytes=" << entry.write_bytes;
48 return os;
49 };
50};
51
52typedef std::list<std::shared_ptr<TestLogEntry>> TestLogEntries;
53typedef LogMapEntry<TestLogEntry> TestMapEntry;
54typedef LogMapEntries<TestLogEntry> TestLogMapEntries;
55typedef LogMap<TestLogEntry> TestLogMap;
56
57class TestWriteLogMap : public TestFixture {
58public:
59 void SetUp() override {
60 TestFixture::SetUp();
61 m_cct = reinterpret_cast<CephContext*>(m_ioctx.cct());
62 }
63
64 CephContext *m_cct;
65};
66
67TEST_F(TestWriteLogMap, Simple) {
68 TestLogEntries es;
69 TestLogMapEntries lme;
70 TestLogMap map(m_cct);
71
72 /* LogEntry takes offset, length, in bytes */
73 auto e1 = make_shared<TestLogEntry>(4, 8);
74 TestLogEntry *e1_ptr = e1.get();
75 ASSERT_EQ(4, e1_ptr->get_offset_bytes());
76 ASSERT_EQ(8, e1_ptr->get_write_bytes());
77 map.add_log_entry(e1);
78
79 /* BlockExtent takes first, last, in blocks */
80 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 100));
81 int numfound = found0.size();
82 /* Written range includes the single write above */
83 ASSERT_EQ(1, numfound);
84 ASSERT_EQ(e1, found0.front().log_entry);
85
86 /* Nothing before that */
87 found0 = map.find_map_entries(BlockExtent(0, 3));
88 numfound = found0.size();
89 ASSERT_EQ(0, numfound);
90
91 /* Nothing after that */
92 found0 = map.find_map_entries(BlockExtent(12, 99));
93 numfound = found0.size();
94 ASSERT_EQ(0, numfound);
95
96 /* 4-11 will be e1 */
97 for (int i=4; i<12; i++) {
98 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
99 int numfound = found0.size();
100 ASSERT_EQ(1, numfound);
101 ASSERT_EQ(e1, found0.front().log_entry);
102 }
103
104 map.remove_log_entry(e1);
105 /* Nothing should be found */
106 for (int i=4; i<12; i++) {
107 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
108 int numfound = found0.size();
109 ASSERT_EQ(0, numfound);
110 }
111}
112
113TEST_F(TestWriteLogMap, OverlapFront) {
114 TestLogMap map(m_cct);
115
116 auto e0 = make_shared<TestLogEntry>(4, 8);
117 map.add_log_entry(e0);
118 /* replaces block 4-7 of e0 */
119 auto e1 = make_shared<TestLogEntry>(0, 8);
120 map.add_log_entry(e1);
121
122 /* Written range includes the two writes above */
123 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 100));
124 int numfound = found0.size();
125 ASSERT_EQ(2, numfound);
126 ASSERT_EQ(e1, found0.front().log_entry);
127 ASSERT_EQ(0, found0.front().block_extent.block_start);
128 ASSERT_EQ(8, found0.front().block_extent.block_end);
129 found0.pop_front();
130 ASSERT_EQ(e0, found0.front().log_entry);
131 ASSERT_EQ(8, found0.front().block_extent.block_start);
132 ASSERT_EQ(12, found0.front().block_extent.block_end);
133
134 /* 0-7 will be e1 */
135 for (int i=0; i<8; i++) {
136 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
137 int numfound = found0.size();
138 ASSERT_EQ(1, numfound);
139 ASSERT_EQ(e1, found0.front().log_entry);
140 }
141
142 /* 8-11 will be e0 */
143 for (int i=8; i<12; i++) {
144 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
145 int numfound = found0.size();
146 ASSERT_EQ(1, numfound);
147 ASSERT_EQ(e0, found0.front().log_entry);
148 }
149}
150
151TEST_F(TestWriteLogMap, OverlapBack) {
152 TestLogMap map(m_cct);
153
154 auto e0 = make_shared<TestLogEntry>(0, 8);
155 map.add_log_entry(e0);
156 /* replaces block 4-7 of e0 */
157 auto e1 = make_shared<TestLogEntry>(4, 8);
158 map.add_log_entry(e1);
159
160 /* Written range includes the two writes above */
161 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 100));
162 int numfound = found0.size();
163 ASSERT_EQ(2, numfound);
164 ASSERT_EQ(e0, found0.front().log_entry);
165 ASSERT_EQ(0, found0.front().block_extent.block_start);
166 ASSERT_EQ(4, found0.front().block_extent.block_end);
167 found0.pop_front();
168 ASSERT_EQ(e1, found0.front().log_entry);
169 ASSERT_EQ(4, found0.front().block_extent.block_start);
170 ASSERT_EQ(12, found0.front().block_extent.block_end);
171
172 /* 0-3 will be e0 */
173 for (int i=0; i<4; i++) {
174 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
175 int numfound = found0.size();
176 ASSERT_EQ(1, numfound);
177 ASSERT_EQ(e0, found0.front().log_entry);
178 }
179
180 /* 4-11 will be e1 */
181 for (int i=4; i<12; i++) {
182 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
183 int numfound = found0.size();
184 ASSERT_EQ(1, numfound);
185 ASSERT_EQ(e1, found0.front().log_entry);
186 }
187
188 map.remove_log_entry(e0);
189
190 /* 0-3 will find nothing */
191 for (int i=0; i<4; i++) {
192 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
193 int numfound = found0.size();
194 ASSERT_EQ(0, numfound);
195 }
196
197 /* 4-11 will still be e1 */
198 for (int i=4; i<12; i++) {
199 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
200 int numfound = found0.size();
201 ASSERT_EQ(1, numfound);
202 ASSERT_EQ(e1, found0.front().log_entry);
203 }
204
205}
206
207TEST_F(TestWriteLogMap, OverlapMiddle) {
208 TestLogMap map(m_cct);
209
210 auto e0 = make_shared<TestLogEntry>(0, 1);
211 map.add_log_entry(e0);
212
213 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 1));
214 int numfound = found0.size();
215 ASSERT_EQ(1, numfound);
216 ASSERT_EQ(e0, found0.front().log_entry);
217 TestLogEntries entries = map.find_log_entries(BlockExtent(0, 1));
218 int entriesfound = entries.size();
219 ASSERT_EQ(1, entriesfound);
220 ASSERT_EQ(e0, entries.front());
221
222 auto e1 = make_shared<TestLogEntry>(1, 1);
223 map.add_log_entry(e1);
224
225 found0 = map.find_map_entries(BlockExtent(1, 2));
226 numfound = found0.size();
227 ASSERT_EQ(1, numfound);
228 ASSERT_EQ(e1, found0.front().log_entry);
229 entries = map.find_log_entries(BlockExtent(1, 2));
230 entriesfound = entries.size();
231 ASSERT_EQ(1, entriesfound);
232 ASSERT_EQ(e1, entries.front());
233
234 auto e2 = make_shared<TestLogEntry>(2, 1);
235 map.add_log_entry(e2);
236
237 found0 = map.find_map_entries(BlockExtent(2, 3));
238 numfound = found0.size();
239 ASSERT_EQ(1, numfound);
240 ASSERT_EQ(e2, found0.front().log_entry);
241 entries = map.find_log_entries(BlockExtent(2, 3));
242 entriesfound = entries.size();
243 ASSERT_EQ(1, entriesfound);
244 ASSERT_EQ(e2, entries.front());
245
246 /* replaces e1 */
247 auto e3 = make_shared<TestLogEntry>(1, 1);
248 map.add_log_entry(e3);
249
250 found0 = map.find_map_entries(BlockExtent(1, 2));
251 numfound = found0.size();
252 ASSERT_EQ(1, numfound);
253 ASSERT_EQ(e3, found0.front().log_entry);
254 entries = map.find_log_entries(BlockExtent(1, 2));
255 entriesfound = entries.size();
256 ASSERT_EQ(1, entriesfound);
257 ASSERT_EQ(e3, entries.front());
258
259 found0 = map.find_map_entries(BlockExtent(0, 100));
260 numfound = found0.size();
261 ASSERT_EQ(3, numfound);
262 ASSERT_EQ(e0, found0.front().log_entry);
263 found0.pop_front();
264 ASSERT_EQ(e3, found0.front().log_entry);
265 found0.pop_front();
266 ASSERT_EQ(e2, found0.front().log_entry);
267 entries = map.find_log_entries(BlockExtent(0, 100));
268 entriesfound = entries.size();
269 ASSERT_EQ(3, entriesfound);
270 ASSERT_EQ(e0, entries.front());
271 entries.pop_front();
272 ASSERT_EQ(e3, entries.front());
273 entries.pop_front();
274 ASSERT_EQ(e2, entries.front());
275
276 entries.clear();
277 entries.emplace_back(e0);
278 entries.emplace_back(e1);
279 map.remove_log_entries(entries);
280
281 found0 = map.find_map_entries(BlockExtent(0, 100));
282 numfound = found0.size();
283 ASSERT_EQ(2, numfound);
284 ASSERT_EQ(e3, found0.front().log_entry);
285 found0.pop_front();
286 ASSERT_EQ(e2, found0.front().log_entry);
287}
288
289TEST_F(TestWriteLogMap, OverlapSplit) {
290 TestLogMap map(m_cct);
291
292 auto e0 = make_shared<TestLogEntry>(0, 8);
293 map.add_log_entry(e0);
294
295 /* Splits e0 at 1 */
296 auto e1 = make_shared<TestLogEntry>(1, 1);
297 map.add_log_entry(e1);
298
299 /* Splits e0 again at 4 */
300 auto e2 = make_shared<TestLogEntry>(4, 2);
301 map.add_log_entry(e2);
302
303 /* Replaces one block of e2, and one of e0 */
304 auto e3 = make_shared<TestLogEntry>(5, 2);
305 map.add_log_entry(e3);
306
307 /* Expecting: 0:e0, 1:e1, 2..3:e0, 4:e2, 5..6:e3, 7:e0 */
308 TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 100));
309 int numfound = found0.size();
310 ASSERT_EQ(6, numfound);
311 ASSERT_EQ(e0, found0.front().log_entry);
312 ASSERT_EQ(0, found0.front().block_extent.block_start);
313 ASSERT_EQ(1, found0.front().block_extent.block_end);
314 found0.pop_front();
315 ASSERT_EQ(e1, found0.front().log_entry);
316 ASSERT_EQ(1, found0.front().block_extent.block_start);
317 ASSERT_EQ(2, found0.front().block_extent.block_end);
318 found0.pop_front();
319 ASSERT_EQ(e0, found0.front().log_entry);
320 ASSERT_EQ(2, found0.front().block_extent.block_start);
321 ASSERT_EQ(4, found0.front().block_extent.block_end);
322 found0.pop_front();
323 ASSERT_EQ(e2, found0.front().log_entry);
324 ASSERT_EQ(4, found0.front().block_extent.block_start);
325 ASSERT_EQ(5, found0.front().block_extent.block_end);
326 found0.pop_front();
327 ASSERT_EQ(e3, found0.front().log_entry);
328 ASSERT_EQ(5, found0.front().block_extent.block_start);
329 ASSERT_EQ(7, found0.front().block_extent.block_end);
330 found0.pop_front();
331 ASSERT_EQ(e0, found0.front().log_entry);
332 ASSERT_EQ(7, found0.front().block_extent.block_start);
333 ASSERT_EQ(8, found0.front().block_extent.block_end);
334}
335
336} // namespace pwl
337} // namespace cache
338} // namespace librbd