Some btree visitor tidying.

Introduce node_location to replace the long list of parameters.  Also
add a depth field to keep track of the depth from root.
This commit is contained in:
Joe Thornber
2013-05-01 16:16:23 +01:00
parent 1884233a2b
commit 5d0b23beea
7 changed files with 109 additions and 95 deletions

View File

@ -263,6 +263,14 @@ namespace persistent_data {
std::list<block_manager<>::write_ref> spine_;
block_address root_;
};
// Used when visiting the nodes that make up a btree.
struct node_location {
unsigned level;
unsigned depth;
bool sub_root;
boost::optional<uint64_t> key;
};
}
template <unsigned Levels, typename ValueTraits>
@ -308,23 +316,25 @@ namespace persistent_data {
// inspect the individual nodes that make up a btree.
class visitor {
public:
virtual ~visitor() {}
typedef boost::shared_ptr<visitor> ptr;
typedef btree_detail::node_location node_location;
virtual ~visitor() {}
// The bool return values indicate whether the walk
// should be continued into sub trees of the node (true == continue).
virtual bool visit_internal(unsigned level, bool sub_root, boost::optional<uint64_t> key,
virtual bool visit_internal(node_location const &l,
internal_node const &n) = 0;
virtual bool visit_internal_leaf(unsigned level, bool sub_root, boost::optional<uint64_t> key,
virtual bool visit_internal_leaf(node_location const &l,
internal_node const &n) = 0;
virtual bool visit_leaf(unsigned level, bool sub_root, boost::optional<uint64_t> key,
virtual bool visit_leaf(node_location const &l,
leaf_node const &n) = 0;
virtual void visit_complete() {}
};
// Walks the tree in depth first order
void visit(typename visitor::ptr visitor) const;
void visit_depth_first(typename visitor::ptr visitor) const;
private:
template <typename ValueTraits2, typename Search>
@ -353,7 +363,7 @@ namespace persistent_data {
int *index);
void walk_tree(typename visitor::ptr visitor,
unsigned level, bool root, boost::optional<uint64_t> key,
btree_detail::node_location const &loc,
block_address b) const;
typename persistent_data::transaction_manager::ptr tm_;

View File

@ -742,37 +742,57 @@ insert_location(btree_detail::shadow_spine &spine,
template <unsigned Levels, typename ValueTraits>
void
btree<Levels, ValueTraits>::visit(typename visitor::ptr visitor) const
btree<Levels, ValueTraits>::visit_depth_first(typename visitor::ptr visitor) const
{
walk_tree(visitor, 0, true, boost::optional<uint64_t>(), root_);
node_location loc;
loc.level = 0;
loc.depth = 0;
loc.sub_root = true;
loc.key = boost::optional<uint64_t>();
walk_tree(visitor, loc, root_);
visitor->visit_complete();
}
template <unsigned Levels, typename ValueTraits>
void
btree<Levels, ValueTraits>::
walk_tree(typename visitor::ptr visitor,
unsigned level, bool sub_root,
boost::optional<uint64_t> key,
block_address b) const
btree<Levels, ValueTraits>::walk_tree(typename visitor::ptr visitor,
node_location const &loc,
block_address b) const
{
using namespace btree_detail;
read_ref blk = tm_->read_lock(b);
internal_node o = to_node<uint64_traits>(blk);
if (o.get_type() == INTERNAL) {
if (visitor->visit_internal(level, sub_root, key, o))
for (unsigned i = 0; i < o.get_nr_entries(); i++)
walk_tree(visitor, level, false, o.key_at(i), o.value_at(i));
if (visitor->visit_internal(loc, o))
for (unsigned i = 0; i < o.get_nr_entries(); i++) {
node_location loc2(loc);
} else if (level < Levels - 1) {
if (visitor->visit_internal_leaf(level, sub_root, key, o))
for (unsigned i = 0; i < o.get_nr_entries(); i++)
walk_tree(visitor, level + 1, true, boost::optional<uint64_t>(o.key_at(i)), o.value_at(i));
loc2.depth = loc.depth + 1;
loc2.sub_root = false;
loc2.key = boost::optional<uint64_t>(o.key_at(i));
walk_tree(visitor, loc2, o.value_at(i));
}
} else if (loc.level < Levels - 1) {
if (visitor->visit_internal_leaf(loc, o))
for (unsigned i = 0; i < o.get_nr_entries(); i++) {
node_location loc2(loc);
loc2.level = loc.level + 1;
loc2.depth = loc.depth + 1;
loc2.sub_root = true;
loc2.key = boost::optional<uint64_t>(o.key_at(i));
walk_tree(visitor, loc, o.value_at(i));
}
} else {
leaf_node ov = to_node<ValueTraits>(blk);
visitor->visit_leaf(level, sub_root, key, ov);
visitor->visit_leaf(loc, ov);
}
}

View File

@ -57,31 +57,27 @@ namespace persistent_data {
template <uint32_t Levels, typename ValueTraits>
class btree_checker : public btree<Levels, ValueTraits>::visitor {
public:
typedef btree_detail::node_location node_location;
btree_checker(block_counter &counter, bool avoid_repeated_visits = true)
: counter_(counter),
errs_(new error_set("btree errors")),
avoid_repeated_visits_(avoid_repeated_visits) {
}
bool visit_internal(unsigned level,
bool sub_root,
optional<uint64_t> key,
bool visit_internal(node_location const &loc,
btree_detail::node_ref<uint64_traits> const &n) {
return check_internal(level, sub_root, key, n);
return check_internal(loc, n);
}
bool visit_internal_leaf(unsigned level,
bool sub_root,
optional<uint64_t> key,
bool visit_internal_leaf(node_location const &loc,
btree_detail::node_ref<uint64_traits> const &n) {
return check_leaf(level, sub_root, key, n);
return check_leaf(loc, n);
}
bool visit_leaf(unsigned level,
bool sub_root,
optional<uint64_t> key,
bool visit_leaf(node_location const &loc,
btree_detail::node_ref<ValueTraits> const &n) {
return check_leaf(level, sub_root, key, n);
return check_leaf(loc, n);
}
error_set::ptr get_errors() const {
@ -94,19 +90,17 @@ namespace persistent_data {
}
private:
bool check_internal(unsigned level,
bool sub_root,
optional<uint64_t> key,
bool check_internal(node_location const &loc,
btree_detail::node_ref<uint64_traits> const &n) {
if (!already_visited(n) &&
check_sum(n) &&
check_block_nr(n) &&
check_max_entries(n) &&
check_nr_entries(n, sub_root) &&
check_nr_entries(n, loc.sub_root) &&
check_ordered_keys(n) &&
check_parent_key(sub_root ? optional<uint64_t>() : key, n)) {
if (sub_root)
new_root(level);
check_parent_key(loc.sub_root ? optional<uint64_t>() : loc.key, n)) {
if (loc.sub_root)
new_root(loc.level);
return true;
}
@ -115,21 +109,19 @@ namespace persistent_data {
}
template <typename ValueTraits2>
bool check_leaf(unsigned level,
bool sub_root,
optional<uint64_t> key,
btree_detail::node_ref<ValueTraits2> const &n) {
bool check_leaf(node_location const &loc,
btree_detail::node_ref<ValueTraits2> const &n) {
if (!already_visited(n) &&
check_sum(n) &&
check_block_nr(n) &&
check_max_entries(n) &&
check_nr_entries(n, sub_root) &&
check_nr_entries(n, loc.sub_root) &&
check_ordered_keys(n) &&
check_parent_key(sub_root ? optional<uint64_t>() : key, n)) {
if (sub_root)
new_root(level);
check_parent_key(loc.sub_root ? optional<uint64_t>() : loc.key, n)) {
if (loc.sub_root)
new_root(loc.level);
return check_leaf_key(level, n);
return check_leaf_key(loc.level, n);
}
return false;