1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/crimson/gtest_seastar.h"
6 #include "test/crimson/seastore/transaction_manager_test_state.h"
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"
13 #include "test/crimson/seastore/test_block.h"
15 using namespace crimson
;
16 using namespace crimson::os
;
17 using namespace crimson::os::seastore
;
21 [[maybe_unused
]] seastar::logger
& logger() {
22 return crimson::get_logger(ceph_subsys_test
);
26 const int STR_LEN
= 50;
28 std::string
rand_name(const int len
)
32 for (int i
= 0; i
< len
; ++i
) {
33 ret
.append(1, (char)(rand() % ('z' - '0')) + '0');
38 bufferlist
rand_buffer(const int len
) {
40 for (auto i
= ptr
.c_str(); i
< ptr
.c_str() + len
; ++i
) {
48 struct omap_manager_test_t
:
49 public seastar_test_suite_t
,
52 OMapManagerRef omap_manager
;
54 omap_manager_test_t() {}
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();
63 seastar::future
<> tear_down_fut() final
{
64 return tm_teardown().then([this] {
66 return seastar::now();
70 using test_omap_t
= std::map
<std::string
, ceph::bufferlist
>;
71 test_omap_t test_omap_mappings
;
74 omap_root_t
&omap_root
,
77 const bufferlist
&val
) {
81 return omap_manager
->omap_set_key(omap_root
, t
, key
, val
);
83 test_omap_mappings
[key
] = val
;
87 omap_root_t
&omap_root
,
93 set_key(omap_root
, t
, key
, bl
);
96 std::string
set_random_key(
97 omap_root_t
&omap_root
,
99 auto key
= rand_name(STR_LEN
);
104 rand_buffer(STR_LEN
));
109 omap_root_t
&omap_root
,
112 auto ret
= with_trans_intr(
115 return omap_manager
->omap_get_value(omap_root
, t
, key
);
117 auto iter
= test_omap_mappings
.find(key
);
118 if (iter
== test_omap_mappings
.end()) {
123 EXPECT_TRUE(*ret
== iter
->second
);
129 omap_root_t
&omap_root
,
135 return omap_manager
->omap_rm_key(omap_root
, t
, key
);
137 test_omap_mappings
.erase(test_omap_mappings
.find(key
));
141 const omap_root_t
&omap_root
,
143 const std::optional
<std::string
> &start
,
147 logger().debug("list on {}", *start
);
149 logger().debug("list on start");
152 auto config
= OMapManager::omap_list_config_t::with_max(max
);
153 config
.max_result_size
= max
;
155 auto [complete
, results
] = with_trans_intr(
158 return omap_manager
->omap_list(omap_root
, t
, start
, config
);
162 test_omap_mappings
.upper_bound(*start
) :
163 test_omap_mappings
.begin();
164 for (auto &&[k
, v
]: results
) {
165 EXPECT_NE(it
, test_omap_mappings
.end());
166 if (it
== test_omap_mappings
.end())
168 EXPECT_EQ(k
, it
->first
);
169 EXPECT_EQ(v
, it
->second
);
172 if (it
== test_omap_mappings
.end()) {
173 EXPECT_TRUE(complete
);
175 EXPECT_EQ(results
.size(), max
);
180 omap_root_t
&omap_root
,
185 return omap_manager
->omap_clear(omap_root
, t
);
187 EXPECT_EQ(omap_root
.get_location(), L_ADDR_NULL
);
190 void check_mappings(omap_root_t
&omap_root
, Transaction
&t
) {
191 for (const auto &i
: test_omap_mappings
){
192 get_value(omap_root
, t
, i
.first
);
196 void check_mappings(omap_root_t
&omap_root
) {
197 auto t
= create_read_transaction();
198 check_mappings(omap_root
, *t
);
201 std::vector
<std::string
> get_mapped_keys() {
202 std::vector
<std::string
> mkeys
;
203 mkeys
.reserve(test_omap_mappings
.size());
204 for (auto &k
: test_omap_mappings
) {
205 mkeys
.push_back(k
.first
);
211 logger().debug("{}: begin", __func__
);
213 omap_manager
= omap_manager::create_omap_manager(*tm
);
214 logger().debug("{}: end", __func__
);
218 auto t
= create_mutate_transaction();
219 omap_root_t omap_root
= with_trans_intr(
222 return omap_manager
->initialize_omap(t
, L_ADDR_MIN
);
224 submit_transaction(std::move(t
));
229 TEST_F(omap_manager_test_t
, basic
)
232 omap_root_t omap_root
= initialize();
234 string key
= "owner";
238 auto t
= create_mutate_transaction();
239 logger().debug("first transaction");
240 set_key(omap_root
, *t
, key
, val
);
241 get_value(omap_root
, *t
, key
);
242 submit_transaction(std::move(t
));
245 auto t
= create_mutate_transaction();
246 logger().debug("second transaction");
247 get_value(omap_root
, *t
, key
);
248 rm_key(omap_root
, *t
, key
);
249 get_value(omap_root
, *t
, key
);
250 submit_transaction(std::move(t
));
253 auto t
= create_mutate_transaction();
254 logger().debug("third transaction");
255 get_value(omap_root
, *t
, key
);
256 submit_transaction(std::move(t
));
261 TEST_F(omap_manager_test_t
, force_leafnode_split
)
264 omap_root_t omap_root
= initialize();
266 for (unsigned i
= 0; i
< 40; i
++) {
267 auto t
= create_mutate_transaction();
268 logger().debug("opened transaction");
269 for (unsigned j
= 0; j
< 10; ++j
) {
270 set_random_key(omap_root
, *t
);
271 if ((i
% 20 == 0) && (j
== 5)) {
272 check_mappings(omap_root
, *t
);
275 logger().debug("force split submit transaction i = {}", i
);
276 submit_transaction(std::move(t
));
277 check_mappings(omap_root
);
282 TEST_F(omap_manager_test_t
, force_leafnode_split_merge
)
285 omap_root_t omap_root
= initialize();
287 for (unsigned i
= 0; i
< 80; i
++) {
288 auto t
= create_mutate_transaction();
289 logger().debug("opened split_merge transaction");
290 for (unsigned j
= 0; j
< 5; ++j
) {
291 set_random_key(omap_root
, *t
);
292 if ((i
% 10 == 0) && (j
== 3)) {
293 check_mappings(omap_root
, *t
);
296 logger().debug("submitting transaction");
297 submit_transaction(std::move(t
));
299 check_mappings(omap_root
);
302 auto mkeys
= get_mapped_keys();
303 auto t
= create_mutate_transaction();
304 for (unsigned i
= 0; i
< mkeys
.size(); i
++) {
306 rm_key(omap_root
, *t
, mkeys
[i
]);
310 logger().debug("submitting transaction i= {}", i
);
311 submit_transaction(std::move(t
));
312 t
= create_mutate_transaction();
315 logger().debug("check_mappings i= {}", i
);
316 check_mappings(omap_root
, *t
);
317 check_mappings(omap_root
);
320 logger().debug("finally submitting transaction ");
321 submit_transaction(std::move(t
));
325 TEST_F(omap_manager_test_t
, force_leafnode_split_merge_fullandbalanced
)
328 omap_root_t omap_root
= initialize();
330 for (unsigned i
= 0; i
< 50; i
++) {
331 auto t
= create_mutate_transaction();
332 logger().debug("opened split_merge transaction");
333 for (unsigned j
= 0; j
< 5; ++j
) {
334 set_random_key(omap_root
, *t
);
335 if ((i
% 10 == 0) && (j
== 3)) {
336 check_mappings(omap_root
, *t
);
339 logger().debug("submitting transaction");
340 submit_transaction(std::move(t
));
342 check_mappings(omap_root
);
345 auto mkeys
= get_mapped_keys();
346 auto t
= create_mutate_transaction();
347 for (unsigned i
= 0; i
< mkeys
.size(); i
++) {
348 if (30 < i
&& i
< 100) {
349 rm_key(omap_root
, *t
, mkeys
[i
]);
353 logger().debug("submitting transaction i= {}", i
);
354 submit_transaction(std::move(t
));
355 t
= create_mutate_transaction();
358 logger().debug("check_mappings i= {}", i
);
359 check_mappings(omap_root
, *t
);
360 check_mappings(omap_root
);
365 logger().debug("finally submitting transaction ");
366 submit_transaction(std::move(t
));
367 check_mappings(omap_root
);
371 TEST_F(omap_manager_test_t
, force_split_listkeys_list_clear
)
374 omap_root_t omap_root
= initialize();
377 for (unsigned i
= 0; i
< 40; i
++) {
378 auto t
= create_mutate_transaction();
379 logger().debug("opened transaction");
380 for (unsigned j
= 0; j
< 10; ++j
) {
381 auto key
= set_random_key(omap_root
, *t
);
384 if ((i
% 20 == 0) && (j
== 5)) {
385 check_mappings(omap_root
, *t
);
388 logger().debug("force split submit transaction i = {}", i
);
389 submit_transaction(std::move(t
));
390 check_mappings(omap_root
);
394 auto t
= create_read_transaction();
395 list(omap_root
, *t
, std::nullopt
);
399 auto t
= create_read_transaction();
400 list(omap_root
, *t
, temp
, 100);
404 auto t
= create_mutate_transaction();
405 clear(omap_root
, *t
);
406 submit_transaction(std::move(t
));
411 TEST_F(omap_manager_test_t
, internal_force_split
)
414 omap_root_t omap_root
= initialize();
416 for (unsigned i
= 0; i
< 10; i
++) {
417 logger().debug("opened split transaction");
418 auto t
= create_mutate_transaction();
420 for (unsigned j
= 0; j
< 80; ++j
) {
421 set_random_key(omap_root
, *t
);
422 if ((i
% 2 == 0) && (j
% 50 == 0)) {
423 check_mappings(omap_root
, *t
);
426 logger().debug("submitting transaction i = {}", i
);
427 submit_transaction(std::move(t
));
429 check_mappings(omap_root
);
433 TEST_F(omap_manager_test_t
, internal_force_merge_fullandbalanced
)
436 omap_root_t omap_root
= initialize();
438 for (unsigned i
= 0; i
< 8; i
++) {
439 logger().debug("opened split transaction");
440 auto t
= create_mutate_transaction();
442 for (unsigned j
= 0; j
< 80; ++j
) {
443 set_random_key(omap_root
, *t
);
444 if ((i
% 2 == 0) && (j
% 50 == 0)) {
445 check_mappings(omap_root
, *t
);
448 logger().debug("submitting transaction");
449 submit_transaction(std::move(t
));
451 auto mkeys
= get_mapped_keys();
452 auto t
= create_mutate_transaction();
453 for (unsigned i
= 0; i
< mkeys
.size(); i
++) {
454 rm_key(omap_root
, *t
, mkeys
[i
]);
457 logger().debug("submitting transaction i= {}", i
);
458 submit_transaction(std::move(t
));
459 t
= create_mutate_transaction();
462 logger().debug("check_mappings i= {}", i
);
463 check_mappings(omap_root
, *t
);
464 check_mappings(omap_root
);
467 logger().debug("finally submitting transaction ");
468 submit_transaction(std::move(t
));
469 check_mappings(omap_root
);
473 TEST_F(omap_manager_test_t
, replay
)
476 omap_root_t omap_root
= initialize();
478 for (unsigned i
= 0; i
< 8; i
++) {
479 logger().debug("opened split transaction");
480 auto t
= create_mutate_transaction();
482 for (unsigned j
= 0; j
< 80; ++j
) {
483 set_random_key(omap_root
, *t
);
484 if ((i
% 2 == 0) && (j
% 50 == 0)) {
485 check_mappings(omap_root
, *t
);
488 logger().debug("submitting transaction i = {}", i
);
489 submit_transaction(std::move(t
));
492 check_mappings(omap_root
);
494 auto mkeys
= get_mapped_keys();
495 auto t
= create_mutate_transaction();
496 for (unsigned i
= 0; i
< mkeys
.size(); i
++) {
497 rm_key(omap_root
, *t
, mkeys
[i
]);
500 logger().debug("submitting transaction i= {}", i
);
501 submit_transaction(std::move(t
));
503 t
= create_mutate_transaction();
506 logger().debug("check_mappings i= {}", i
);
507 check_mappings(omap_root
, *t
);
508 check_mappings(omap_root
);
511 logger().debug("finally submitting transaction ");
512 submit_transaction(std::move(t
));
514 check_mappings(omap_root
);
519 TEST_F(omap_manager_test_t
, internal_force_split_to_root
)
522 omap_root_t omap_root
= initialize();
524 logger().debug("set big keys");
525 for (unsigned i
= 0; i
< 53; i
++) {
526 auto t
= create_mutate_transaction();
528 for (unsigned j
= 0; j
< 8; ++j
) {
529 set_random_key(omap_root
, *t
);
531 logger().debug("submitting transaction i = {}", i
);
532 submit_transaction(std::move(t
));
534 logger().debug("set small keys");
535 for (unsigned i
= 0; i
< 100; i
++) {
536 auto t
= create_mutate_transaction();
537 for (unsigned j
= 0; j
< 8; ++j
) {
538 set_random_key(omap_root
, *t
);
540 logger().debug("submitting transaction last");
541 submit_transaction(std::move(t
));
543 check_mappings(omap_root
);