mirror of
https://github.com/ceph/ceph
synced 2025-01-01 08:32:24 +00:00
crimson/seastore: convert onode unit test to use interruptible future.
Signed-off-by: chunmei-liu <chunmei.liu@intel.com>
This commit is contained in:
parent
6d0426468a
commit
f61e94ff93
@ -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);
|
||||
|
@ -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<IS_DUMMY_SYNC>;
|
||||
@ -145,22 +169,22 @@ TEST_F(a_basic_test_t, 2_node_sizes)
|
||||
ValueBuilderImpl<UnboundedValue> vb;
|
||||
context_t c{*nm, vb, *t};
|
||||
std::array<std::pair<NodeImplURef, NodeExtentMutable>, 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<ghobject_t,
|
||||
std::tuple<test_item_t, UnboundedBtree::Cursor>> 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<true>(t_clone).unsafe_get0();
|
||||
auto nxt_cursor = INTR(cursor.erase<true>, 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<NodeExtentMutable> rebuild_extent(context_t) override {
|
||||
eagain_ifuture<NodeExtentMutable> 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<Ref<DummyChild>>& splitable_nodes) {
|
||||
ceph_assert(can_split());
|
||||
ceph_assert(splitable_nodes.find(this) != splitable_nodes.end());
|
||||
@ -941,10 +968,10 @@ class DummyChildPool {
|
||||
}
|
||||
Ref<Node> 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<Ref<DummyChild>>& splitable_nodes) {
|
||||
const auto& keys = impl->get_keys();
|
||||
@ -964,9 +991,9 @@ class DummyChildPool {
|
||||
return fut;
|
||||
}
|
||||
|
||||
eagain_future<> merge(context_t c, Ref<DummyChild>&& this_ref) {
|
||||
eagain_ifuture<> merge(context_t c, Ref<DummyChild>&& 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<Ref<DummyChild>> create_initial(
|
||||
static eagain_ifuture<Ref<DummyChild>> create_initial(
|
||||
context_t c, const std::set<ghobject_t>& 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<InternalNode> 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<Ref<tree_cursor_t>> lookup_smallest(context_t) override {
|
||||
eagain_ifuture<Ref<tree_cursor_t>> lookup_smallest(context_t) override {
|
||||
ceph_abort("impossible path"); }
|
||||
eagain_future<Ref<tree_cursor_t>> lookup_largest(context_t) override {
|
||||
eagain_ifuture<Ref<tree_cursor_t>> 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<search_result_t> lower_bound_tracked(
|
||||
eagain_ifuture<search_result_t> 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<Node>, 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<DummyChild>&& left, Ref<DummyChild>&& 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<ghobject_t>& keys) {
|
||||
reset();
|
||||
|
||||
// create tree
|
||||
auto ref_dummy = NodeExtentManager::create_dummy(IS_DUMMY_SYNC);
|
||||
p_dummy = static_cast<DummyManager*>(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<seastar::stop_iteration> {
|
||||
if (splitable_nodes.empty()) {
|
||||
return seastar::make_ready_future<seastar::stop_iteration>(
|
||||
seastar::stop_iteration::yes);
|
||||
}
|
||||
auto index = rd() % splitable_nodes.size();
|
||||
auto iter = splitable_nodes.begin();
|
||||
std::advance(iter, index);
|
||||
Ref<DummyChild> 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<seastar::stop_iteration> {
|
||||
if (splitable_nodes.empty()) {
|
||||
return seastar::make_ready_future<seastar::stop_iteration>(
|
||||
seastar::stop_iteration::yes);
|
||||
}
|
||||
auto index = rd() % splitable_nodes.size();
|
||||
auto iter = splitable_nodes.begin();
|
||||
std::advance(iter, index);
|
||||
Ref<DummyChild> 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<DummyManager*>(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<TreeBuilder<TRACK_CURSORS, BoundedValue>>(
|
||||
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<SeastoreNodeExtentManager<true>*>(moved_nm.get());
|
||||
auto tree = std::make_unique<TreeBuilder<TRACK_CURSORS, ExtendedValue>>(
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user