Internally, get key_view_t when lookup into the leaf node.
Signed-off-by: Yingxin Cheng <yingxin.cheng@intel.com>
* tree_cursor_t
*/
+tree_cursor_t::tree_cursor_t(Ref<LeafNode> node, const search_position_t& pos)
+ : leaf_node{node}, position{pos} {
+ assert(!is_end());
+ leaf_node->do_track_cursor(*this);
+}
+
tree_cursor_t::tree_cursor_t(
Ref<LeafNode> node, const search_position_t& pos,
- const onode_t* _p_value, layout_version_t v)
+ const key_view_t& key, const onode_t* _p_value, layout_version_t v)
: leaf_node{node}, position{pos} {
assert(!is_end());
- update_p_value(_p_value, v);
+ update_kv(key, _p_value, v);
leaf_node->do_track_cursor(*this);
}
}
}
+const key_view_t& tree_cursor_t::get_key_view() const {
+ ensure_kv();
+ return *key_view;
+}
+
const onode_t* tree_cursor_t::get_p_value() const {
- assert(!is_end());
- if (!p_value || node_version != leaf_node->get_layout_version()) {
- // NOTE: the leaf node is always present when we hold its reference.
- std::tie(p_value, node_version) = leaf_node->get_p_value(position);
- }
- assert(p_value);
+ ensure_kv();
return p_value;
}
assert(!is_end());
leaf_node = node;
position = pos;
+ key_view.reset();
p_value = nullptr;
leaf_node->do_track_cursor(*this);
}
-void tree_cursor_t::update_p_value(const onode_t* _p_value, layout_version_t v) {
+void tree_cursor_t::update_kv(
+ const key_view_t& key, const onode_t* _p_value, layout_version_t v) const {
assert(!is_end());
assert(_p_value);
- assert(std::make_pair(_p_value, v) == leaf_node->get_p_value(position));
+ assert(std::make_tuple(key, _p_value, v) == leaf_node->get_kv(position));
+ key_view = key;
p_value = _p_value;
node_version = v;
}
+void tree_cursor_t::ensure_kv() const {
+ assert(!is_end());
+ if (!p_value || node_version != leaf_node->get_layout_version()) {
+ // NOTE: the leaf node is always present when we hold its reference.
+ std::tie(key_view, p_value, node_version) = leaf_node->get_kv(position);
+ }
+ assert(p_value);
+}
+
/*
* Node
*/
return impl->is_level_tail();
}
-std::pair<const onode_t*, layout_version_t> LeafNode::get_p_value(
+std::tuple<key_view_t, const onode_t*, layout_version_t> LeafNode::get_kv(
const search_position_t& pos) const {
- return {impl->get_p_value(pos), layout_version};
+ key_view_t key_view;
+ auto p_value = impl->get_p_value(pos, &key_view);
+ return {key_view, p_value, layout_version};
}
node_future<Ref<tree_cursor_t>>
new tree_cursor_t(this));
}
auto pos = search_position_t::begin();
- auto p_value = impl->get_p_value(pos);
+ key_view_t index_key;
+ auto p_value = impl->get_p_value(pos, &index_key);
return node_ertr::make_ready_future<Ref<tree_cursor_t>>(
- get_or_track_cursor(pos, p_value));
+ get_or_track_cursor(pos, index_key, p_value));
}
node_future<Ref<tree_cursor_t>>
}
search_position_t pos;
const onode_t* p_value = nullptr;
- impl->get_largest_value(pos, p_value);
+ key_view_t index_key;
+ impl->get_largest_slot(pos, index_key, &p_value);
return node_ertr::make_ready_future<Ref<tree_cursor_t>>(
- get_or_track_cursor(pos, p_value));
+ get_or_track_cursor(pos, index_key, p_value));
}
node_future<Node::search_result_t>
LeafNode::lower_bound_tracked(
context_t c, const key_hobj_t& key, MatchHistory& history) {
- auto result = impl->lower_bound(key, history);
+ key_view_t index_key;
+ auto result = impl->lower_bound(key, history, &index_key);
Ref<tree_cursor_t> cursor;
if (result.position.is_end()) {
assert(!result.p_value);
cursor = new tree_cursor_t(this);
} else {
- cursor = get_or_track_cursor(result.position, result.p_value);
+ cursor = get_or_track_cursor(result.position, index_key, result.p_value);
}
return node_ertr::make_ready_future<search_result_t>(
search_result_t{cursor, result.match()});
}
Ref<tree_cursor_t> LeafNode::get_or_track_cursor(
- const search_position_t& position, const onode_t* p_value) {
+ const search_position_t& position,
+ const key_view_t& key, const onode_t* p_value) {
assert(!position.is_end());
assert(p_value);
Ref<tree_cursor_t> p_cursor;
auto found = tracked_cursors.find(position);
if (found == tracked_cursors.end()) {
- p_cursor = new tree_cursor_t(this, position, p_value, layout_version);
+ p_cursor = new tree_cursor_t(this, position, key, p_value, layout_version);
} else {
p_cursor = found->second;
assert(p_cursor->get_leaf_node() == this);
assert(p_cursor->get_position() == position);
- p_cursor->update_p_value(p_value, layout_version);
+ p_cursor->update_kv(key, p_value, layout_version);
}
return p_cursor;
}
void LeafNode::validate_cursor(tree_cursor_t& cursor) const {
+#ifndef NDEBUG
assert(this == cursor.get_leaf_node().get());
assert(!cursor.is_end());
- assert(impl->get_p_value(cursor.get_position()) == cursor.get_p_value());
+ auto [key, val, ver] = get_kv(cursor.get_position());
+ assert(key == cursor.get_key_view());
+ assert(val == cursor.get_p_value());
+#endif
}
Ref<tree_cursor_t> LeafNode::track_insert(
}
// track insert
- return new tree_cursor_t(this, insert_pos, p_onode, layout_version);
+ // TODO: getting key_view_t from stage::proceed_insert() and
+ // stage::append_insert() has not supported yet
+ return new tree_cursor_t(this, insert_pos);
}
void LeafNode::track_split(
#include "crimson/common/type_helpers.h"
#include "node_extent_mutable.h"
+#include "stages/key_layout.h"
#include "stages/stage_types.h"
#include "super.h"
#include "tree_types.h"
* LeafNode --> tree_cursor_t*
*/
-struct key_hobj_t;
class LeafNode;
class InternalNode;
tree_cursor_t& operator=(tree_cursor_t&&) = delete;
bool is_end() const { return position.is_end(); }
+ const key_view_t& get_key_view() const;
const onode_t* get_p_value() const;
private:
+ tree_cursor_t(Ref<LeafNode>, const search_position_t&);
tree_cursor_t(Ref<LeafNode>, const search_position_t&,
- const onode_t*, layout_version_t);
+ const key_view_t& key, const onode_t*, layout_version_t);
// lookup reaches the end, contain leaf node for further insert
tree_cursor_t(Ref<LeafNode>);
const search_position_t& get_position() const { return position; }
Ref<LeafNode> get_leaf_node() { return leaf_node; }
void update_track(Ref<LeafNode>, const search_position_t&);
- void update_p_value(const onode_t*, layout_version_t);
+ void update_kv(const key_view_t&, const onode_t*, layout_version_t) const;
+ void ensure_kv() const;
private:
Ref<LeafNode> leaf_node;
search_position_t position;
// cached information
+ mutable std::optional<key_view_t> key_view;
mutable const onode_t* p_value;
mutable layout_version_t node_version;
bool is_level_tail() const;
layout_version_t get_layout_version() const { return layout_version; }
- std::pair<const onode_t*, layout_version_t> get_p_value(
+ std::tuple<key_view_t, const onode_t*, layout_version_t> get_kv(
const search_position_t&) const;
void do_track_cursor(tree_cursor_t& cursor) {
validate_cursor(cursor);
private:
// XXX: extract a common tracker for InternalNode to track Node,
// and LeafNode to track tree_cursor_t.
- Ref<tree_cursor_t> get_or_track_cursor(const search_position_t&, const onode_t*);
+ Ref<tree_cursor_t> get_or_track_cursor(
+ const search_position_t&, const key_view_t&, const onode_t*);
Ref<tree_cursor_t> track_insert(
const search_position_t&, match_stage_t, const onode_t*);
void track_split(const search_position_t&, Ref<LeafNode>);
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
virtual const laddr_t* get_p_value(
- const search_position_t&, internal_marker_t={}) const {
+ const search_position_t&,
+ key_view_t* = nullptr, internal_marker_t = {}) const {
assert(false && "impossible path");
}
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
virtual lookup_result_t<node_type_t::INTERNAL> lower_bound(
- const key_hobj_t&, MatchHistory&, internal_marker_t={}) const {
+ const key_hobj_t&, MatchHistory&,
+ key_view_t* = nullptr, internal_marker_t = {}) const {
assert(false && "impossible path");
}
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
virtual const onode_t* get_p_value(
- const search_position_t&, leaf_marker_t={}) const {
+ const search_position_t&,
+ key_view_t* = nullptr, leaf_marker_t={}) const {
assert(false && "impossible path");
}
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
virtual lookup_result_t<node_type_t::LEAF> lower_bound(
- const key_hobj_t&, MatchHistory&, leaf_marker_t={}) const {
+ const key_hobj_t&, MatchHistory&,
+ key_view_t* = nullptr, leaf_marker_t = {}) const {
assert(false && "impossible path");
}
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
assert(false && "impossible path");
}
- virtual void get_largest_value(search_position_t&, const onode_t*&) const = 0;
+ virtual void get_largest_slot(
+ search_position_t&, key_view_t&, const onode_t**) const = 0;
virtual std::tuple<match_stage_t, node_offset_t> evaluate_insert(
const key_hobj_t&, const onode_t&,
const MatchHistory&, search_position_t&) const = 0;
}
key_view_t get_largest_key_view() const override {
- key_view_t ret;
- STAGE_T::lookup_largest_index(extent.read(), ret);
- return ret;
+ key_view_t index_key;
+ STAGE_T::template lookup_largest_slot<false, true, false>(
+ extent.read(), nullptr, &index_key, nullptr);
+ return index_key;
}
std::ostream& dump(std::ostream& os) const override {
/*
* Common
*/
- const value_t* get_p_value(
- const search_position_t& position, marker_t={}) const override {
+ const value_t* get_p_value(const search_position_t& position,
+ key_view_t* index_key=nullptr, marker_t={}) const override {
auto& node_stage = extent.read();
if constexpr (NODE_TYPE == node_type_t::INTERNAL) {
+ assert(!index_key);
if (position.is_end()) {
assert(is_level_tail());
return node_stage.get_end_p_laddr();
} else {
assert(!position.is_end());
}
- return STAGE_T::get_p_value(node_stage, cast_down<STAGE>(position));
+ if (index_key) {
+ return STAGE_T::template get_p_value<true>(
+ node_stage, cast_down<STAGE>(position), index_key);
+ } else {
+ return STAGE_T::get_p_value(node_stage, cast_down<STAGE>(position));
+ }
}
lookup_result_t<NODE_TYPE> lower_bound(
- const key_hobj_t& key, MatchHistory& history, marker_t={}) const override {
+ const key_hobj_t& key, MatchHistory& history,
+ key_view_t* index_key=nullptr, marker_t={}) const override {
auto& node_stage = extent.read();
if constexpr (NODE_TYPE == node_type_t::LEAF) {
if (unlikely(node_stage.keys() == 0)) {
}
}
- auto result_raw = STAGE_T::lower_bound(node_stage, key, history);
+ typename STAGE_T::result_t result_raw;
+ if (index_key) {
+ result_raw = STAGE_T::template lower_bound<true>(
+ node_stage, key, history, index_key);
+#ifndef NDEBUG
+ if (!result_raw.is_end()) {
+ full_key_t<KeyT::VIEW> index;
+ STAGE_T::get_key_view(node_stage, result_raw.position, index);
+ assert(index == *index_key);
+ }
+#endif
+ } else {
+ result_raw = STAGE_T::lower_bound(node_stage, key, history);
+ }
#ifndef NDEBUG
if (result_raw.is_end()) {
assert(result_raw.mstat == MSTAT_END);
/*
* LeafNodeImpl
*/
- void get_largest_value(search_position_t& pos, const onode_t*& p_value) const override {
+ void get_largest_slot(search_position_t& pos,
+ key_view_t& index_key, const onode_t** pp_value) const override {
if constexpr (NODE_TYPE == node_type_t::LEAF) {
- STAGE_T::lookup_largest(extent.read(), cast_down_fill_0<STAGE>(pos), p_value);
+ STAGE_T::template lookup_largest_slot<true, true, true>(
+ extent.read(), &cast_down_fill_0<STAGE>(pos), &index_key, pp_value);
} else {
assert(false && "impossible path");
}
}
}
size_t size() const { return length + sizeof(string_size_t); }
+ std::string_view to_string_view() const {
+ assert(type() == Type::STR);
+ return {p_key, length};
+ }
bool operator==(const string_key_view_t& x) const {
if (type() == x.type() && type() != Type::STR)
return true;
return *p_snap_gen;
}
+ ghobject_t to_ghobj() const {
+ ghobject_t ghobj;
+ ghobj.shard_id.id = shard();
+ ghobj.hobj.pool = pool();
+ ghobj.hobj.set_hash(crush());
+ ghobj.hobj.nspace = nspace().to_string_view();
+ ghobj.hobj.oid.name = oid().to_string_view();
+ ghobj.hobj.snap = snap();
+ ghobj.generation = gen();
+ return ghobj;
+ }
+
void set(const crush_t& key) {
assert(!has_crush());
p_crush = &key;
* Lookup internals (hide?)
*/
- static result_t smallest_result(const iterator_t& iter) {
+ template <bool GET_KEY>
+ static result_t smallest_result(
+ const iterator_t& iter, full_key_t<KeyT::VIEW>* index_key) {
static_assert(!IS_BOTTOM);
assert(!iter.is_end());
auto pos_smallest = NXT_STAGE_T::position_t::begin();
auto nxt_container = iter.get_nxt_container();
- auto value_ptr = NXT_STAGE_T::get_p_value(nxt_container, pos_smallest);
+ auto value_ptr = NXT_STAGE_T::template get_p_value<GET_KEY>(
+ nxt_container, pos_smallest, index_key);
+ if constexpr (GET_KEY) {
+ index_key->set(iter.get_key());
+ }
return result_t{{iter.index(), pos_smallest}, value_ptr, STAGE};
}
+ template <bool GET_KEY>
static result_t nxt_lower_bound(
- const full_key_t<KeyT::HOBJ>& key, iterator_t& iter, MatchHistory& history) {
+ const full_key_t<KeyT::HOBJ>& key, iterator_t& iter,
+ MatchHistory& history, full_key_t<KeyT::VIEW>* index_key) {
static_assert(!IS_BOTTOM);
assert(!iter.is_end());
auto nxt_container = iter.get_nxt_container();
- auto nxt_result = NXT_STAGE_T::lower_bound(nxt_container, key, history);
+ auto nxt_result = NXT_STAGE_T::template lower_bound<GET_KEY>(
+ nxt_container, key, history, index_key);
if (nxt_result.is_end()) {
if (iter.is_last()) {
return result_t::end();
} else {
- return smallest_result(++iter);
+ return smallest_result<GET_KEY>(++iter, index_key);
}
} else {
+ if constexpr (GET_KEY) {
+ index_key->set(iter.get_key());
+ }
return result_t::from_nxt(iter.index(), nxt_result);
}
}
- static void lookup_largest(
- const container_t& container, position_t& position, const value_t*& p_value) {
+ template <bool GET_POS, bool GET_KEY, bool GET_VAL>
+ static void lookup_largest_slot(
+ const container_t& container, position_t* p_position,
+ full_key_t<KeyT::VIEW>* p_index_key, const value_t** pp_value) {
auto iter = iterator_t(container);
iter.seek_last();
- position.index = iter.index();
+ if constexpr (GET_KEY) {
+ assert(p_index_key);
+ p_index_key->set(iter.get_key());
+ }
+ if constexpr (GET_POS) {
+ assert(p_position);
+ p_position->index = iter.index();
+ }
if constexpr (IS_BOTTOM) {
- p_value = iter.get_p_value();
+ if constexpr (GET_VAL) {
+ assert(pp_value);
+ *pp_value = iter.get_p_value();
+ }
} else {
auto nxt_container = iter.get_nxt_container();
- NXT_STAGE_T::lookup_largest(nxt_container, position.nxt, p_value);
- }
- }
-
- static void lookup_largest_index(
- const container_t& container, full_key_t<KeyT::VIEW>& output) {
- auto iter = iterator_t(container);
- iter.seek_last();
- output.set(iter.get_key());
- if constexpr (!IS_BOTTOM) {
- auto nxt_container = iter.get_nxt_container();
- NXT_STAGE_T::lookup_largest_index(nxt_container, output);
+ if constexpr (GET_POS) {
+ NXT_STAGE_T::template lookup_largest_slot<true, GET_KEY, GET_VAL>(
+ nxt_container, &p_position->nxt, p_index_key, pp_value);
+ } else {
+ NXT_STAGE_T::template lookup_largest_slot<false, GET_KEY, GET_VAL>(
+ nxt_container, nullptr, p_index_key, pp_value);
+ }
}
}
+ template <bool GET_KEY = false>
static const value_t* get_p_value(
- const container_t& container, const position_t& position) {
+ const container_t& container, const position_t& position,
+ full_key_t<KeyT::VIEW>* index_key = nullptr) {
auto iter = iterator_t(container);
iter.seek_at(position.index);
+ if constexpr (GET_KEY) {
+ index_key->set(iter.get_key());
+ }
if constexpr (!IS_BOTTOM) {
auto nxt_container = iter.get_nxt_container();
- return NXT_STAGE_T::get_p_value(nxt_container, position.nxt);
+ return NXT_STAGE_T::template get_p_value<GET_KEY>(
+ nxt_container, position.nxt, index_key);
} else {
return iter.get_p_value();
}
static void get_key_view(
const container_t& container,
const position_t& position,
- full_key_t<KeyT::VIEW>& output) {
+ full_key_t<KeyT::VIEW>& index_key) {
auto iter = iterator_t(container);
iter.seek_at(position.index);
- output.set(iter.get_key());
+ index_key.set(iter.get_key());
if constexpr (!IS_BOTTOM) {
auto nxt_container = iter.get_nxt_container();
- return NXT_STAGE_T::get_key_view(nxt_container, position.nxt, output);
+ return NXT_STAGE_T::get_key_view(nxt_container, position.nxt, index_key);
}
}
+ template <bool GET_KEY = false>
static result_t lower_bound(
const container_t& container,
const full_key_t<KeyT::HOBJ>& key,
- MatchHistory& history) {
+ MatchHistory& history,
+ full_key_t<KeyT::VIEW>* index_key = nullptr) {
bool exclude_last = false;
if (history.get<STAGE>().has_value()) {
if (*history.get<STAGE>() == MatchKindCMP::EQ) {
test_key_equal = (cmp == MatchKindCMP::EQ);
}
if (test_key_equal) {
- return nxt_lower_bound(key, iter, history);
+ return nxt_lower_bound<GET_KEY>(key, iter, history, index_key);
} else {
// key[stage] < index[stage][left-most]
- return smallest_result(iter);
+ return smallest_result<GET_KEY>(iter, index_key);
}
}
}
} else {
assert(compare_to<KeyT::HOBJ>(key, iter.get_key()) == MatchKindCMP::EQ);
}
+ if constexpr (GET_KEY) {
+ index_key->set(iter.get_key());
+ }
if constexpr (IS_BOTTOM) {
auto value_ptr = iter.get_p_value();
return result_t{{iter.index()}, value_ptr, MSTAT_EQ};
} else {
auto nxt_container = iter.get_nxt_container();
- auto nxt_result = NXT_STAGE_T::lower_bound(nxt_container, key, history);
+ auto nxt_result = NXT_STAGE_T::template lower_bound<GET_KEY>(
+ nxt_container, key, history, index_key);
// !history.is_PO<STAGE - 1>() means
// key[stage+1 ...] <= index[stage+1 ...][*]
assert(!nxt_result.is_end());
history.set<STAGE>(bs_match == MatchKindBS::EQ ?
MatchKindCMP::EQ : MatchKindCMP::NE);
if constexpr (IS_BOTTOM) {
+ if constexpr (GET_KEY) {
+ index_key->set(iter.get_key());
+ }
auto value_ptr = iter.get_p_value();
return result_t{{iter.index()}, value_ptr,
(bs_match == MatchKindBS::EQ ? MSTAT_EQ : MSTAT_NE0)};
} else {
if (bs_match == MatchKindBS::EQ) {
- return nxt_lower_bound(key, iter, history);
+ return nxt_lower_bound<GET_KEY>(key, iter, history, index_key);
} else {
- return smallest_result(iter);
+ return smallest_result<GET_KEY>(iter, index_key);
}
}
}
#include "node.h"
#include "node_extent_manager.h"
-#include "stages/key_layout.h" // full_key_t<KeyT::HOBJ>
+#include "stages/key_layout.h"
#include "super.h"
namespace crimson::os::seastore::onode {
}
}
-const ghobject_t& Cursor::get_ghobj() {
- // TODO
- assert(false && "not implemented");
+ghobject_t Cursor::get_ghobj() const {
+ return p_cursor->get_key_view().to_ghobj();
}
const onode_t* Cursor::value() const {
~Cursor();
bool is_end() const;
- const ghobject_t& get_ghobj();
+ // XXX: return key_view_t to avoid unecessary ghobject_t constructions
+ ghobject_t get_ghobj() const;
const onode_t* value() const;
bool operator==(const Cursor& x) const;
bool operator!=(const Cursor& x) const { return !(*this == x); }
}
static void validate_cursor(
- const Btree::Cursor& cursor, const onode_t& onode) {
+ const Btree::Cursor& cursor, const ghobject_t& key, const onode_t& onode) {
assert(!cursor.is_end());
+ assert(cursor.get_ghobj() == key);
assert(cursor.value());
assert(cursor.value() != &onode);
assert(*cursor.value() == onode);
auto [cursor, success] = tree.insert(t, key, value).unsafe_get0();
assert(success == true);
insert_history.emplace_back(key, &value, cursor);
- Onodes::validate_cursor(cursor, value);
+ Onodes::validate_cursor(cursor, key, value);
auto cursor_ = tree.lower_bound(t, key).unsafe_get0();
assert(cursor_.value() == cursor.value());
return cursor.value();
auto [cursor1_dup, ret1_dup] = tree.insert(
t, key1, onode1_dup).unsafe_get0();
assert(ret1_dup == false);
- Onodes::validate_cursor(cursor1_dup, onode1);
+ Onodes::validate_cursor(cursor1_dup, key1, onode1);
}
// insert key2, onode2 to key1's left at STAGE_LEFT
{make_ghobj(4, 4, 4, "ns3", "oid3", 2, 2), &onodes.pick()},
{make_ghobj(4, 4, 4, "ns4", "oid4", 2, 2), &onodes.pick()},
{make_ghobj(4, 4, 4, "ns4", "oid4", 4, 4), &onodes.pick()}};
- auto& smallest_value = *kvs[0].second;
- auto& largest_value = *kvs[kvs.size() - 1].second;
+ auto [smallest_key, smallest_value] = kvs[0];
+ auto [largest_key, largest_value] = kvs[kvs.size() - 1];
std::random_shuffle(kvs.begin(), kvs.end());
std::for_each(kvs.begin(), kvs.end(), [&f_validate_insert_new] (auto& kv) {
f_validate_insert_new(kv.first, *kv.second);
for (auto& [k, v, c] : insert_history) {
// validate values in tree keep intact
auto cursor = tree.lower_bound(t, k).unsafe_get0();
- Onodes::validate_cursor(cursor, *v);
+ Onodes::validate_cursor(cursor, k, *v);
// validate values in cursors keep intact
- Onodes::validate_cursor(c, *v);
+ Onodes::validate_cursor(c, k, *v);
}
Onodes::validate_cursor(
- tree.lower_bound(t, key_s).unsafe_get0(), smallest_value);
+ tree.lower_bound(t, key_s).unsafe_get0(), smallest_key, *smallest_value);
Onodes::validate_cursor(
- tree.begin(t).unsafe_get0(), smallest_value);
+ tree.begin(t).unsafe_get0(), smallest_key, *smallest_value);
Onodes::validate_cursor(
- tree.last(t).unsafe_get0(), largest_value);
+ tree.last(t).unsafe_get0(), largest_key, *largest_value);
std::ostringstream oss;
tree.dump(t, oss);
auto& value = onodes.create(120);
auto [cursor, success] = tree.insert(t, key, value).unsafe_get0();
assert(success == true);
- Onodes::validate_cursor(cursor, value);
+ Onodes::validate_cursor(cursor, key, value);
insert_history.emplace_back(key, &value, cursor);
}
assert(tree.height(t).unsafe_get0() == 1);
logger().info("insert {}:", key_hobj_t(key));
auto [cursor, success] = tree_clone.insert(t_clone, key, value).unsafe_get0();
assert(success == true);
- Onodes::validate_cursor(cursor, value);
+ Onodes::validate_cursor(cursor, key, value);
std::ostringstream oss;
tree_clone.dump(t_clone, oss);
for (auto& [k, v, c] : insert_history) {
auto result = tree_clone.lower_bound(t_clone, k).unsafe_get0();
- Onodes::validate_cursor(result, *v);
+ Onodes::validate_cursor(result, k, *v);
}
auto result = tree_clone.lower_bound(t_clone, key).unsafe_get0();
- Onodes::validate_cursor(result, value);
+ Onodes::validate_cursor(result, key, value);
};
auto& onode = onodes.create(1280);