NodeExtentMutable::NodeExtentMutable(NodeExtent& extent)
: extent{extent} {
- assert(extent.is_pending());
+ assert(extent.is_pending() || // during mutation
+ extent.is_clean()); // during replay
}
const char* NodeExtentMutable::get_read() const {
- assert(extent.is_pending());
+ assert(extent.is_pending() || // during mutation
+ extent.is_clean()); // during replay
return extent.get_bptr().c_str();
}
char* NodeExtentMutable::get_write() {
- assert(extent.is_pending());
+ assert(extent.is_pending() || // during mutation
+ extent.is_clean()); // during replay
return extent.get_bptr().c_str();
}
using future = ertr::future<ValueT>;
TreeBuilder(KVPool& kvs, NodeExtentManagerURef&& nm)
- : kvs{kvs}, tree{std::move(nm)} {}
+ : kvs{kvs} {
+ tree.emplace(std::move(nm));
+ }
future<> bootstrap(Transaction& t) {
std::ostringstream oss;
} else {
oss << "track=off, ";
}
- oss << tree;
+ oss << *tree;
logger().warn("TreeBuilder: {}, bootstrapping ...", oss.str());
- return tree.mkfs(t);
+ return tree->mkfs(t);
}
future<> insert(Transaction& t) {
}
auto [key, p_value] = kv_iter.get_kv();
logger().debug("[{}] {} -> {}", kv_iter.index(), key_hobj_t{key}, *p_value);
- return tree.insert(t, key, *p_value
+ return tree->insert(t, key, *p_value
).safe_then([&t, this, cursors](auto ret) {
auto& [cursor, success] = ret;
assert(success == true);
#ifndef NDEBUG
auto [key, p_value] = kv_iter.get_kv();
Onodes::validate_cursor(cursor, key, *p_value);
- return tree.lower_bound(t, key).safe_then([this, cursor](auto cursor_) {
+ return tree->lower_bound(t, key).safe_then([this, cursor](auto cursor_) {
auto [key, p_value] = kv_iter.get_kv();
ceph_assert(cursor_.get_ghobj() == key);
ceph_assert(cursor_.value() == cursor.value());
assert(c_iter != cursors->end());
auto [k, v] = kv_iter.get_kv();
// validate values in tree keep intact
- return tree.lower_bound(t, k).safe_then([this, &c_iter](auto cursor) {
+ return tree->lower_bound(t, k).safe_then([this, &c_iter](auto cursor) {
auto [k, v] = kv_iter.get_kv();
Onodes::validate_cursor(cursor, k, *v);
// validate values in cursors keep intact
}
future<> get_stats(Transaction& t) {
- return tree.get_stats_slow(t
+ return tree->get_stats_slow(t
).safe_then([this](auto stats) {
logger().warn("{}", stats);
});
}
+ void reload(NodeExtentManagerURef&& nm) {
+ tree.emplace(std::move(nm));
+ }
+
future<> validate(Transaction& t) {
logger().info("Verifing insertion ...");
return seastar::do_with(
return ertr::make_ready_future<bool>(true);
}
auto [k, v] = kvs_iter.get_kv();
- return tree.lower_bound(t, k
+ return tree->lower_bound(t, k
).safe_then([&kvs_iter, k=k, v=v] (auto cursor) {
Onodes::validate_cursor(cursor, k, *v);
++kvs_iter;
}
KVPool& kvs;
- Btree tree;
+ std::optional<Btree> tree;
KVPool::iterator_t kv_iter;
};
TEST_F(d_seastore_tm_test_t, 6_random_insert_leaf_node)
{
run_async([this] {
+ constexpr bool TEST_SEASTORE = true;
constexpr bool TRACK_CURSORS = true;
KVPool kvs{{8, 11, 64, 256, 301, 320},
{8, 16, 128, 512, 576, 640},
{0, 32}, {0, 10}, {0, 4}};
auto tree = std::make_unique<TreeBuilder<TRACK_CURSORS>>(kvs,
-#if 0
- NodeExtentManager::create_dummy(IS_DUMMY_SYNC)
-#else
- NodeExtentManager::create_seastore(*tm)
-#endif
- );
+ (TEST_SEASTORE ? NodeExtentManager::create_seastore(*tm)
+ : NodeExtentManager::create_dummy(IS_DUMMY_SYNC)));
{
auto t = tm->create_transaction();
tree->bootstrap(*t).unsafe_get();
tree->get_stats(*t).unsafe_get();
tm->submit_transaction(std::move(t)).unsafe_get();
}
+ if constexpr (TEST_SEASTORE) {
+ logger().info("seastore replay begin");
+ restart();
+ tree->reload(NodeExtentManager::create_seastore(*tm));
+ logger().info("seastore replay end");
+ }
{
// Note: tm->create_weak_transaction() can also work, but too slow.
auto t = tm->create_transaction();