]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/crimson/seastore/test_omap_manager.cc
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / test / crimson / seastore / test_omap_manager.cc
CommitLineData
20effc67
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/crimson/gtest_seastar.h"
5
6#include "test/crimson/seastore/transaction_manager_test_state.h"
7
8#include "crimson/os/seastore/cache.h"
9#include "crimson/os/seastore/transaction_manager.h"
10#include "crimson/os/seastore/segment_manager.h"
11#include "crimson/os/seastore/omap_manager.h"
12
13#include "test/crimson/seastore/test_block.h"
14
15using namespace crimson;
16using namespace crimson::os;
17using namespace crimson::os::seastore;
18using namespace std;
19
20namespace {
21 [[maybe_unused]] seastar::logger& logger() {
22 return crimson::get_logger(ceph_subsys_test);
23 }
24}
25
26const int STR_LEN = 50;
27
28std::string rand_name(const int len)
29{
30 std::string ret;
31 ret.reserve(len);
32 for (int i = 0; i < len; ++i) {
33 ret.append(1, (char)(rand() % ('z' - '0')) + '0');
34 }
35 return ret;
36}
37
38bufferlist rand_buffer(const int len) {
39 bufferptr ptr(len);
40 for (auto i = ptr.c_str(); i < ptr.c_str() + len; ++i) {
41 *i = (char)rand();
42 }
43 bufferlist bl;
44 bl.append(ptr);
45 return bl;
46}
47
48struct omap_manager_test_t :
49 public seastar_test_suite_t,
50 TMTestState {
51
52 OMapManagerRef omap_manager;
53
54 omap_manager_test_t() {}
55
56 seastar::future<> set_up_fut() final {
57 return tm_setup().then([this] {
58 omap_manager = omap_manager::create_omap_manager(*tm);
59 return seastar::now();
60 });
61 }
62
63 seastar::future<> tear_down_fut() final {
64 return tm_teardown().then([this] {
65 omap_manager.reset();
66 return seastar::now();
67 });
68 }
69
70 using test_omap_t = std::map<std::string, ceph::bufferlist>;
71 test_omap_t test_omap_mappings;
72
73 void set_key(
74 omap_root_t &omap_root,
75 Transaction &t,
76 const string &key,
77 const bufferlist &val) {
78 with_trans_intr(
79 t,
80 [&, this](auto &t) {
81 return omap_manager->omap_set_key(omap_root, t, key, val);
82 }).unsafe_get0();
83 test_omap_mappings[key] = val;
84 }
85
86 void set_key(
87 omap_root_t &omap_root,
88 Transaction &t,
89 const string &key,
90 const string &val) {
91 bufferlist bl;
92 bl.append(val);
93 set_key(omap_root, t, key, bl);
94 }
95
96 std::string set_random_key(
97 omap_root_t &omap_root,
98 Transaction &t) {
99 auto key = rand_name(STR_LEN);
100 set_key(
101 omap_root,
102 t,
103 key,
104 rand_buffer(STR_LEN));
105 return key;
106 }
107
108 void get_value(
109 omap_root_t &omap_root,
110 Transaction &t,
111 const string &key) {
112 auto ret = with_trans_intr(
113 t,
114 [&, this](auto &t) {
115 return omap_manager->omap_get_value(omap_root, t, key);
116 }).unsafe_get0();
117 auto iter = test_omap_mappings.find(key);
118 if (iter == test_omap_mappings.end()) {
119 EXPECT_FALSE(ret);
120 } else {
121 EXPECT_TRUE(ret);
122 if (ret) {
123 EXPECT_TRUE(*ret == iter->second);
124 }
125 }
126 }
127
128 void rm_key(
129 omap_root_t &omap_root,
130 Transaction &t,
131 const string &key) {
132 with_trans_intr(
133 t,
134 [&, this](auto &t) {
135 return omap_manager->omap_rm_key(omap_root, t, key);
136 }).unsafe_get0();
137 test_omap_mappings.erase(test_omap_mappings.find(key));
138 }
139
1e59de90
TL
140 std::vector<std::string> rm_key_range(
141 omap_root_t &omap_root,
142 Transaction &t,
143 const std::string &first,
144 const std::string &last) {
145 logger().debug("rm keys in range {} ~ {}", first, last);
146 auto config = OMapManager::omap_list_config_t()
147 .with_max(3000)
148 .with_inclusive(true, false);
149
150 with_trans_intr(
151 t,
152 [&, this](auto &t) {
153 return omap_manager->omap_rm_key_range(
154 omap_root, t, first, last, config);
155 }).unsafe_get0();
156
157 std::vector<std::string> keys;
158 size_t count = 0;
159 for (auto iter = test_omap_mappings.begin();
160 iter != test_omap_mappings.end(); ) {
161 if (iter->first >= first && iter->first < last) {
162 keys.push_back(iter->first);
163 iter = test_omap_mappings.erase(iter);
164 count++;
165 } else {
166 iter++;
167 }
168 if (count == config.max_result_size) {
169 break;
170 }
171 }
172 return keys;
173 }
174
20effc67
TL
175 void list(
176 const omap_root_t &omap_root,
177 Transaction &t,
1e59de90
TL
178 const std::optional<std::string> &first,
179 const std::optional<std::string> &last,
180 size_t max = 128,
181 bool inclusive = false) {
182
183 if (first && last) {
184 logger().debug("list on {} ~ {}", *first, *last);
185 } else if (first) {
186 logger().debug("list on {} ~ end", *first);
187 } else if (last) {
188 logger().debug("list on start ~ {}", *last);
20effc67 189 } else {
1e59de90 190 logger().debug("list on start ~ end");
20effc67
TL
191 }
192
1e59de90
TL
193 auto config = OMapManager::omap_list_config_t()
194 .with_max(max)
195 .with_inclusive(inclusive, false);
20effc67
TL
196
197 auto [complete, results] = with_trans_intr(
198 t,
199 [&, this](auto &t) {
1e59de90 200 return omap_manager->omap_list(omap_root, t, first, last, config);
20effc67
TL
201 }).unsafe_get0();
202
1e59de90
TL
203 test_omap_t::iterator it, lit;
204 if (first) {
205 it = config.first_inclusive ?
206 test_omap_mappings.lower_bound(*first) :
207 test_omap_mappings.upper_bound(*first);
208 } else {
209 it = test_omap_mappings.begin();
210 }
211 if (last) {
212 lit = config.last_inclusive ?
213 test_omap_mappings.upper_bound(*last) :
214 test_omap_mappings.lower_bound(*last);
215 } else {
216 lit = test_omap_mappings.end();
217 }
218
20effc67
TL
219 for (auto &&[k, v]: results) {
220 EXPECT_NE(it, test_omap_mappings.end());
1e59de90 221 if (it == test_omap_mappings.end()) {
20effc67 222 return;
1e59de90 223 }
20effc67
TL
224 EXPECT_EQ(k, it->first);
225 EXPECT_EQ(v, it->second);
226 it++;
227 }
1e59de90 228 if (it == lit) {
20effc67
TL
229 EXPECT_TRUE(complete);
230 } else {
231 EXPECT_EQ(results.size(), max);
232 }
233 }
234
235 void clear(
236 omap_root_t &omap_root,
237 Transaction &t) {
238 with_trans_intr(
239 t,
240 [&, this](auto &t) {
241 return omap_manager->omap_clear(omap_root, t);
242 }).unsafe_get0();
243 EXPECT_EQ(omap_root.get_location(), L_ADDR_NULL);
244 }
245
246 void check_mappings(omap_root_t &omap_root, Transaction &t) {
247 for (const auto &i: test_omap_mappings){
248 get_value(omap_root, t, i.first);
249 }
250 }
251
252 void check_mappings(omap_root_t &omap_root) {
253 auto t = create_read_transaction();
254 check_mappings(omap_root, *t);
255 }
256
257 std::vector<std::string> get_mapped_keys() {
258 std::vector<std::string> mkeys;
259 mkeys.reserve(test_omap_mappings.size());
260 for (auto &k: test_omap_mappings) {
261 mkeys.push_back(k.first);
262 }
263 return mkeys;
264 }
265
266 void replay() {
20effc67
TL
267 restart();
268 omap_manager = omap_manager::create_omap_manager(*tm);
20effc67
TL
269 }
270
271 auto initialize() {
272 auto t = create_mutate_transaction();
273 omap_root_t omap_root = with_trans_intr(
274 *t,
275 [this](auto &t) {
276 return omap_manager->initialize_omap(t, L_ADDR_MIN);
277 }).unsafe_get0();
278 submit_transaction(std::move(t));
279 return omap_root;
280 }
281};
282
aee94f69 283TEST_P(omap_manager_test_t, basic)
20effc67
TL
284{
285 run_async([this] {
286 omap_root_t omap_root = initialize();
287
288 string key = "owner";
289 string val = "test";
290
291 {
292 auto t = create_mutate_transaction();
293 logger().debug("first transaction");
294 set_key(omap_root, *t, key, val);
295 get_value(omap_root, *t, key);
296 submit_transaction(std::move(t));
297 }
298 {
299 auto t = create_mutate_transaction();
300 logger().debug("second transaction");
301 get_value(omap_root, *t, key);
302 rm_key(omap_root, *t, key);
303 get_value(omap_root, *t, key);
304 submit_transaction(std::move(t));
305 }
306 {
307 auto t = create_mutate_transaction();
308 logger().debug("third transaction");
309 get_value(omap_root, *t, key);
310 submit_transaction(std::move(t));
311 }
312 });
313}
314
aee94f69 315TEST_P(omap_manager_test_t, force_leafnode_split)
20effc67
TL
316{
317 run_async([this] {
318 omap_root_t omap_root = initialize();
319
320 for (unsigned i = 0; i < 40; i++) {
321 auto t = create_mutate_transaction();
322 logger().debug("opened transaction");
323 for (unsigned j = 0; j < 10; ++j) {
324 set_random_key(omap_root, *t);
325 if ((i % 20 == 0) && (j == 5)) {
326 check_mappings(omap_root, *t);
327 }
328 }
329 logger().debug("force split submit transaction i = {}", i);
330 submit_transaction(std::move(t));
331 check_mappings(omap_root);
332 }
333 });
334}
335
aee94f69 336TEST_P(omap_manager_test_t, force_leafnode_split_merge)
20effc67
TL
337{
338 run_async([this] {
339 omap_root_t omap_root = initialize();
340
341 for (unsigned i = 0; i < 80; i++) {
342 auto t = create_mutate_transaction();
343 logger().debug("opened split_merge transaction");
344 for (unsigned j = 0; j < 5; ++j) {
345 set_random_key(omap_root, *t);
346 if ((i % 10 == 0) && (j == 3)) {
347 check_mappings(omap_root, *t);
348 }
349 }
350 logger().debug("submitting transaction");
351 submit_transaction(std::move(t));
352 if (i % 50 == 0) {
353 check_mappings(omap_root);
354 }
355 }
356 auto mkeys = get_mapped_keys();
357 auto t = create_mutate_transaction();
358 for (unsigned i = 0; i < mkeys.size(); i++) {
359 if (i % 3 != 0) {
360 rm_key(omap_root, *t, mkeys[i]);
361 }
362
363 if (i % 10 == 0) {
364 logger().debug("submitting transaction i= {}", i);
365 submit_transaction(std::move(t));
366 t = create_mutate_transaction();
367 }
368 if (i % 100 == 0) {
369 logger().debug("check_mappings i= {}", i);
370 check_mappings(omap_root, *t);
371 check_mappings(omap_root);
372 }
373 }
374 logger().debug("finally submitting transaction ");
375 submit_transaction(std::move(t));
376 });
377}
378
aee94f69 379TEST_P(omap_manager_test_t, force_leafnode_split_merge_fullandbalanced)
20effc67
TL
380{
381 run_async([this] {
382 omap_root_t omap_root = initialize();
383
384 for (unsigned i = 0; i < 50; i++) {
385 auto t = create_mutate_transaction();
386 logger().debug("opened split_merge transaction");
387 for (unsigned j = 0; j < 5; ++j) {
388 set_random_key(omap_root, *t);
389 if ((i % 10 == 0) && (j == 3)) {
390 check_mappings(omap_root, *t);
391 }
392 }
393 logger().debug("submitting transaction");
394 submit_transaction(std::move(t));
395 if (i % 50 == 0) {
396 check_mappings(omap_root);
397 }
398 }
399 auto mkeys = get_mapped_keys();
400 auto t = create_mutate_transaction();
401 for (unsigned i = 0; i < mkeys.size(); i++) {
402 if (30 < i && i < 100) {
403 rm_key(omap_root, *t, mkeys[i]);
404 }
405
406 if (i % 10 == 0) {
407 logger().debug("submitting transaction i= {}", i);
408 submit_transaction(std::move(t));
409 t = create_mutate_transaction();
410 }
411 if (i % 50 == 0) {
412 logger().debug("check_mappings i= {}", i);
413 check_mappings(omap_root, *t);
414 check_mappings(omap_root);
415 }
1e59de90 416 if (i == 100) {
20effc67 417 break;
1e59de90 418 }
20effc67
TL
419 }
420 logger().debug("finally submitting transaction ");
421 submit_transaction(std::move(t));
422 check_mappings(omap_root);
423 });
424}
425
aee94f69 426TEST_P(omap_manager_test_t, force_split_listkeys_list_rmkey_range_clear)
20effc67
TL
427{
428 run_async([this] {
429 omap_root_t omap_root = initialize();
430
1e59de90 431 string first, last;
20effc67
TL
432 for (unsigned i = 0; i < 40; i++) {
433 auto t = create_mutate_transaction();
434 logger().debug("opened transaction");
435 for (unsigned j = 0; j < 10; ++j) {
436 auto key = set_random_key(omap_root, *t);
1e59de90
TL
437 if (i == 10) {
438 first = key;
439 }
440 if (i == 30) {
441 last = key;
442 if (first > last) {
443 std::swap(first, last);
444 }
445 }
20effc67
TL
446 if ((i % 20 == 0) && (j == 5)) {
447 check_mappings(omap_root, *t);
448 }
449 }
450 logger().debug("force split submit transaction i = {}", i);
451 submit_transaction(std::move(t));
452 check_mappings(omap_root);
453 }
454
1e59de90
TL
455 std::optional<std::string> first_temp;
456 std::optional<std::string> last_temp;
457 {
458 auto t = create_read_transaction();
459 first_temp = std::nullopt;
460 last_temp = std::nullopt;
461 list(omap_root, *t, first_temp, last_temp);
462 }
463
464 {
465 auto t = create_read_transaction();
466 first_temp = first;
467 last_temp = std::nullopt;
468 list(omap_root, *t, first_temp, last_temp, 100);
469 }
470
471 {
472 auto t = create_read_transaction();
473 first_temp = first;
474 last_temp = std::nullopt;
475 list(omap_root, *t, first_temp, last_temp, 100, true);
476 }
477
478 {
479 auto t = create_read_transaction();
480 first_temp = std::nullopt;
481 last_temp = last;
482 list(omap_root, *t, first_temp, last_temp, 10240);
483 }
484
20effc67
TL
485 {
486 auto t = create_read_transaction();
1e59de90
TL
487 first_temp = first;
488 last_temp = last;
489 list(omap_root, *t, first_temp, last_temp, 10240, true);
20effc67
TL
490 }
491
492 {
493 auto t = create_read_transaction();
1e59de90
TL
494 list(omap_root, *t, first, last, 10240, true);
495 }
496
497 {
498 auto t = create_mutate_transaction();
499 auto keys = rm_key_range(omap_root, *t, first, last);
500 for (const auto& key : keys) {
501 get_value(omap_root, *t, key);
502 }
503 submit_transaction(std::move(t));
20effc67
TL
504 }
505
506 {
507 auto t = create_mutate_transaction();
508 clear(omap_root, *t);
509 submit_transaction(std::move(t));
510 }
511 });
512}
513
aee94f69 514TEST_P(omap_manager_test_t, force_inner_node_split_list_rmkey_range)
1e59de90
TL
515{
516 run_async([this] {
517 omap_root_t omap_root = initialize();
518
519 string first = "";
520 string last;
521 while (cache->get_omap_tree_depth() < 3) {
522 for (unsigned i = 0; i < 40; i++) {
523 auto t = create_mutate_transaction();
524 logger().debug("opened transaction");
525 for (unsigned j = 0; j < 10; ++j) {
526 auto key = set_random_key(omap_root, *t);
527 if (key.compare(first) < 0 || !first.length()) {
528 first = key;
529 }
530 if (i == 10) {
531 last = key;
532 }
533 }
534 logger().debug("force split submit transaction i = {}", i);
535 submit_transaction(std::move(t));
536 }
537 }
538
539 std::optional<std::string> first_temp;
540 std::optional<std::string> last_temp;
541 {
542 auto t = create_read_transaction();
543 first_temp = first;
544 last_temp = std::nullopt;
545 list(omap_root, *t, first_temp, last_temp, 10240);
546 }
547
548 {
549 auto t = create_read_transaction();
550 first_temp = first;
551 last_temp = std::nullopt;
552 list(omap_root, *t, first_temp, last_temp, 10240, true);
553 }
554
555 {
556 auto t = create_read_transaction();
557 first_temp = std::nullopt;
558 last_temp = last;
559 list(omap_root, *t, first_temp, last_temp, 10240);
560 }
561
562 {
563 auto t = create_read_transaction();
564 first_temp = first;
565 last_temp = last;
566 list(omap_root, *t, first_temp, last_temp, 10240, true);
567 }
568
569 {
570 auto t = create_mutate_transaction();
571 auto keys = rm_key_range(omap_root, *t, first, last);
572 for (const auto& key : keys) {
573 get_value(omap_root, *t, key);
574 }
575 submit_transaction(std::move(t));
576 }
577
578 {
579 auto t = create_mutate_transaction();
580 clear(omap_root, *t);
581 submit_transaction(std::move(t));
582 }
583 });
584}
585
586
aee94f69 587TEST_P(omap_manager_test_t, internal_force_split)
20effc67
TL
588{
589 run_async([this] {
590 omap_root_t omap_root = initialize();
591
592 for (unsigned i = 0; i < 10; i++) {
593 logger().debug("opened split transaction");
594 auto t = create_mutate_transaction();
595
596 for (unsigned j = 0; j < 80; ++j) {
597 set_random_key(omap_root, *t);
598 if ((i % 2 == 0) && (j % 50 == 0)) {
599 check_mappings(omap_root, *t);
600 }
601 }
602 logger().debug("submitting transaction i = {}", i);
603 submit_transaction(std::move(t));
604 }
605 check_mappings(omap_root);
606 });
607}
608
aee94f69 609TEST_P(omap_manager_test_t, internal_force_merge_fullandbalanced)
20effc67
TL
610{
611 run_async([this] {
612 omap_root_t omap_root = initialize();
613
614 for (unsigned i = 0; i < 8; i++) {
615 logger().debug("opened split transaction");
616 auto t = create_mutate_transaction();
617
618 for (unsigned j = 0; j < 80; ++j) {
619 set_random_key(omap_root, *t);
620 if ((i % 2 == 0) && (j % 50 == 0)) {
621 check_mappings(omap_root, *t);
622 }
623 }
624 logger().debug("submitting transaction");
625 submit_transaction(std::move(t));
626 }
627 auto mkeys = get_mapped_keys();
628 auto t = create_mutate_transaction();
629 for (unsigned i = 0; i < mkeys.size(); i++) {
630 rm_key(omap_root, *t, mkeys[i]);
631
632 if (i % 10 == 0) {
633 logger().debug("submitting transaction i= {}", i);
634 submit_transaction(std::move(t));
635 t = create_mutate_transaction();
636 }
637 if (i % 50 == 0) {
638 logger().debug("check_mappings i= {}", i);
639 check_mappings(omap_root, *t);
640 check_mappings(omap_root);
641 }
642 }
643 logger().debug("finally submitting transaction ");
644 submit_transaction(std::move(t));
645 check_mappings(omap_root);
646 });
647}
648
aee94f69 649TEST_P(omap_manager_test_t, replay)
20effc67
TL
650{
651 run_async([this] {
652 omap_root_t omap_root = initialize();
653
654 for (unsigned i = 0; i < 8; i++) {
655 logger().debug("opened split transaction");
656 auto t = create_mutate_transaction();
657
658 for (unsigned j = 0; j < 80; ++j) {
659 set_random_key(omap_root, *t);
660 if ((i % 2 == 0) && (j % 50 == 0)) {
661 check_mappings(omap_root, *t);
662 }
663 }
664 logger().debug("submitting transaction i = {}", i);
665 submit_transaction(std::move(t));
666 }
667 replay();
668 check_mappings(omap_root);
669
670 auto mkeys = get_mapped_keys();
671 auto t = create_mutate_transaction();
672 for (unsigned i = 0; i < mkeys.size(); i++) {
673 rm_key(omap_root, *t, mkeys[i]);
674
675 if (i % 10 == 0) {
676 logger().debug("submitting transaction i= {}", i);
677 submit_transaction(std::move(t));
678 replay();
679 t = create_mutate_transaction();
680 }
681 if (i % 50 == 0) {
682 logger().debug("check_mappings i= {}", i);
683 check_mappings(omap_root, *t);
684 check_mappings(omap_root);
685 }
686 }
687 logger().debug("finally submitting transaction ");
688 submit_transaction(std::move(t));
689 replay();
690 check_mappings(omap_root);
691 });
692}
693
694
aee94f69 695TEST_P(omap_manager_test_t, internal_force_split_to_root)
20effc67
TL
696{
697 run_async([this] {
698 omap_root_t omap_root = initialize();
699
700 logger().debug("set big keys");
701 for (unsigned i = 0; i < 53; i++) {
702 auto t = create_mutate_transaction();
703
704 for (unsigned j = 0; j < 8; ++j) {
705 set_random_key(omap_root, *t);
706 }
707 logger().debug("submitting transaction i = {}", i);
708 submit_transaction(std::move(t));
709 }
710 logger().debug("set small keys");
711 for (unsigned i = 0; i < 100; i++) {
712 auto t = create_mutate_transaction();
713 for (unsigned j = 0; j < 8; ++j) {
714 set_random_key(omap_root, *t);
715 }
716 logger().debug("submitting transaction last");
717 submit_transaction(std::move(t));
718 }
719 check_mappings(omap_root);
720 });
721}
aee94f69
TL
722
723INSTANTIATE_TEST_SUITE_P(
724 omap_manager_test,
725 omap_manager_test_t,
726 ::testing::Values (
727 "segmented",
728 "circularbounded"
729 )
730);