Transaction &trans,
OnodeRef &onode) = 0;
+ using list_onodes_ertr = base_ertr;
+ using list_onodes_bare_ret = std::tuple<std::vector<ghobject_t>, ghobject_t>;
+ using list_onodes_ret = list_onodes_ertr::future<list_onodes_bare_ret>;
+ virtual list_onodes_ret list_onodes(
+ Transaction &trans,
+ const ghobject_t& start,
+ const ghobject_t& end,
+ uint64_t limit) = 0;
+
virtual ~OnodeManager() {}
};
using OnodeManagerRef = std::unique_ptr<OnodeManager>;
return erase_onode_ertr::now();
}
+FLTreeOnodeManager::list_onodes_ret FLTreeOnodeManager::list_onodes(
+ Transaction &trans,
+ const ghobject_t& start,
+ const ghobject_t& end,
+ uint64_t limit)
+{
+ return tree.lower_bound(trans, start
+ ).safe_then([this, &trans, end, limit] (auto&& cursor) {
+ using crimson::os::seastore::onode::full_key_t;
+ return seastar::do_with(
+ limit,
+ std::move(cursor),
+ list_onodes_bare_ret(),
+ [this, &trans, end] (auto& to_list, auto& current_cursor, auto& ret) {
+ using get_next_ertr = typename OnodeTree::btree_ertr;
+ return crimson::do_until(
+ [this, &trans, end, &to_list, ¤t_cursor, &ret] () mutable
+ -> get_next_ertr::future<bool> {
+ if (current_cursor.is_end() ||
+ current_cursor.get_ghobj() >= end) {
+ std::get<1>(ret) = end;
+ return seastar::make_ready_future<bool>(true);
+ }
+ if (to_list == 0) {
+ std::get<1>(ret) = current_cursor.get_ghobj();
+ return seastar::make_ready_future<bool>(true);
+ }
+ std::get<0>(ret).emplace_back(current_cursor.get_ghobj());
+ return tree.get_next(trans, current_cursor
+ ).safe_then([&to_list, ¤t_cursor] (auto&& next_cursor) mutable {
+ // we intentionally hold the current_cursor during get_next() to
+ // accelerate tree lookup.
+ --to_list;
+ current_cursor = next_cursor;
+ return seastar::make_ready_future<bool>(false);
+ });
+ }).safe_then([&ret] () mutable {
+ return seastar::make_ready_future<list_onodes_bare_ret>(
+ std::move(ret));
+ });
+ });
+ }).handle_error(
+ list_onodes_ertr::pass_further{},
+ crimson::ct_error::assert_all{
+ "Invalid error in FLTreeOnodeManager::list_onodes"
+ }
+ );
+}
+
FLTreeOnodeManager::~FLTreeOnodeManager() {}
}
});
}
+ static constexpr uint64_t LIST_LIMIT = 10;
+ void validate_list_onodes(KVPool<onode_item_t>& pool) {
+ with_onodes_process(pool.begin(), pool.end(),
+ [this] (auto& t, auto& oids, auto& items) {
+ std::vector<ghobject_t> listed_oids;
+ auto start = ghobject_t();
+ auto end = ghobject_t::get_max();
+ assert(start < end);
+ 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();
+ listed_oids.insert(listed_oids.end(), list_ret.begin(), list_ret.end());
+ start = list_end;
+ }
+ ceph_assert(oids.size() == listed_oids.size());
+ });
+ }
+
fltree_onode_manager_test_t() {}
};
});
validate_onode(iter);
+ validate_list_onodes(pool);
+
with_onode_write(iter, [this](auto& t, auto& onode, auto& item) {
OnodeRef onode_ref = &onode;
manager->erase_onode(t, onode_ref).unsafe_get0();
});
validate_onodes(start, end);
+ validate_list_onodes(pool);
+
auto rd_start = pool.random_begin();
auto rd_end = rd_start + 50;
with_onodes_write(rd_start, rd_end,
start = pool.begin();
end = pool.end();
validate_onodes(start, end);
+
+ validate_list_onodes(pool);
});
}