From: chunmei-liu Date: Wed, 28 Jul 2021 01:23:25 +0000 (-0700) Subject: crimson/seastore: convert onode unit test to use interruptible future. X-Git-Tag: v17.1.0~1221^2~1 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=f61e94ff933fb3cd54b5a3969aa0aecc871d49be;p=ceph.git crimson/seastore: convert onode unit test to use interruptible future. Signed-off-by: chunmei-liu --- diff --git a/src/test/crimson/seastore/onode_tree/test_fltree_onode_manager.cc b/src/test/crimson/seastore/onode_tree/test_fltree_onode_manager.cc index 9804c9746d92b..294e1626a78f9 100644 --- a/src/test/crimson/seastore/onode_tree/test_fltree_onode_manager.cc +++ b/src/test/crimson/seastore/onode_tree/test_fltree_onode_manager.cc @@ -71,7 +71,7 @@ struct fltree_onode_manager_test_t virtual void _init() final { TMTestState::_init(); - manager.reset(new FLTreeOnodeManager(itm)); + manager.reset(new FLTreeOnodeManager(*tm)); } virtual void _destroy() final { @@ -112,18 +112,22 @@ struct fltree_onode_manager_test_t void with_onode_write(iterator_t& it, F&& f) { with_transaction([this, &it, f=std::move(f)] (auto& t) { auto p_kv = *it; - auto onode = manager->get_or_create_onode( - t, p_kv->key).unsafe_get0(); + auto onode = with_trans_intr(t, [&](auto &t) { + return manager->get_or_create_onode(t, p_kv->key); + }).unsafe_get0(); std::invoke(f, t, *onode, p_kv->value); - manager->write_dirty(t, {onode}).unsafe_get0(); + with_trans_intr(t, [&](auto &t) { + return manager->write_dirty(t, {onode}); + }).unsafe_get0(); }); } void validate_onode(iterator_t& it) { with_transaction([this, &it] (auto& t) { auto p_kv = *it; - auto onode = manager->get_onode( - t, p_kv->key).unsafe_get0(); + auto onode = with_trans_intr(t, [&](auto &t) { + return manager->get_onode(t, p_kv->key); + }).unsafe_get0(); p_kv->value.validate(*onode); }); } @@ -131,8 +135,9 @@ struct fltree_onode_manager_test_t void validate_erased(iterator_t& it) { with_transaction([this, &it] (auto& t) { auto p_kv = *it; - auto exist = manager->contains_onode( - t, p_kv->key).unsafe_get0(); + auto exist = with_trans_intr(t, [&](auto &t) { + return manager->contains_onode(t, p_kv->key); + }).unsafe_get0(); ceph_assert(exist == false); }); } @@ -159,15 +164,18 @@ struct fltree_onode_manager_test_t const iterator_t& start, const iterator_t& end, F&& f) { with_onodes_process(start, end, [this, f=std::move(f)] (auto& t, auto& oids, auto& items) { - auto onodes = manager->get_or_create_onodes( - t, oids).unsafe_get0(); + auto onodes = with_trans_intr(t, [&](auto &t) { + return manager->get_or_create_onodes(t, oids); + }).unsafe_get0(); for (auto tup : boost::combine(onodes, items)) { OnodeRef onode; onode_item_t* p_item; boost::tie(onode, p_item) = tup; std::invoke(f, t, *onode, *p_item); } - manager->write_dirty(t, onodes).unsafe_get0(); + with_trans_intr(t, [&](auto &t) { + return manager->write_dirty(t, onodes); + }).unsafe_get0(); }); } @@ -179,7 +187,9 @@ struct fltree_onode_manager_test_t ghobject_t oid; onode_item_t* p_item; boost::tie(oid, p_item) = tup; - auto onode = manager->get_onode(t, oid).unsafe_get0(); + auto onode = with_trans_intr(t, [&](auto &t) { + return manager->get_onode(t, oid); + }).unsafe_get0(); p_item->validate(*onode); } }); @@ -190,8 +200,9 @@ struct fltree_onode_manager_test_t with_onodes_process(start, end, [this] (auto& t, auto& oids, auto& items) { for (auto& oid : oids) { - auto exist = manager->contains_onode( - t, oid).unsafe_get0(); + auto exist = with_trans_intr(t, [&](auto &t) { + return manager->contains_onode(t, oid); + }).unsafe_get0(); ceph_assert(exist == false); } }); @@ -208,8 +219,9 @@ struct fltree_onode_manager_test_t assert(start < oids[0]); assert(oids[0] < end); while (start != end) { - auto [list_ret, list_end] = manager->list_onodes( - t, start, end, LIST_LIMIT).unsafe_get0(); + auto [list_ret, list_end] = with_trans_intr(t, [&](auto &t) { + return manager->list_onodes(t, start, end, LIST_LIMIT); + }).unsafe_get0(); listed_oids.insert(listed_oids.end(), list_ret.begin(), list_ret.end()); start = list_end; } @@ -239,7 +251,9 @@ TEST_F(fltree_onode_manager_test_t, 1_single) with_onode_write(iter, [this](auto& t, auto& onode, auto& item) { OnodeRef onode_ref = &onode; - manager->erase_onode(t, onode_ref).unsafe_get0(); + with_trans_intr(t, [&](auto &t) { + return manager->erase_onode(t, onode_ref); + }).unsafe_get0(); }); validate_erased(iter); }); @@ -283,7 +297,9 @@ TEST_F(fltree_onode_manager_test_t, 2_synthetic) with_onodes_write(rd_start, rd_end, [this](auto& t, auto& onode, auto& item) { OnodeRef onode_ref = &onode; - manager->erase_onode(t, onode_ref).unsafe_get0(); + with_trans_intr(t, [&](auto &t) { + return manager->erase_onode(t, onode_ref); + }).unsafe_get0(); }); validate_erased(rd_start, rd_end); pool.erase_from_random(rd_start, rd_end); diff --git a/src/test/crimson/seastore/onode_tree/test_staged_fltree.cc b/src/test/crimson/seastore/onode_tree/test_staged_fltree.cc index e77df0c6b2b76..b6cf810639971 100644 --- a/src/test/crimson/seastore/onode_tree/test_staged_fltree.cc +++ b/src/test/crimson/seastore/onode_tree/test_staged_fltree.cc @@ -22,6 +22,30 @@ using namespace crimson::os::seastore::onode; +#define INTR(fun, t) \ + with_trans_intr( \ + t, \ + [&] (auto &tr) { \ + return fun(tr); \ + } \ + ) + +#define INTR_R(fun, t, args...) \ + with_trans_intr( \ + t, \ + [&] (auto &tr) { \ + return fun(tr, args); \ + } \ + ) + +#define INTR_WITH_PARAM(fun, c, b, v) \ + with_trans_intr( \ + c.t, \ + [=] (auto &t) { \ + return fun(c, b, v); \ + } \ + ) + namespace { constexpr bool IS_DUMMY_SYNC = false; using DummyManager = DummyNodeExtentManager; @@ -145,22 +169,22 @@ TEST_F(a_basic_test_t, 2_node_sizes) ValueBuilderImpl vb; context_t c{*nm, vb, *t}; std::array, 16> nodes = { - InternalNode0::allocate(c, false, 1u).unsafe_get0().make_pair(), - InternalNode1::allocate(c, false, 1u).unsafe_get0().make_pair(), - InternalNode2::allocate(c, false, 1u).unsafe_get0().make_pair(), - InternalNode3::allocate(c, false, 1u).unsafe_get0().make_pair(), - InternalNode0::allocate(c, true, 1u).unsafe_get0().make_pair(), - InternalNode1::allocate(c, true, 1u).unsafe_get0().make_pair(), - InternalNode2::allocate(c, true, 1u).unsafe_get0().make_pair(), - InternalNode3::allocate(c, true, 1u).unsafe_get0().make_pair(), - LeafNode0::allocate(c, false, 0u).unsafe_get0().make_pair(), - LeafNode1::allocate(c, false, 0u).unsafe_get0().make_pair(), - LeafNode2::allocate(c, false, 0u).unsafe_get0().make_pair(), - LeafNode3::allocate(c, false, 0u).unsafe_get0().make_pair(), - LeafNode0::allocate(c, true, 0u).unsafe_get0().make_pair(), - LeafNode1::allocate(c, true, 0u).unsafe_get0().make_pair(), - LeafNode2::allocate(c, true, 0u).unsafe_get0().make_pair(), - LeafNode3::allocate(c, true, 0u).unsafe_get0().make_pair() + INTR_WITH_PARAM(InternalNode0::allocate, c, false, 1u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(InternalNode1::allocate, c, false, 1u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(InternalNode2::allocate, c, false, 1u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(InternalNode3::allocate, c, false, 1u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(InternalNode0::allocate, c, true, 1u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(InternalNode1::allocate, c, true, 1u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(InternalNode2::allocate, c, true, 1u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(InternalNode3::allocate, c, true, 1u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(LeafNode0::allocate, c, false, 0u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(LeafNode1::allocate, c, false, 0u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(LeafNode2::allocate, c, false, 0u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(LeafNode3::allocate, c, false, 0u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(LeafNode0::allocate, c, true, 0u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(LeafNode1::allocate, c, true, 0u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(LeafNode2::allocate, c, true, 0u).unsafe_get0().make_pair(), + INTR_WITH_PARAM(LeafNode3::allocate, c, true, 0u).unsafe_get0().make_pair() }; std::ostringstream oss; oss << "\nallocated nodes:"; @@ -204,20 +228,21 @@ TEST_F(b_dummy_tree_test_t, 3_random_insert_erase_leaf_node) "\nrandomized leaf node insert:\n"); auto key_s = ghobject_t(); auto key_e = ghobject_t::get_max(); - ASSERT_TRUE(tree.find(t, key_s).unsafe_get0().is_end()); - ASSERT_TRUE(tree.begin(t).unsafe_get0().is_end()); - ASSERT_TRUE(tree.last(t).unsafe_get0().is_end()); + ASSERT_TRUE(INTR_R(tree.find, t, key_s).unsafe_get0().is_end()); + ASSERT_TRUE(INTR(tree.begin, t).unsafe_get0().is_end()); + ASSERT_TRUE(INTR(tree.last, t).unsafe_get0().is_end()); std::map> insert_history; auto f_validate_insert_new = [this, &insert_history] ( const ghobject_t& key, const test_item_t& value) { - auto [cursor, success] = tree.insert( - t, key, {value.get_payload_size()}).unsafe_get0(); + auto conf = UnboundedBtree::tree_value_config_t{value.get_payload_size()}; + auto [cursor, success] = INTR_R(tree.insert, + t, key, conf).unsafe_get0(); initialize_cursor_from_item(t, key, value, cursor, success); insert_history.emplace(key, std::make_tuple(value, cursor)); - auto cursor_ = tree.find(t, key).unsafe_get0(); + auto cursor_ = INTR_R(tree.find, t, key).unsafe_get0(); ceph_assert(cursor_ != tree.end()); ceph_assert(cursor_.value() == cursor.value()); validate_cursor_from_item(key, value, cursor_); @@ -225,12 +250,12 @@ TEST_F(b_dummy_tree_test_t, 3_random_insert_erase_leaf_node) }; auto f_validate_erase = [this, &insert_history] (const ghobject_t& key) { - auto cursor_erase = tree.find(t, key).unsafe_get0(); - auto cursor_next = cursor_erase.get_next(t).unsafe_get0(); - auto cursor_ret = tree.erase(t, cursor_erase).unsafe_get0(); + auto cursor_erase = INTR_R(tree.find, t, key).unsafe_get0(); + auto cursor_next = INTR(cursor_erase.get_next, t).unsafe_get0(); + auto cursor_ret = INTR_R(tree.erase, t, cursor_erase).unsafe_get0(); ceph_assert(cursor_erase.is_end()); ceph_assert(cursor_ret == cursor_next); - auto cursor_lb = tree.lower_bound(t, key).unsafe_get0(); + auto cursor_lb = INTR_R(tree.lower_bound, t, key).unsafe_get0(); ceph_assert(cursor_lb == cursor_next); auto it = insert_history.find(key); ceph_assert(std::get<1>(it->second).is_end()); @@ -253,18 +278,19 @@ TEST_F(b_dummy_tree_test_t, 3_random_insert_erase_leaf_node) // validate lookup { - auto cursor1_s = tree.lower_bound(t, key_s).unsafe_get0(); + auto cursor1_s = INTR_R(tree.lower_bound, t, key_s).unsafe_get0(); ASSERT_EQ(cursor1_s.get_ghobj(), key1); ASSERT_EQ(cursor1_s.value(), test_value1); - auto cursor1_e = tree.lower_bound(t, key_e).unsafe_get0(); + auto cursor1_e = INTR_R(tree.lower_bound, t, key_e).unsafe_get0(); ASSERT_TRUE(cursor1_e.is_end()); } // insert the same key1 with a different value { auto value1_dup = values.pick(); - auto [cursor1_dup, ret1_dup] = tree.insert( - t, key1, {value1_dup.get_payload_size()}).unsafe_get0(); + auto conf = UnboundedBtree::tree_value_config_t{value1_dup.get_payload_size()}; + auto [cursor1_dup, ret1_dup] = INTR_R(tree.insert, + t, key1, conf).unsafe_get0(); ASSERT_FALSE(ret1_dup); validate_cursor_from_item(key1, value1, cursor1_dup); } @@ -345,28 +371,28 @@ TEST_F(b_dummy_tree_test_t, 3_random_insert_erase_leaf_node) std::for_each(kvs.begin(), kvs.end(), [&f_insert_erase_insert] (auto& kv) { f_insert_erase_insert(kv.first, kv.second); }); - ASSERT_EQ(tree.height(t).unsafe_get0(), 1); + ASSERT_EQ(INTR(tree.height, t).unsafe_get0(), 1); ASSERT_FALSE(tree.test_is_clean()); for (auto& [k, val] : insert_history) { auto& [v, c] = val; // validate values in tree keep intact - auto cursor = tree.find(t, k).unsafe_get0(); + auto cursor = INTR_R(tree.find, t, k).unsafe_get0(); EXPECT_NE(cursor, tree.end()); validate_cursor_from_item(k, v, cursor); // validate values in cursors keep intact validate_cursor_from_item(k, v, c); } { - auto cursor = tree.lower_bound(t, key_s).unsafe_get0(); + auto cursor = INTR_R(tree.lower_bound, t, key_s).unsafe_get0(); validate_cursor_from_item(smallest_key, smallest_value, cursor); } { - auto cursor = tree.begin(t).unsafe_get0(); + auto cursor = INTR(tree.begin, t).unsafe_get0(); validate_cursor_from_item(smallest_key, smallest_value, cursor); } { - auto cursor = tree.last(t).unsafe_get0(); + auto cursor = INTR(tree.last, t).unsafe_get0(); validate_cursor_from_item(largest_key, largest_value, cursor); } @@ -381,11 +407,11 @@ TEST_F(b_dummy_tree_test_t, 3_random_insert_erase_leaf_node) std::sort(kvs.begin(), kvs.end(), [](auto& l, auto& r) { return l.first < r.first; }); - auto cursor = tree.begin(t).unsafe_get0(); + auto cursor = INTR(tree.begin, t).unsafe_get0(); for (auto& [k, v] : kvs) { ASSERT_FALSE(cursor.is_end()); validate_cursor_from_item(k, v, cursor); - cursor = cursor.get_next(t).unsafe_get0(); + cursor = INTR(cursor.get_next, t).unsafe_get0(); } ASSERT_TRUE(cursor.is_end()); } @@ -397,12 +423,12 @@ TEST_F(b_dummy_tree_test_t, 3_random_insert_erase_leaf_node) // randomized erase until empty std::random_shuffle(kvs.begin(), kvs.end()); for (auto& [k, v] : kvs) { - auto e_size = tree.erase(t, k).unsafe_get0(); + auto e_size = INTR_R(tree.erase, t, k).unsafe_get0(); ASSERT_EQ(e_size, 1); } - auto cursor = tree.begin(t).unsafe_get0(); + auto cursor = INTR(tree.begin, t).unsafe_get0(); ASSERT_TRUE(cursor.is_end()); - ASSERT_EQ(tree.height(t).unsafe_get0(), 1); + ASSERT_EQ(INTR(tree.height, t).unsafe_get0(), 1); }); } @@ -457,7 +483,7 @@ class TestTree { auto value = values.create(value_size); insert_tree(key, value).get0(); } - ASSERT_EQ(tree.height(t).unsafe_get0(), 1); + ASSERT_EQ(INTR(tree.height, t).unsafe_get0(), 1); ASSERT_FALSE(tree.test_is_clean()); //std::ostringstream oss; //tree.dump(t, oss); @@ -479,7 +505,7 @@ class TestTree { ++key_iter; ++value_iter; } - ASSERT_EQ(tree.height(t).unsafe_get0(), 1); + ASSERT_EQ(INTR(tree.height, t).unsafe_get0(), 1); ASSERT_FALSE(tree.test_is_clean()); //std::ostringstream oss; //tree.dump(t, oss); @@ -499,12 +525,13 @@ class TestTree { UnboundedBtree tree_clone(std::move(ref_dummy)); auto ref_t_clone = make_test_transaction(); Transaction& t_clone = *ref_t_clone; - tree_clone.test_clone_from(t_clone, t, tree).unsafe_get0(); + INTR_R(tree_clone.test_clone_from, t_clone, t, tree).unsafe_get0(); // insert and split logger().info("\n\nINSERT-SPLIT {}:", key_hobj_t(key)); - auto [cursor, success] = tree_clone.insert( - t_clone, key, {value.get_payload_size()}).unsafe_get0(); + auto conf = UnboundedBtree::tree_value_config_t{value.get_payload_size()}; + auto [cursor, success] = INTR_R(tree_clone.insert, + t_clone, key, conf).unsafe_get0(); initialize_cursor_from_item(t, key, value, cursor, success); { @@ -512,15 +539,15 @@ class TestTree { tree_clone.dump(t_clone, oss); logger().info("dump new root:\n{}", oss.str()); } - EXPECT_EQ(tree_clone.height(t_clone).unsafe_get0(), 2); + EXPECT_EQ(INTR(tree_clone.height, t_clone).unsafe_get0(), 2); for (auto& [k, val] : insert_history) { auto& [v, c] = val; - auto result = tree_clone.find(t_clone, k).unsafe_get0(); + auto result = INTR_R(tree_clone.find, t_clone, k).unsafe_get0(); EXPECT_NE(result, tree_clone.end()); validate_cursor_from_item(k, v, result); } - auto result = tree_clone.find(t_clone, key).unsafe_get0(); + auto result = INTR_R(tree_clone.find, t_clone, key).unsafe_get0(); EXPECT_NE(result, tree_clone.end()); validate_cursor_from_item(key, value, result); EXPECT_TRUE(last_split.match(expected)); @@ -528,11 +555,11 @@ class TestTree { // erase and merge logger().info("\n\nERASE-MERGE {}:", key_hobj_t(key)); - auto nxt_cursor = cursor.erase(t_clone).unsafe_get0(); + auto nxt_cursor = INTR(cursor.erase, t_clone).unsafe_get0(); { // track root again to dump - auto begin = tree_clone.begin(t_clone).unsafe_get0(); + auto begin = INTR(tree_clone.begin, t_clone).unsafe_get0(); std::ignore = begin; std::ostringstream oss; tree_clone.dump(t_clone, oss); @@ -550,12 +577,11 @@ class TestTree { for (auto& [k, val] : insert_history) { auto& [v, c] = val; - auto result = tree_clone.find(t_clone, k).unsafe_get0(); + auto result = INTR_R(tree_clone.find, t_clone, k).unsafe_get0(); EXPECT_NE(result, tree_clone.end()); validate_cursor_from_item(k, v, result); } - - EXPECT_EQ(tree_clone.height(t_clone).unsafe_get0(), 1); + EXPECT_EQ(INTR(tree_clone.height, t_clone).unsafe_get0(), 1); EXPECT_EQ(p_dummy->size(), 1); }); } @@ -567,8 +593,9 @@ class TestTree { private: seastar::future<> insert_tree(const ghobject_t& key, const test_item_t& value) { return seastar::async([this, &key, &value] { - auto [cursor, success] = tree.insert( - t, key, {value.get_payload_size()}).unsafe_get0(); + auto conf = UnboundedBtree::tree_value_config_t{value.get_payload_size()}; + auto [cursor, success] = INTR_R(tree.insert, + t, key, conf).unsafe_get0(); initialize_cursor_from_item(t, key, value, cursor, success); insert_history.emplace(key, std::make_tuple(value, cursor)); }); @@ -835,10 +862,10 @@ class DummyChildPool { build_name(); return search_position_t::end(); } - eagain_future<> retire_extent(context_t) override { + eagain_ifuture<> retire_extent(context_t) override { assert(!_is_extent_retired); _is_extent_retired = true; - return seastar::now(); + return eagain_iertr::now(); } protected: @@ -871,7 +898,7 @@ class DummyChildPool { ceph_abort("impossible path"); } search_position_t merge(NodeExtentMutable&, NodeImpl&, match_stage_t, extent_len_t) override { ceph_abort("impossible path"); } - eagain_future rebuild_extent(context_t) override { + eagain_ifuture rebuild_extent(context_t) override { ceph_abort("impossible path"); } node_stats_t get_stats() const override { ceph_abort("impossible path"); } @@ -913,7 +940,7 @@ class DummyChildPool { key_view_t get_pivot_key() const { return *impl->get_pivot_index(); } - eagain_future<> populate_split( + eagain_ifuture<> populate_split( context_t c, std::set>& splitable_nodes) { ceph_assert(can_split()); ceph_assert(splitable_nodes.find(this) != splitable_nodes.end()); @@ -941,10 +968,10 @@ class DummyChildPool { } Ref this_ref = this; return apply_split_to_parent( - c, std::move(this_ref), std::move(right_child), false); + c, std::move(this_ref), std::move(right_child), false); } - eagain_future<> insert_and_split( + eagain_ifuture<> insert_and_split( context_t c, const ghobject_t& insert_key, std::set>& splitable_nodes) { const auto& keys = impl->get_keys(); @@ -964,9 +991,9 @@ class DummyChildPool { return fut; } - eagain_future<> merge(context_t c, Ref&& this_ref) { + eagain_ifuture<> merge(context_t c, Ref&& this_ref) { return parent_info().ptr->get_child_peers(c, parent_info().position - ).safe_then([c, this_ref = std::move(this_ref), this] (auto lr_nodes) mutable { + ).si_then([c, this_ref = std::move(this_ref), this] (auto lr_nodes) mutable { auto& [lnode, rnode] = lr_nodes; if (rnode) { lnode.reset(); @@ -985,7 +1012,7 @@ class DummyChildPool { }); } - eagain_future<> fix_key(context_t c, const ghobject_t& new_key) { + eagain_ifuture<> fix_key(context_t c, const ghobject_t& new_key) { const auto& keys = impl->get_keys(); ceph_assert(keys.size() == 1); assert(impl->is_level_tail() == false); @@ -1015,24 +1042,24 @@ class DummyChildPool { return create(keys, is_level_tail, seed++, pool); } - static eagain_future> create_initial( + static eagain_ifuture> create_initial( context_t c, const std::set& keys, DummyChildPool& pool, RootNodeTracker& root_tracker) { auto initial = create_new(keys, true, pool); return c.nm.get_super(c.t, root_tracker - ).handle_error( - eagain_ertr::pass_further{}, + ).handle_error_interruptible( + eagain_iertr::pass_further{}, crimson::ct_error::assert_all{"Invalid error during create_initial()"} - ).safe_then([c, &pool, initial](auto super) { + ).si_then([c, &pool, initial](auto super) { initial->make_root_new(c, std::move(super)); - return initial->upgrade_root(c).safe_then([initial] { + return initial->upgrade_root(c).si_then([initial] { return initial; }); }); } protected: - eagain_future<> test_clone_non_root( + eagain_ifuture<> test_clone_non_root( context_t, Ref new_parent) const override { ceph_assert(!is_root()); auto p_pool_clone = pool.pool_clone_in_progress; @@ -1040,18 +1067,18 @@ class DummyChildPool { auto clone = create( impl->get_keys(), impl->is_level_tail(), impl->laddr(), *p_pool_clone); clone->as_child(parent_info().position, new_parent); - return seastar::now(); + return eagain_iertr::now(); } - eagain_future> lookup_smallest(context_t) override { + eagain_ifuture> lookup_smallest(context_t) override { ceph_abort("impossible path"); } - eagain_future> lookup_largest(context_t) override { + eagain_ifuture> lookup_largest(context_t) override { ceph_abort("impossible path"); } - eagain_future<> test_clone_root(context_t, RootNodeTracker&) const override { + eagain_ifuture<> test_clone_root(context_t, RootNodeTracker&) const override { ceph_abort("impossible path"); } - eagain_future lower_bound_tracked( + eagain_ifuture lower_bound_tracked( context_t, const key_hobj_t&, MatchHistory&) override { ceph_abort("impossible path"); } - eagain_future<> do_get_tree_stats(context_t, tree_stats_t&) override { + eagain_ifuture<> do_get_tree_stats(context_t, tree_stats_t&) override { ceph_abort("impossible path"); } bool is_tracking() const override { return false; } void track_merge(Ref, match_stage_t, search_position_t&) override { @@ -1065,7 +1092,7 @@ class DummyChildPool { bool can_split() const { return impl->get_keys().size() > 1; } - static eagain_future<> do_merge( + static eagain_ifuture<> do_merge( context_t c, Ref&& left, Ref&& right, bool stole_key) { assert(right->use_count() == 1); assert(left->impl->get_keys().size() == 1); @@ -1094,37 +1121,38 @@ class DummyChildPool { eagain_future<> build_tree(const std::set& keys) { reset(); - // create tree auto ref_dummy = NodeExtentManager::create_dummy(IS_DUMMY_SYNC); p_dummy = static_cast(ref_dummy.get()); p_btree.emplace(std::move(ref_dummy)); - return DummyChild::create_initial(get_context(), keys, *this, *p_btree->root_tracker - ).safe_then([this](auto initial_child) { - // split - splitable_nodes.insert(initial_child); - return crimson::repeat([this] () - -> eagain_future { - if (splitable_nodes.empty()) { - return seastar::make_ready_future( - seastar::stop_iteration::yes); - } - auto index = rd() % splitable_nodes.size(); - auto iter = splitable_nodes.begin(); - std::advance(iter, index); - Ref child = *iter; - return child->populate_split(get_context(), splitable_nodes - ).safe_then([] { - return seastar::stop_iteration::no; + return with_trans_intr(get_context().t, [this, &keys] (auto &tr) { + return DummyChild::create_initial(get_context(), keys, *this, *p_btree->root_tracker + ).si_then([this](auto initial_child) { + // split + splitable_nodes.insert(initial_child); + return trans_intr::repeat([this] () + -> eagain_ifuture { + if (splitable_nodes.empty()) { + return seastar::make_ready_future( + seastar::stop_iteration::yes); + } + auto index = rd() % splitable_nodes.size(); + auto iter = splitable_nodes.begin(); + std::advance(iter, index); + Ref child = *iter; + return child->populate_split(get_context(), splitable_nodes + ).si_then([] { + return seastar::stop_iteration::no; + }); }); - }); - }).safe_then([this] { + }).si_then([this] { //std::ostringstream oss; //p_btree->dump(t(), oss); //logger().info("\n{}\n", oss.str()); - return p_btree->height(t()); - }).safe_then([](auto height) { - ceph_assert(height == 2); + return p_btree->height(t()); + }).si_then([](auto height) { + ceph_assert(height == 2); + }); }); } @@ -1137,14 +1165,17 @@ class DummyChildPool { // insert and split logger().info("\n\nINSERT-SPLIT {} at pos({}):", key_hobj_t(key), pos); auto node_to_split = pool_clone.get_node_by_pos(pos); - node_to_split->insert_and_split( - pool_clone.get_context(), key, pool_clone.splitable_nodes).unsafe_get0(); + with_trans_intr(pool_clone.get_context().t, [&] (auto &t) { + return node_to_split->insert_and_split( + pool_clone.get_context(), key, pool_clone.splitable_nodes); + }).unsafe_get0(); { std::ostringstream oss; pool_clone.p_btree->dump(pool_clone.t(), oss); logger().info("dump new root:\n{}", oss.str()); } - EXPECT_EQ(pool_clone.p_btree->height(pool_clone.t()).unsafe_get0(), 3); + auto &pt = pool_clone.t(); + EXPECT_EQ(INTR(pool_clone.p_btree->height, pt).unsafe_get0(), 3); EXPECT_TRUE(last_split.match(expected)); EXPECT_EQ(pool_clone.p_dummy->size(), 3); @@ -1152,9 +1183,12 @@ class DummyChildPool { auto pivot_key = node_to_split->get_pivot_key(); logger().info("\n\nERASE-MERGE {}:", node_to_split->get_name()); assert(pivot_key.compare_to(key_hobj_t(key)) == MatchKindCMP::EQ); - node_to_split->merge( - pool_clone.get_context(), std::move(node_to_split)).unsafe_get0(); - EXPECT_EQ(pool_clone.p_btree->height(pool_clone.t()).unsafe_get0(), 2); + with_trans_intr(pool_clone.get_context().t, [&] (auto &t) { + return node_to_split->merge( + pool_clone.get_context(), std::move(node_to_split)); + }).unsafe_get0(); + auto &pt2 = pool_clone.t(); + EXPECT_EQ(INTR(pool_clone.p_btree->height ,pt2).unsafe_get0(), 2); EXPECT_EQ(pool_clone.p_dummy->size(), 1); }); } @@ -1170,23 +1204,30 @@ class DummyChildPool { auto old_key = node_to_fix->get_pivot_key().to_ghobj(); logger().info("\n\nFIX pos({}) from {} to {}, expect_split={}:", pos, node_to_fix->get_name(), key_hobj_t(new_key), expect_split); - node_to_fix->fix_key(pool_clone.get_context(), new_key).unsafe_get0(); + with_trans_intr(pool_clone.get_context().t, [&] (auto &t) { + return node_to_fix->fix_key(pool_clone.get_context(), new_key); + }).unsafe_get0(); if (expect_split) { std::ostringstream oss; pool_clone.p_btree->dump(pool_clone.t(), oss); logger().info("dump new root:\n{}", oss.str()); - EXPECT_EQ(pool_clone.p_btree->height(pool_clone.t()).unsafe_get0(), 3); + auto &pt = pool_clone.t(); + EXPECT_EQ(INTR(pool_clone.p_btree->height, pt).unsafe_get0(), 3); EXPECT_EQ(pool_clone.p_dummy->size(), 3); } else { - EXPECT_EQ(pool_clone.p_btree->height(pool_clone.t()).unsafe_get0(), 2); + auto &pt = pool_clone.t(); + EXPECT_EQ(INTR(pool_clone.p_btree->height, pt).unsafe_get0(), 2); EXPECT_EQ(pool_clone.p_dummy->size(), 1); } // fix back logger().info("\n\nFIX pos({}) from {} back to {}:", pos, node_to_fix->get_name(), key_hobj_t(old_key)); - node_to_fix->fix_key(pool_clone.get_context(), old_key).unsafe_get0(); - EXPECT_EQ(pool_clone.p_btree->height(pool_clone.t()).unsafe_get0(), 2); + with_trans_intr(pool_clone.get_context().t, [&] (auto &t) { + return node_to_fix->fix_key(pool_clone.get_context(), old_key); + }).unsafe_get0(); + auto &pt = pool_clone.t(); + EXPECT_EQ(INTR(pool_clone.p_btree->height, pt).unsafe_get0(), 2); EXPECT_EQ(pool_clone.p_dummy->size(), 1); }); } @@ -1197,8 +1238,10 @@ class DummyChildPool { auto ref_dummy = NodeExtentManager::create_dummy(IS_DUMMY_SYNC); pool_clone.p_dummy = static_cast(ref_dummy.get()); pool_clone.p_btree.emplace(std::move(ref_dummy)); - pool_clone.p_btree->test_clone_from( - pool_clone.t(), t(), *p_btree).unsafe_get0(); + auto &pt = pool_clone.t(); + [[maybe_unused]] auto &tr = t(); + INTR_R(pool_clone.p_btree->test_clone_from, + pt, tr, *p_btree).unsafe_get0(); pool_clone_in_progress = nullptr; } @@ -1528,14 +1571,14 @@ TEST_F(d_seastore_tm_test_t, 6_random_tree_insert_erase) {8, 11, 64, 256, 301, 320}, {8, 16, 128, 512, 576, 640}, {0, 16}, {0, 10}, {0, 4}); - auto moved_nm = (TEST_SEASTORE ? NodeExtentManager::create_seastore(itm) + auto moved_nm = (TEST_SEASTORE ? NodeExtentManager::create_seastore(*tm) : NodeExtentManager::create_dummy(IS_DUMMY_SYNC)); auto p_nm = moved_nm.get(); auto tree = std::make_unique>( kvs, std::move(moved_nm)); { auto t = create_mutate_transaction(); - tree->bootstrap(*t).unsafe_get(); + INTR(tree->bootstrap, *t).unsafe_get(); submit_transaction(std::move(t)); segment_cleaner->run_until_halt().get0(); } @@ -1543,69 +1586,71 @@ TEST_F(d_seastore_tm_test_t, 6_random_tree_insert_erase) // test insert { auto t = create_mutate_transaction(); - tree->insert(*t).unsafe_get(); + INTR(tree->insert, *t).unsafe_get(); submit_transaction(std::move(t)); segment_cleaner->run_until_halt().get0(); } { auto t = create_read_transaction(); - tree->get_stats(*t).unsafe_get(); + INTR(tree->get_stats, *t).unsafe_get(); } if constexpr (TEST_SEASTORE) { logger().info("seastore replay insert begin"); restart(); - tree->reload(NodeExtentManager::create_seastore(itm)); + tree->reload(NodeExtentManager::create_seastore(*tm)); logger().info("seastore replay insert end"); } { // Note: create_weak_transaction() can also work, but too slow. auto t = create_read_transaction(); - tree->validate(*t).unsafe_get(); + INTR(tree->validate, *t).unsafe_get(); } // test erase 3/4 { auto t = create_mutate_transaction(); - tree->erase(*t, kvs.size() / 4 * 3).unsafe_get(); + auto size = kvs.size() / 4 * 3; + INTR_R(tree->erase, *t, size).unsafe_get(); submit_transaction(std::move(t)); segment_cleaner->run_until_halt().get0(); } { auto t = create_read_transaction(); - tree->get_stats(*t).unsafe_get(); + INTR(tree->get_stats, *t).unsafe_get(); } if constexpr (TEST_SEASTORE) { logger().info("seastore replay erase-1 begin"); restart(); - tree->reload(NodeExtentManager::create_seastore(itm)); + tree->reload(NodeExtentManager::create_seastore(*tm)); logger().info("seastore replay erase-1 end"); } { auto t = create_read_transaction(); - tree->validate(*t).unsafe_get(); + INTR(tree->validate, *t).unsafe_get(); } // test erase remaining { auto t = create_mutate_transaction(); - tree->erase(*t, kvs.size()).unsafe_get(); + auto size = kvs.size(); + INTR_R(tree->erase, *t, size).unsafe_get(); submit_transaction(std::move(t)); segment_cleaner->run_until_halt().get0(); } { auto t = create_read_transaction(); - tree->get_stats(*t).unsafe_get(); + INTR(tree->get_stats, *t).unsafe_get(); } if constexpr (TEST_SEASTORE) { logger().info("seastore replay erase-2 begin"); restart(); - tree->reload(NodeExtentManager::create_seastore(itm)); + tree->reload(NodeExtentManager::create_seastore(*tm)); logger().info("seastore replay erase-2 end"); } { auto t = create_read_transaction(); - tree->validate(*t).unsafe_get(); - EXPECT_EQ(tree->height(*t).unsafe_get0(), 1); + INTR(tree->validate, *t).unsafe_get(); + EXPECT_EQ(INTR(tree->height, *t).unsafe_get0(), 1); } if constexpr (!TEST_SEASTORE) { @@ -1627,7 +1672,7 @@ TEST_F(d_seastore_tm_test_t, 7_tree_insert_erase_eagain) {8, 16, 128, 576, 992, 1200}, {0, 8}, {0, 10}, {0, 4}); auto moved_nm = NodeExtentManager::create_seastore( - itm, L_ADDR_MIN, EAGAIN_PROBABILITY); + *tm, L_ADDR_MIN, EAGAIN_PROBABILITY); auto p_nm = static_cast*>(moved_nm.get()); auto tree = std::make_unique>( kvs, std::move(moved_nm)); @@ -1641,7 +1686,7 @@ TEST_F(d_seastore_tm_test_t, 7_tree_insert_erase_eagain) return seastar::do_with( create_mutate_transaction(), [this, &tree](auto &t) { - return tree->bootstrap(*t + return INTR(tree->bootstrap, *t ).safe_then([this, &t] { return submit_transaction_fut(*t); }); @@ -1660,7 +1705,7 @@ TEST_F(d_seastore_tm_test_t, 7_tree_insert_erase_eagain) return seastar::do_with( create_mutate_transaction(), [this, &tree, &iter](auto &t) { - return tree->insert_one(*t, iter + return INTR_R(tree->insert_one, *t, iter ).safe_then([this, &t](auto cursor) { cursor.invalidate(); return submit_transaction_fut(*t); @@ -1675,7 +1720,7 @@ TEST_F(d_seastore_tm_test_t, 7_tree_insert_erase_eagain) { p_nm->set_generate_eagain(false); auto t = create_read_transaction(); - tree->get_stats(*t).unsafe_get0(); + INTR(tree->get_stats, *t).unsafe_get0(); p_nm->set_generate_eagain(true); } @@ -1688,7 +1733,7 @@ TEST_F(d_seastore_tm_test_t, 7_tree_insert_erase_eagain) repeat_eagain2([this, &tree, &num_ops_eagain, &iter] { ++num_ops_eagain; auto t = create_read_transaction(); - return tree->validate_one(*t, iter + return INTR_R(tree->validate_one, *t, iter ).safe_then([t=std::move(t)]{}); }).get0(); ++iter; @@ -1707,7 +1752,7 @@ TEST_F(d_seastore_tm_test_t, 7_tree_insert_erase_eagain) return seastar::do_with( create_mutate_transaction(), [this, &tree, &iter](auto &t) { - return tree->erase_one(*t, iter + return INTR_R(tree->erase_one, *t, iter ).safe_then([this, &t] () mutable { return submit_transaction_fut(*t); }); @@ -1722,9 +1767,9 @@ TEST_F(d_seastore_tm_test_t, 7_tree_insert_erase_eagain) { p_nm->set_generate_eagain(false); auto t = create_read_transaction(); - tree->get_stats(*t).unsafe_get0(); - tree->validate(*t).unsafe_get0(); - EXPECT_EQ(tree->height(*t).unsafe_get0(), 1); + INTR(tree->get_stats, *t).unsafe_get0(); + INTR(tree->validate, *t).unsafe_get0(); + EXPECT_EQ(INTR(tree->height,*t).unsafe_get0(), 1); } // we can adjust EAGAIN_PROBABILITY to get a proper eagain_rate