[btree] allow people to visit all the nodes in a btree.

This commit is contained in:
Joe Thornber 2011-08-22 11:55:55 +01:00
parent 9be40b76b5
commit 4d37416075
3 changed files with 72 additions and 0 deletions

19
btree.h
View File

@ -299,6 +299,22 @@ namespace persistent_data {
// free the on disk btree when the destructor is called
void destroy();
// Derive a class from this base class if you need to
// inspect the individual nodes that make up a btree.
class visitor {
public:
virtual ~visitor() {}
typedef boost::shared_ptr<visitor> ptr;
virtual void visit_internal(unsigned level, btree_detail::node_ref<uint64_traits, BlockSize> const &n) = 0;
virtual void visit_internal_leaf(unsigned level, btree_detail::node_ref<uint64_traits, BlockSize> const &n) = 0;
virtual void visit_leaf(unsigned level, btree_detail::node_ref<ValueTraits, BlockSize> const &n) = 0;
};
// Walks the tree in depth first order
void visit(typename visitor::ptr visitor);
private:
template <typename ValueTraits2>
void split_node(btree_detail::shadow_spine<BlockSize> &spine,
@ -321,6 +337,9 @@ namespace persistent_data {
uint64_t key,
int *index);
void walk_tree(typename visitor::ptr visitor,
unsigned level, block_address b);
typename persistent_data::transaction_manager<BlockSize>::ptr tm_;
bool destroy_;
block_address root_;

View File

@ -590,5 +590,36 @@ insert_location(btree_detail::shadow_spine<BlockSize> &spine,
(leaf.key_at(i) != key));
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
void
btree<Levels, ValueTraits, BlockSize>::visit(typename visitor::ptr visitor)
{
walk_tree(visitor, 0, root_);
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
void
btree<Levels, ValueTraits, BlockSize>::
walk_tree(typename visitor::ptr visitor,
unsigned level, block_address b)
{
using namespace btree_detail;
auto blk = tm_->read_lock(b);
auto o = to_node<uint64_traits, BlockSize>(blk);
if (o.get_type() == INTERNAL) {
visitor->visit_internal(level, o);
for (unsigned i = 0; i < o.get_nr_entries(); i++)
walk_tree(visitor, level, o.value_at(i));
} else if (level < Levels - 1) {
visitor->visit_internal_leaf(level, o);
for (unsigned i = 0; i < o.get_nr_entries(); i++)
walk_tree(visitor, level + 1, o.value_at(i));
} else {
auto ov = to_node<ValueTraits, BlockSize>(blk);
visitor->visit_leaf(level, ov);
}
}
//----------------------------------------------------------------

View File

@ -30,6 +30,28 @@ namespace {
new btree<1, uint64_traits, 4096>(
create_tm(), rc));
}
class constraint_visitor : public btree<1, uint64_traits, 4096>::visitor {
private:
void visit_internal(unsigned level, btree_detail::node_ref<uint64_traits, 4096> const &n) {
// cout << "internal: level = " << level << ", nr_entries = " << n.get_nr_entries() << endl;
}
void visit_internal_leaf(unsigned level, btree_detail::node_ref<uint64_traits, 4096> const &n) {
// cout << "internal_leaf !" << endl;
}
void visit_leaf(unsigned level, btree_detail::node_ref<uint64_traits, 4096> const &n) {
// cout << "leaf: level = " << level << ", nr_entries = " << n.get_nr_entries() << endl;
}
};
void check_constraints(btree<1, uint64_traits, 4096>::ptr tree) {
typedef btree<1, uint64_traits, 4096> tree_type;
typename tree_type::visitor::ptr v(new constraint_visitor);
tree->visit(v);
}
}
//----------------------------------------------------------------