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>;
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:";
"\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_);
};
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());
// 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);
}
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);
}
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());
}
// 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);
});
}
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);
++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);
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);
{
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));
// 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);
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);
});
}
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));
});
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:
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"); }
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());
}
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();
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();
});
}
- 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);
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;
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 {
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);
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);
+ });
});
}
// 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);
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);
});
}
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);
});
}
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;
}
{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();
}
// 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) {
{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));
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);
});
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);
{
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);
}
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;
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);
});
{
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