Having the block size as a template parameter makes all the code very

verbose, and we're not likely to change it.  So this change removes
that template arg from everything except the block manager.
This commit is contained in:
Joe Thornber
2011-08-31 12:48:41 +01:00
parent a285fee757
commit 9cfdbfb8cc
15 changed files with 799 additions and 807 deletions

249
btree.tcc
View File

@@ -9,23 +9,23 @@ using namespace std;
//----------------------------------------------------------------
template <typename ValueTraits, uint32_t BlockSize>
node_ref<ValueTraits, BlockSize>::node_ref(block_address location, disk_node *raw)
template <typename ValueTraits>
node_ref<ValueTraits>::node_ref(block_address location, disk_node *raw)
: location_(location),
raw_(raw)
{
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
block_address
node_ref<ValueTraits, BlockSize>::get_block_nr() const
node_ref<ValueTraits>::get_block_nr() const
{
return to_cpu<uint64_t>(raw_->header.blocknr);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
btree_detail::node_type
node_ref<ValueTraits, BlockSize>::get_type() const
node_ref<ValueTraits>::get_type() const
{
uint32_t flags = to_cpu<uint32_t>(raw_->header.flags);
if (flags & INTERNAL_NODE)
@@ -36,9 +36,9 @@ node_ref<ValueTraits, BlockSize>::get_type() const
throw runtime_error("unknow node type");
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void
node_ref<ValueTraits, BlockSize>::set_type(node_type t)
node_ref<ValueTraits>::set_type(node_type t)
{
uint32_t flags = to_cpu<uint32_t>(raw_->header.flags);
switch (t) {
@@ -53,67 +53,67 @@ node_ref<ValueTraits, BlockSize>::set_type(node_type t)
raw_->header.flags = to_disk<__le32>(flags);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
unsigned
node_ref<ValueTraits, BlockSize>::get_nr_entries() const
node_ref<ValueTraits>::get_nr_entries() const
{
return to_cpu<uint32_t>(raw_->header.nr_entries);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void
node_ref<ValueTraits, BlockSize>::set_nr_entries(unsigned n)
node_ref<ValueTraits>::set_nr_entries(unsigned n)
{
raw_->header.nr_entries = to_disk<__le32>(n);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
unsigned
node_ref<ValueTraits, BlockSize>::get_max_entries() const
node_ref<ValueTraits>::get_max_entries() const
{
return to_cpu<uint32_t>(raw_->header.max_entries);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void
node_ref<ValueTraits, BlockSize>::set_max_entries(unsigned n)
node_ref<ValueTraits>::set_max_entries(unsigned n)
{
raw_->header.max_entries = to_disk<__le32>(n);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void
node_ref<ValueTraits, BlockSize>::set_max_entries()
node_ref<ValueTraits>::set_max_entries()
{
set_max_entries(calc_max_entries());
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
size_t
node_ref<ValueTraits, BlockSize>::get_value_size() const
node_ref<ValueTraits>::get_value_size() const
{
return to_cpu<uint32_t>(raw_->header.value_size);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
uint64_t
node_ref<ValueTraits, BlockSize>::key_at(unsigned i) const
node_ref<ValueTraits>::key_at(unsigned i) const
{
if (i >= get_nr_entries())
throw runtime_error("key index out of bounds");
return to_cpu<uint64_t>(raw_->keys[i]);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void
node_ref<ValueTraits, BlockSize>::set_key(unsigned i, uint64_t k)
node_ref<ValueTraits>::set_key(unsigned i, uint64_t k)
{
raw_->keys[i] = to_disk<__le64>(k);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
typename ValueTraits::value_type
node_ref<ValueTraits, BlockSize>::value_at(unsigned i) const
node_ref<ValueTraits>::value_at(unsigned i) const
{
if (i >= get_nr_entries())
throw runtime_error("value index out of bounds");
@@ -127,21 +127,21 @@ node_ref<ValueTraits, BlockSize>::value_at(unsigned i) const
return v;
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void
node_ref<ValueTraits, BlockSize>::set_value(unsigned i,
typename ValueTraits::value_type const &v)
node_ref<ValueTraits>::set_value(unsigned i,
typename ValueTraits::value_type const &v)
{
typename ValueTraits::disk_type d;
ValueTraits::pack(v, d);
::memcpy(value_ptr(i), &d, sizeof(d));
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void
node_ref<ValueTraits, BlockSize>::insert_at(unsigned i,
uint64_t key,
typename ValueTraits::value_type const &v)
node_ref<ValueTraits>::insert_at(unsigned i,
uint64_t key,
typename ValueTraits::value_type const &v)
{
unsigned n = get_nr_entries();
if ((n + 1) > get_max_entries())
@@ -153,21 +153,21 @@ node_ref<ValueTraits, BlockSize>::insert_at(unsigned i,
overwrite_at(i, key, v);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void
node_ref<ValueTraits, BlockSize>::overwrite_at(unsigned i,
uint64_t key,
typename ValueTraits::value_type const &v)
node_ref<ValueTraits>::overwrite_at(unsigned i,
uint64_t key,
typename ValueTraits::value_type const &v)
{
set_key(i, key);
set_value(i, v);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void
node_ref<ValueTraits, BlockSize>::copy_entries(node_ref const &rhs,
unsigned begin,
unsigned end)
node_ref<ValueTraits>::copy_entries(node_ref const &rhs,
unsigned begin,
unsigned end)
{
unsigned count = end - begin;
unsigned n = get_nr_entries();
@@ -179,10 +179,9 @@ node_ref<ValueTraits, BlockSize>::copy_entries(node_ref const &rhs,
::memcpy(value_ptr(n), rhs.value_ptr(begin), sizeof(typename ValueTraits::disk_type) * count);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
int
node_ref<ValueTraits, BlockSize>::bsearch(uint64_t key,
int want_hi) const
node_ref<ValueTraits>::bsearch(uint64_t key, int want_hi) const
{
int lo = -1, hi = get_nr_entries();
@@ -202,9 +201,9 @@ node_ref<ValueTraits, BlockSize>::bsearch(uint64_t key,
return want_hi ? hi : lo;
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
optional<unsigned>
node_ref<ValueTraits, BlockSize>::exact_search(uint64_t key) const
node_ref<ValueTraits>::exact_search(uint64_t key) const
{
int i = bsearch(key, 0);
if (i < 0 || static_cast<unsigned>(i) >= get_nr_entries())
@@ -213,45 +212,45 @@ node_ref<ValueTraits, BlockSize>::exact_search(uint64_t key) const
return optional<unsigned>(i);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
int
node_ref<ValueTraits, BlockSize>::lower_bound(uint64_t key) const
node_ref<ValueTraits>::lower_bound(uint64_t key) const
{
return bsearch(key, 0);
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
unsigned
node_ref<ValueTraits, BlockSize>::calc_max_entries(void)
node_ref<ValueTraits>::calc_max_entries(void)
{
uint32_t total;
// key + value
size_t elt_size = sizeof(uint64_t) + sizeof(typename ValueTraits::disk_type);
total = (BlockSize - sizeof(struct node_header)) / elt_size;
total = (MD_BLOCK_SIZE - sizeof(struct node_header)) / elt_size;
return (total / 3) * 3; // rounds down
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void *
node_ref<ValueTraits, BlockSize>::key_ptr(unsigned i) const
node_ref<ValueTraits>::key_ptr(unsigned i) const
{
return raw_->keys + i;
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
void *
node_ref<ValueTraits, BlockSize>::value_ptr(unsigned i) const
node_ref<ValueTraits>::value_ptr(unsigned i) const
{
void *value_base = &raw_->keys[to_cpu<uint32_t>(raw_->header.max_entries)];
return static_cast<unsigned char *>(value_base) +
sizeof(typename ValueTraits::disk_type) * i;
}
template <typename ValueTraits, uint32_t BlockSize>
template <typename ValueTraits>
template <typename RefCounter>
void
node_ref<ValueTraits, BlockSize>::inc_children(RefCounter &rc)
node_ref<ValueTraits>::inc_children(RefCounter &rc)
{
unsigned nr_entries = get_nr_entries();
for (unsigned i = 0; i < nr_entries; i++) {
@@ -265,9 +264,9 @@ node_ref<ValueTraits, BlockSize>::inc_children(RefCounter &rc)
//----------------------------------------------------------------
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
btree<Levels, ValueTraits, BlockSize>::
btree(typename transaction_manager<BlockSize>::ptr tm,
template <unsigned Levels, typename ValueTraits>
btree<Levels, ValueTraits>::
btree(typename transaction_manager::ptr tm,
typename ValueTraits::ref_counter rc)
: tm_(tm),
destroy_(false),
@@ -277,7 +276,7 @@ btree(typename transaction_manager<BlockSize>::ptr tm,
write_ref root = tm_->new_block();
leaf_node n = to_node<ValueTraits, BlockSize>(root);
leaf_node n = to_node<ValueTraits>(root);
n.set_type(btree_detail::LEAF);
n.set_nr_entries(0);
n.set_max_entries();
@@ -285,9 +284,9 @@ btree(typename transaction_manager<BlockSize>::ptr tm,
root_ = root.get_location();
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
btree<Levels, ValueTraits, BlockSize>::
btree(typename transaction_manager<BlockSize>::ptr tm,
template <unsigned Levels, typename ValueTraits>
btree<Levels, ValueTraits>::
btree(typename transaction_manager::ptr tm,
block_address root,
typename ValueTraits::ref_counter rc)
: tm_(tm),
@@ -297,54 +296,54 @@ btree(typename transaction_manager<BlockSize>::ptr tm,
{
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
btree<Levels, ValueTraits, BlockSize>::~btree()
template <unsigned Levels, typename ValueTraits>
btree<Levels, ValueTraits>::~btree()
{
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
typename btree<Levels, ValueTraits, BlockSize>::maybe_value
btree<Levels, ValueTraits, BlockSize>::lookup(key const &key) const
template <unsigned Levels, typename ValueTraits>
typename btree<Levels, ValueTraits>::maybe_value
btree<Levels, ValueTraits>::lookup(key const &key) const
{
using namespace btree_detail;
ro_spine<BlockSize> spine(tm_);
ro_spine spine(tm_);
block_address root = root_;
for (unsigned level = 0; level < Levels - 1; ++level) {
optional<block_address> mroot =
lookup_raw<uint64_traits, BlockSize>(spine, root, key[level]);
lookup_raw<uint64_traits>(spine, root, key[level]);
if (!mroot)
return maybe_value();
root = *mroot;
}
return lookup_raw<ValueTraits, BlockSize>(spine, root, key[Levels - 1]);
return lookup_raw<ValueTraits>(spine, root, key[Levels - 1]);
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
typename btree<Levels, ValueTraits, BlockSize>::maybe_pair
btree<Levels, ValueTraits, BlockSize>::lookup_le(key const &key) const
template <unsigned Levels, typename ValueTraits>
typename btree<Levels, ValueTraits>::maybe_pair
btree<Levels, ValueTraits>::lookup_le(key const &key) const
{
using namespace btree_detail;
return maybe_pair();
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
typename btree<Levels, ValueTraits, BlockSize>::maybe_pair
btree<Levels, ValueTraits, BlockSize>::lookup_ge(key const &key) const
template <unsigned Levels, typename ValueTraits>
typename btree<Levels, ValueTraits>::maybe_pair
btree<Levels, ValueTraits>::lookup_ge(key const &key) const
{
using namespace btree_detail;
return maybe_pair();
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
template <unsigned Levels, typename ValueTraits>
void
btree<Levels, ValueTraits, BlockSize>::
btree<Levels, ValueTraits>::
insert(key const &key,
typename ValueTraits::value_type const &value)
{
@@ -352,14 +351,14 @@ insert(key const &key,
block_address block = root_;
int index = 0; // FIXME: ???
shadow_spine<BlockSize> spine(tm_);
shadow_spine spine(tm_);
for (unsigned level = 0; level < Levels - 1; ++level) {
bool need_insert = insert_location<uint64_traits>(spine, block, key[level], &index);
internal_node n = spine.template get_node<uint64_traits>();
if (need_insert) {
btree<Levels - 1, ValueTraits, BlockSize> new_tree(tm_, rc_);
btree<Levels - 1, ValueTraits> new_tree(tm_, rc_);
n.insert_at(index, key[level], new_tree.get_root());
}
@@ -376,78 +375,78 @@ insert(key const &key,
n.set_value(index, value);
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
template <unsigned Levels, typename ValueTraits>
void
btree<Levels, ValueTraits, BlockSize>::remove(key const &key)
btree<Levels, ValueTraits>::remove(key const &key)
{
using namespace btree_detail;
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
template <unsigned Levels, typename ValueTraits>
block_address
btree<Levels, ValueTraits, BlockSize>::get_root() const
btree<Levels, ValueTraits>::get_root() const
{
return root_;
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
template <unsigned Levels, typename ValueTraits>
void
btree<Levels, ValueTraits, BlockSize>::set_root(block_address root)
btree<Levels, ValueTraits>::set_root(block_address root)
{
using namespace btree_detail;
root_ = root;
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
typename btree<Levels, ValueTraits, BlockSize>::ptr
btree<Levels, ValueTraits, BlockSize>::clone() const
template <unsigned Levels, typename ValueTraits>
typename btree<Levels, ValueTraits>::ptr
btree<Levels, ValueTraits>::clone() const
{
using namespace btree_detail;
ro_spine<BlockSize> spine(tm_);
ro_spine spine(tm_);
spine.step(root_);
write_ref new_root = tm_->new_block();
internal_node o = spine.template get_node<uint64_traits>();
if (o.get_type() == INTERNAL) {
internal_node n = to_node<uint64_traits, BlockSize>(new_root);
::memcpy(n.raw(), o.raw(), BlockSize);
internal_node n = to_node<uint64_traits>(new_root);
::memcpy(n.raw(), o.raw(), MD_BLOCK_SIZE);
typename uint64_traits::ref_counter rc(internal_rc_);
n.inc_children(rc);
} else {
leaf_node n = to_node<ValueTraits, BlockSize>(new_root);
::memcpy(n.raw(), o.raw(), BlockSize);
leaf_node n = to_node<ValueTraits>(new_root);
::memcpy(n.raw(), o.raw(), MD_BLOCK_SIZE);
typename ValueTraits::ref_counter rc(rc_);
n.inc_children(rc);
}
return btree<Levels, ValueTraits, BlockSize>::ptr(
new btree<Levels, ValueTraits, BlockSize>(
return btree<Levels, ValueTraits>::ptr(
new btree<Levels, ValueTraits>(
tm_, new_root.get_location(), rc_));
}
#if 0
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
template <unsigned Levels, typename ValueTraits>
void
btree<Levels, ValueTraits, BlockSize>::destroy()
btree<Levels, ValueTraits>::destroy()
{
using namespace btree_detail;
}
#endif
template <unsigned Levels, typename _, uint32_t BlockSize>
template <unsigned Levels, typename _>
template <typename ValueTraits>
void
btree<Levels, _, BlockSize>::
split_node(btree_detail::shadow_spine<BlockSize> &spine,
btree<Levels, _>::
split_node(btree_detail::shadow_spine &spine,
block_address parent_index,
uint64_t key,
bool top)
{
node_ref<ValueTraits, BlockSize> n = spine.template get_node<ValueTraits>();
node_ref<ValueTraits> n = spine.template get_node<ValueTraits>();
if (n.get_nr_entries() == n.get_max_entries()) {
if (top)
split_beneath<ValueTraits>(spine, key);
@@ -456,11 +455,11 @@ split_node(btree_detail::shadow_spine<BlockSize> &spine,
}
}
template <unsigned Levels, typename _, uint32_t BlockSize>
template <unsigned Levels, typename _>
template <typename ValueTraits>
void
btree<Levels, _, BlockSize>::
split_beneath(btree_detail::shadow_spine<BlockSize> &spine,
btree<Levels, _>::
split_beneath(btree_detail::shadow_spine &spine,
uint64_t key)
{
using namespace btree_detail;
@@ -469,17 +468,17 @@ split_beneath(btree_detail::shadow_spine<BlockSize> &spine,
unsigned nr_left, nr_right;
write_ref left = tm_->new_block();
node_ref<ValueTraits, BlockSize> l = to_node<ValueTraits, BlockSize>(left);
node_ref<ValueTraits> l = to_node<ValueTraits>(left);
l.set_nr_entries(0);
l.set_max_entries();
write_ref right = tm_->new_block();
node_ref<ValueTraits, BlockSize> r = to_node<ValueTraits, BlockSize>(right);
node_ref<ValueTraits> r = to_node<ValueTraits>(right);
r.set_nr_entries(0);
r.set_max_entries();
{
node_ref<ValueTraits, BlockSize> p = spine.template get_node<ValueTraits>();
node_ref<ValueTraits> p = spine.template get_node<ValueTraits>();
nr_left = p.get_nr_entries() / 2;
nr_right = p.get_nr_entries() - nr_left;
type = p.get_type();
@@ -508,21 +507,21 @@ split_beneath(btree_detail::shadow_spine<BlockSize> &spine,
spine.step(right);
}
template <unsigned Levels, typename _, uint32_t BlockSize>
template <unsigned Levels, typename _>
template <typename ValueTraits>
void
btree<Levels, _, BlockSize>::
split_sibling(btree_detail::shadow_spine<BlockSize> &spine,
btree<Levels, _>::
split_sibling(btree_detail::shadow_spine &spine,
block_address parent_index,
uint64_t key)
{
using namespace btree_detail;
node_ref<ValueTraits, BlockSize> l = spine.template get_node<ValueTraits>();
node_ref<ValueTraits> l = spine.template get_node<ValueTraits>();
block_address left = spine.get_block();
write_ref right = tm_->new_block();
node_ref<ValueTraits, BlockSize> r = to_node<ValueTraits, BlockSize>(right);
node_ref<ValueTraits> r = to_node<ValueTraits>(right);
unsigned nr_left = l.get_nr_entries() / 2;
unsigned nr_right = l.get_nr_entries() - nr_left;
@@ -545,11 +544,11 @@ split_sibling(btree_detail::shadow_spine<BlockSize> &spine,
}
// Returns true if we need a new insertion, rather than overwrite.
template <unsigned Levels, typename _, uint32_t BlockSize>
template <unsigned Levels, typename _>
template <typename ValueTraits>
bool
btree<Levels, _, BlockSize>::
insert_location(btree_detail::shadow_spine<BlockSize> &spine,
btree<Levels, _>::
insert_location(btree_detail::shadow_spine &spine,
block_address block,
uint64_t key,
int *index)
@@ -595,7 +594,7 @@ insert_location(btree_detail::shadow_spine<BlockSize> &spine,
top = false;
}
node_ref<ValueTraits, BlockSize> leaf = spine.template get_node<ValueTraits>();
node_ref<ValueTraits> leaf = spine.template get_node<ValueTraits>();
// FIXME: gross
if (i < 0 || leaf.key_at(i) != key)
i++;
@@ -611,16 +610,16 @@ insert_location(btree_detail::shadow_spine<BlockSize> &spine,
(leaf.key_at(i) != key));
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
template <unsigned Levels, typename ValueTraits>
void
btree<Levels, ValueTraits, BlockSize>::visit(typename visitor::ptr visitor) const
btree<Levels, ValueTraits>::visit(typename visitor::ptr visitor) const
{
walk_tree(visitor, 0, true, root_);
}
template <unsigned Levels, typename ValueTraits, uint32_t BlockSize>
template <unsigned Levels, typename ValueTraits>
void
btree<Levels, ValueTraits, BlockSize>::
btree<Levels, ValueTraits>::
walk_tree(typename visitor::ptr visitor,
unsigned level, bool is_root,
block_address b) const
@@ -628,7 +627,7 @@ walk_tree(typename visitor::ptr visitor,
using namespace btree_detail;
read_ref blk = tm_->read_lock(b);
internal_node o = to_node<uint64_traits, BlockSize>(blk);
internal_node o = to_node<uint64_traits>(blk);
if (o.get_type() == INTERNAL) {
if (visitor->visit_internal(level, is_root, o))
for (unsigned i = 0; i < o.get_nr_entries(); i++)
@@ -640,7 +639,7 @@ walk_tree(typename visitor::ptr visitor,
walk_tree(visitor, level + 1, true, o.value_at(i));
} else {
leaf_node ov = to_node<ValueTraits, BlockSize>(blk);
leaf_node ov = to_node<ValueTraits>(blk);
visitor->visit_leaf(level, is_root, ov);
}
}