[btree] use a block_ref_counter for internal nodes
This commit is contained in:
parent
e89d81e318
commit
83a09e1a2a
@ -38,6 +38,8 @@ PDATA_SOURCE=\
|
|||||||
persistent-data/lock_tracker.cc \
|
persistent-data/lock_tracker.cc \
|
||||||
persistent-data/transaction_manager.cc \
|
persistent-data/transaction_manager.cc \
|
||||||
\
|
\
|
||||||
|
persistent-data/data-structures/btree.cc \
|
||||||
|
\
|
||||||
persistent-data/space_map.cc \
|
persistent-data/space_map.cc \
|
||||||
persistent-data/space-maps/disk.cc \
|
persistent-data/space-maps/disk.cc \
|
||||||
persistent-data/space-maps/recursive.cc \
|
persistent-data/space-maps/recursive.cc \
|
||||||
|
28
persistent-data/data-structures/btree.cc
Normal file
28
persistent-data/data-structures/btree.cc
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "persistent-data/data-structures/btree.h"
|
||||||
|
|
||||||
|
using namespace persistent_data;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
block_ref_counter::block_ref_counter(space_map::ptr sm)
|
||||||
|
: sm_(sm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
block_ref_counter::set(block_address const &b, uint32_t rc) {
|
||||||
|
sm_->set_count(b, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
block_ref_counter::inc(block_address const &b) {
|
||||||
|
sm_->inc(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
block_ref_counter::dec(block_address const &b) {
|
||||||
|
sm_->dec(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -31,6 +31,20 @@
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace persistent_data {
|
namespace persistent_data {
|
||||||
|
class block_ref_counter : public ref_counter<block_address> {
|
||||||
|
public:
|
||||||
|
block_ref_counter(space_map::ptr sm);
|
||||||
|
|
||||||
|
virtual void set(block_address const &v, uint32_t rc);
|
||||||
|
virtual void inc(block_address const &v);
|
||||||
|
virtual void dec(block_address const &v);
|
||||||
|
|
||||||
|
private:
|
||||||
|
space_map::ptr sm_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: move to sep file. I don't think it's directly used by
|
||||||
|
// the btree code.
|
||||||
struct uint64_traits {
|
struct uint64_traits {
|
||||||
typedef base::le64 disk_type;
|
typedef base::le64 disk_type;
|
||||||
typedef uint64_t value_type;
|
typedef uint64_t value_type;
|
||||||
@ -45,6 +59,20 @@ namespace persistent_data {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct block_traits {
|
||||||
|
typedef base::le64 disk_type;
|
||||||
|
typedef block_address value_type;
|
||||||
|
typedef block_ref_counter ref_counter;
|
||||||
|
|
||||||
|
static void unpack(disk_type const &disk, value_type &value) {
|
||||||
|
value = base::to_cpu<uint64_t>(disk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pack(value_type const &value, disk_type &disk) {
|
||||||
|
disk = base::to_disk<base::le64>(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
namespace btree_detail {
|
namespace btree_detail {
|
||||||
using namespace base;
|
using namespace base;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -243,11 +271,11 @@ namespace persistent_data {
|
|||||||
return spine_.size() > 1;
|
return spine_.size() > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_ref<uint64_traits> get_parent() {
|
node_ref<block_traits> get_parent() {
|
||||||
if (spine_.size() < 2)
|
if (spine_.size() < 2)
|
||||||
throw std::runtime_error("no parent");
|
throw std::runtime_error("no parent");
|
||||||
|
|
||||||
return to_node<uint64_traits>(spine_.front());
|
return to_node<block_traits>(spine_.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
block_address get_parent_location() const {
|
block_address get_parent_location() const {
|
||||||
@ -316,7 +344,7 @@ namespace persistent_data {
|
|||||||
typedef typename block_manager<>::read_ref read_ref;
|
typedef typename block_manager<>::read_ref read_ref;
|
||||||
typedef typename block_manager<>::write_ref write_ref;
|
typedef typename block_manager<>::write_ref write_ref;
|
||||||
typedef typename btree_detail::node_ref<ValueTraits> leaf_node;
|
typedef typename btree_detail::node_ref<ValueTraits> leaf_node;
|
||||||
typedef typename btree_detail::node_ref<uint64_traits> internal_node;
|
typedef typename btree_detail::node_ref<block_traits> internal_node;
|
||||||
|
|
||||||
btree(typename persistent_data::transaction_manager::ptr tm,
|
btree(typename persistent_data::transaction_manager::ptr tm,
|
||||||
typename ValueTraits::ref_counter rc);
|
typename ValueTraits::ref_counter rc);
|
||||||
@ -420,7 +448,7 @@ namespace persistent_data {
|
|||||||
typename persistent_data::transaction_manager::ptr tm_;
|
typename persistent_data::transaction_manager::ptr tm_;
|
||||||
bool destroy_;
|
bool destroy_;
|
||||||
block_address root_;
|
block_address root_;
|
||||||
no_op_ref_counter<uint64_t> internal_rc_;
|
block_ref_counter internal_rc_;
|
||||||
typename ValueTraits::ref_counter rc_;
|
typename ValueTraits::ref_counter rc_;
|
||||||
typename block_manager<>::validator::ptr validator_;
|
typename block_manager<>::validator::ptr validator_;
|
||||||
};
|
};
|
||||||
|
@ -60,6 +60,7 @@ namespace {
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace persistent_data {
|
namespace persistent_data {
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ro_spine::step(block_address b)
|
ro_spine::step(block_address b)
|
||||||
{
|
{
|
||||||
@ -356,7 +357,7 @@ namespace persistent_data {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//--------------------------------
|
||||||
|
|
||||||
template <unsigned Levels, typename ValueTraits>
|
template <unsigned Levels, typename ValueTraits>
|
||||||
btree<Levels, ValueTraits>::
|
btree<Levels, ValueTraits>::
|
||||||
@ -364,6 +365,7 @@ namespace persistent_data {
|
|||||||
typename ValueTraits::ref_counter rc)
|
typename ValueTraits::ref_counter rc)
|
||||||
: tm_(tm),
|
: tm_(tm),
|
||||||
destroy_(false),
|
destroy_(false),
|
||||||
|
internal_rc_(tm->get_sm()),
|
||||||
rc_(rc),
|
rc_(rc),
|
||||||
validator_(new btree_node_validator)
|
validator_(new btree_node_validator)
|
||||||
{
|
{
|
||||||
@ -388,6 +390,7 @@ namespace persistent_data {
|
|||||||
: tm_(tm),
|
: tm_(tm),
|
||||||
destroy_(false),
|
destroy_(false),
|
||||||
root_(root),
|
root_(root),
|
||||||
|
internal_rc_(tm->get_sm()),
|
||||||
rc_(rc),
|
rc_(rc),
|
||||||
validator_(new btree_node_validator)
|
validator_(new btree_node_validator)
|
||||||
{
|
{
|
||||||
@ -426,7 +429,7 @@ namespace persistent_data {
|
|||||||
|
|
||||||
for (unsigned level = 0; level < Levels - 1; ++level) {
|
for (unsigned level = 0; level < Levels - 1; ++level) {
|
||||||
optional<block_address> mroot =
|
optional<block_address> mroot =
|
||||||
lookup_raw<uint64_traits, lower_bound_search<uint64_traits> >(spine, root, key[level]);
|
lookup_raw<block_traits, lower_bound_search<block_traits> >(spine, root, key[level]);
|
||||||
if (!mroot)
|
if (!mroot)
|
||||||
return maybe_value();
|
return maybe_value();
|
||||||
|
|
||||||
@ -467,9 +470,9 @@ namespace persistent_data {
|
|||||||
shadow_spine spine(tm_, validator_);
|
shadow_spine spine(tm_, validator_);
|
||||||
|
|
||||||
for (unsigned level = 0; level < Levels - 1; ++level) {
|
for (unsigned level = 0; level < Levels - 1; ++level) {
|
||||||
bool need_insert = insert_location<uint64_traits>(spine, block, key[level], &index, internal_rc_);
|
bool need_insert = insert_location<block_traits>(spine, block, key[level], &index, internal_rc_);
|
||||||
|
|
||||||
internal_node n = spine.template get_node<uint64_traits>();
|
internal_node n = spine.template get_node<block_traits>();
|
||||||
if (need_insert) {
|
if (need_insert) {
|
||||||
btree<Levels - 1, ValueTraits> new_tree(tm_, rc_);
|
btree<Levels - 1, ValueTraits> new_tree(tm_, rc_);
|
||||||
n.insert_at(index, key[level], new_tree.get_root());
|
n.insert_at(index, key[level], new_tree.get_root());
|
||||||
@ -556,7 +559,7 @@ namespace persistent_data {
|
|||||||
if (!mi || *mi < 0)
|
if (!mi || *mi < 0)
|
||||||
return optional<leaf_type>();
|
return optional<leaf_type>();
|
||||||
|
|
||||||
node_ref<uint64_traits> internal = spine.template get_node<uint64_traits>();
|
node_ref<block_traits> internal = spine.template get_node<block_traits>();
|
||||||
block = internal.value_at(*mi);
|
block = internal.value_at(*mi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -623,11 +626,11 @@ namespace persistent_data {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// The parent may have changed value type, so we re-get it.
|
// The parent may have changed value type, so we re-get it.
|
||||||
internal_node p = spine.template get_node<uint64_traits>();
|
internal_node p = spine.template get_node<block_traits>();
|
||||||
p.set_type(btree_detail::INTERNAL);
|
p.set_type(btree_detail::INTERNAL);
|
||||||
p.set_max_entries();
|
p.set_max_entries();
|
||||||
p.set_nr_entries(2);
|
p.set_nr_entries(2);
|
||||||
p.set_value_size(sizeof(typename uint64_traits::disk_type));
|
p.set_value_size(sizeof(typename block_traits::disk_type));
|
||||||
|
|
||||||
p.overwrite_at(0, l.key_at(0), left.get_location());
|
p.overwrite_at(0, l.key_at(0), left.get_location());
|
||||||
p.overwrite_at(1, r.key_at(0), right.get_location());
|
p.overwrite_at(1, r.key_at(0), right.get_location());
|
||||||
@ -703,15 +706,15 @@ namespace persistent_data {
|
|||||||
p.set_value(i, spine.get_block());
|
p.set_value(i, spine.get_block());
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_node internal = spine.template get_node<uint64_traits>();
|
internal_node internal = spine.template get_node<block_traits>();
|
||||||
|
|
||||||
// Split the node if we're full
|
// Split the node if we're full
|
||||||
if (internal.get_type() == INTERNAL)
|
if (internal.get_type() == INTERNAL)
|
||||||
split_node<uint64_traits>(spine, i, key, top);
|
split_node<block_traits>(spine, i, key, top);
|
||||||
else
|
else
|
||||||
split_node<ValueTraits>(spine, i, key, top);
|
split_node<ValueTraits>(spine, i, key, top);
|
||||||
|
|
||||||
internal = spine.template get_node<uint64_traits>();
|
internal = spine.template get_node<block_traits>();
|
||||||
i = internal.lower_bound(key);
|
i = internal.lower_bound(key);
|
||||||
if (internal.get_type() == btree_detail::LEAF)
|
if (internal.get_type() == btree_detail::LEAF)
|
||||||
break;
|
break;
|
||||||
@ -780,7 +783,7 @@ namespace persistent_data {
|
|||||||
using namespace btree_detail;
|
using namespace btree_detail;
|
||||||
|
|
||||||
read_ref blk = tm_->read_lock(b, validator_);
|
read_ref blk = tm_->read_lock(b, validator_);
|
||||||
internal_node o = to_node<uint64_traits>(blk);
|
internal_node o = to_node<block_traits>(blk);
|
||||||
|
|
||||||
// FIXME: use a switch statement
|
// FIXME: use a switch statement
|
||||||
if (o.get_type() == INTERNAL) {
|
if (o.get_type() == INTERNAL) {
|
||||||
@ -817,7 +820,7 @@ namespace persistent_data {
|
|||||||
void
|
void
|
||||||
btree<Levels, _>::inc_children(btree_detail::shadow_spine &spine, RefCounter &leaf_rc)
|
btree<Levels, _>::inc_children(btree_detail::shadow_spine &spine, RefCounter &leaf_rc)
|
||||||
{
|
{
|
||||||
node_ref<uint64_traits> nr = spine.template get_node<uint64_traits>();
|
node_ref<block_traits> nr = spine.template get_node<block_traits>();
|
||||||
if (nr.get_type() == INTERNAL)
|
if (nr.get_type() == INTERNAL)
|
||||||
nr.inc_children(internal_rc_);
|
nr.inc_children(internal_rc_);
|
||||||
else {
|
else {
|
||||||
|
@ -66,12 +66,12 @@ namespace persistent_data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool visit_internal(node_location const &loc,
|
bool visit_internal(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
return check_internal(loc, n);
|
return check_internal(loc, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool visit_internal_leaf(node_location const &loc,
|
bool visit_internal_leaf(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
return check_leaf(loc, n);
|
return check_leaf(loc, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ namespace persistent_data {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool check_internal(node_location const &loc,
|
bool check_internal(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
if (!already_visited(n) &&
|
if (!already_visited(n) &&
|
||||||
check_block_nr(n) &&
|
check_block_nr(n) &&
|
||||||
check_max_entries(n) &&
|
check_max_entries(n) &&
|
||||||
|
@ -146,14 +146,14 @@ namespace persistent_data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool visit_internal(node_location const &loc,
|
bool visit_internal(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
update_path(loc.path);
|
update_path(loc.path);
|
||||||
|
|
||||||
return check_internal(loc, n);
|
return check_internal(loc, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool visit_internal_leaf(node_location const &loc,
|
bool visit_internal_leaf(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
update_path(loc.path);
|
update_path(loc.path);
|
||||||
|
|
||||||
return check_leaf(loc, n);
|
return check_leaf(loc, n);
|
||||||
@ -200,7 +200,7 @@ namespace persistent_data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool check_internal(node_location const &loc,
|
bool check_internal(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
if (!already_visited(n) &&
|
if (!already_visited(n) &&
|
||||||
check_block_nr(n) &&
|
check_block_nr(n) &&
|
||||||
check_max_entries(n) &&
|
check_max_entries(n) &&
|
||||||
|
@ -44,7 +44,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool visit_internal(node_location const &loc,
|
bool visit_internal(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
|
|
||||||
if (!checker_.visit_internal(loc, n)) {
|
if (!checker_.visit_internal(loc, n)) {
|
||||||
found_errors_ = true;
|
found_errors_ = true;
|
||||||
@ -55,7 +55,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool visit_internal_leaf(node_location const &loc,
|
bool visit_internal_leaf(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
if (!checker_.visit_internal_leaf(loc, n)) {
|
if (!checker_.visit_internal_leaf(loc, n)) {
|
||||||
found_errors_ = true;
|
found_errors_ = true;
|
||||||
return false;
|
return false;
|
||||||
@ -148,12 +148,12 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool visit_internal(node_location const &loc,
|
bool visit_internal(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
return checker_.visit_internal(loc, n);
|
return checker_.visit_internal(loc, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool visit_internal_leaf(node_location const &loc,
|
bool visit_internal_leaf(node_location const &loc,
|
||||||
btree_detail::node_ref<uint64_traits> const &n) {
|
btree_detail::node_ref<block_traits> const &n) {
|
||||||
return checker_.visit_internal_leaf(loc, n);
|
return checker_.visit_internal_leaf(loc, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ namespace {
|
|||||||
class constraint_visitor : public btree<1, uint64_traits>::visitor {
|
class constraint_visitor : public btree<1, uint64_traits>::visitor {
|
||||||
public:
|
public:
|
||||||
typedef btree_detail::node_location node_location;
|
typedef btree_detail::node_location node_location;
|
||||||
typedef btree_detail::node_ref<uint64_traits> internal_node;
|
typedef btree_detail::node_ref<block_traits> internal_node;
|
||||||
typedef btree_detail::node_ref<uint64_traits> leaf_node;
|
typedef btree_detail::node_ref<uint64_traits> leaf_node;
|
||||||
|
|
||||||
bool visit_internal(node_location const &loc,
|
bool visit_internal(node_location const &loc,
|
||||||
|
Loading…
Reference in New Issue
Block a user