Merge branch 'master' into space-map-checking

This commit is contained in:
Joe Thornber
2015-04-07 12:18:23 +01:00
168 changed files with 7851 additions and 2250 deletions

View File

@ -31,9 +31,9 @@ namespace persistent_data {
namespace array_detail {
uint32_t const ARRAY_CSUM_XOR = 595846735;
struct array_block_validator : public block_manager<>::validator {
virtual void check(buffer<> const &b, block_address location) const {
array_block_disk const *data = reinterpret_cast<array_block_disk const *>(&b);
struct array_block_validator : public bcache::validator {
virtual void check(void const *raw, block_address location) const {
array_block_disk const *data = reinterpret_cast<array_block_disk const *>(raw);
crc32c sum(ARRAY_CSUM_XOR);
sum.append(&data->max_entries, MD_BLOCK_SIZE - sizeof(uint32_t));
if (sum.get_sum() != to_cpu<uint32_t>(data->csum))
@ -43,8 +43,8 @@ namespace persistent_data {
throw checksum_error("bad block nr in array block");
}
virtual void prepare(buffer<> &b, block_address location) const {
array_block_disk *data = reinterpret_cast<array_block_disk *>(&b);
virtual void prepare(void *raw, block_address location) const {
array_block_disk *data = reinterpret_cast<array_block_disk *>(raw);
data->blocknr = to_disk<base::le64, uint64_t>(location);
crc32c sum(ARRAY_CSUM_XOR);
@ -172,7 +172,7 @@ namespace persistent_data {
unsigned visit_array_block(ValueVisitor &vv,
btree_path const &p,
typename block_traits::value_type const &v) const {
rblock rb(tm_->read_lock(v, validator_), rc_);
rblock rb(tm_.read_lock(v, validator_), rc_);
for (uint32_t i = 0; i < rb.nr_entries(); i++)
vv.visit(p[0] * rb.max_entries() + i, rb.get(i));
@ -207,8 +207,6 @@ namespace persistent_data {
unsigned entries_per_block_;
};
typedef typename persistent_data::transaction_manager::ptr tm_ptr;
typedef block_manager<>::write_ref write_ref;
typedef block_manager<>::read_ref read_ref;
@ -219,23 +217,23 @@ namespace persistent_data {
typedef typename ValueTraits::value_type value_type;
typedef typename ValueTraits::ref_counter ref_counter;
array(tm_ptr tm, ref_counter rc)
array(transaction_manager &tm, ref_counter rc)
: tm_(tm),
entries_per_block_(rblock::calc_max_entries()),
nr_entries_(0),
block_rc_(tm->get_sm(), *this),
block_rc_(tm.get_sm(), *this),
block_tree_(tm, block_rc_),
rc_(rc),
validator_(new array_detail::array_block_validator) {
}
array(tm_ptr tm, ref_counter rc,
array(transaction_manager &tm, ref_counter rc,
block_address root,
unsigned nr_entries)
: tm_(tm),
entries_per_block_(rblock::calc_max_entries()),
nr_entries_(nr_entries),
block_rc_(tm->get_sm(), *this),
block_rc_(tm.get_sm(), *this),
block_tree_(tm, root, block_rc_),
rc_(rc),
validator_(new array_detail::array_block_validator) {
@ -378,7 +376,7 @@ namespace persistent_data {
wblock new_ablock(unsigned ablock_index) {
uint64_t key[1] = {ablock_index};
write_ref b = tm_->new_block(validator_);
write_ref b = tm_.new_block(validator_);
block_address location = b.get_location();
wblock wb(b, rc_);
@ -389,13 +387,13 @@ namespace persistent_data {
rblock get_ablock(unsigned ablock_index) const {
block_address addr = lookup_block_address(ablock_index);
return rblock(tm_->read_lock(addr, validator_), rc_);
return rblock(tm_.read_lock(addr, validator_), rc_);
}
wblock shadow_ablock(unsigned ablock_index) {
uint64_t key[1] = {ablock_index};
block_address addr = lookup_block_address(ablock_index);
std::pair<write_ref, bool> p = tm_->shadow(addr, validator_);
std::pair<write_ref, bool> p = tm_.shadow(addr, validator_);
wblock wb = wblock(p.first, rc_);
if (p.second)
@ -407,17 +405,17 @@ namespace persistent_data {
}
void dec_ablock_entries(block_address addr) {
rblock b(tm_->read_lock(addr, validator_), rc_);
rblock b(tm_.read_lock(addr, validator_), rc_);
b.dec_all_entries();
}
tm_ptr tm_;
transaction_manager &tm_;
unsigned entries_per_block_;
unsigned nr_entries_;
block_ref_counter block_rc_;
btree<1, block_traits> block_tree_;
typename ValueTraits::ref_counter rc_;
block_manager<>::validator::ptr validator_;
bcache::validator::ptr validator_;
};
}

View File

@ -19,7 +19,7 @@
#ifndef ARRAY_BLOCK_H
#define ARRAY_BLOCK_H
#include "persistent-data/endian_utils.h"
#include "base/endian_utils.h"
//----------------------------------------------------------------
@ -163,11 +163,11 @@ namespace persistent_data {
}
array_block_disk *get_header() {
return reinterpret_cast<array_block_disk *>(ref_.data().raw());
return reinterpret_cast<array_block_disk *>(ref_.data());
}
array_block_disk const *get_header() const {
return reinterpret_cast<array_block_disk const *>(ref_.data().raw());
return reinterpret_cast<array_block_disk const *>(ref_.data());
}
disk_type &element_at(unsigned int index) {

View File

@ -2,7 +2,6 @@
#include "persistent-data/data-structures/bitset.h"
#include "persistent-data/math_utils.h"
using namespace boost;
using namespace persistent_data;
using namespace persistent_data::bitset_detail;
using namespace std;
@ -12,7 +11,7 @@ using namespace std;
namespace {
struct bitset_traits {
typedef base::le64 disk_type;
typedef uint64_t value_type;
typedef ::uint64_t value_type;
typedef no_op_ref_counter<uint64_t> ref_counter;
static void unpack(disk_type const &disk, value_type &value) {
@ -27,25 +26,31 @@ namespace {
namespace persistent_data {
namespace bitset_detail {
size_t BITS_PER_ULL = 64;
class bitset_impl {
public:
typedef boost::shared_ptr<bitset_impl> ptr;
typedef persistent_data::transaction_manager::ptr tm_ptr;
bitset_impl(tm_ptr tm)
bitset_impl(transaction_manager &tm)
: nr_bits_(0),
array_(tm, rc_) {
}
bitset_impl(tm_ptr tm, block_address root, unsigned nr_bits)
bitset_impl(transaction_manager &tm, block_address root, unsigned nr_bits)
: nr_bits_(nr_bits),
array_(tm, rc_, root, nr_bits) {
array_(tm, rc_, root, div_up<unsigned>(nr_bits, BITS_PER_ULL)) {
}
block_address get_root() const {
return array_.get_root();
}
unsigned get_nr_bits() const {
return nr_bits_;
}
void grow(unsigned new_nr_bits, bool default_value) {
pad_last_block(default_value);
resize_array(new_nr_bits, default_value);
@ -77,7 +82,7 @@ namespace persistent_data {
}
void walk_bitset(bitset_visitor &v) const {
bit_visitor vv(v);
bit_visitor vv(v, nr_bits_);
damage_visitor dv(v);
array_.visit_values(vv, dv);
}
@ -85,18 +90,20 @@ namespace persistent_data {
private:
class bit_visitor {
public:
bit_visitor(bitset_visitor &v)
: v_(v) {
bit_visitor(bitset_visitor &v, unsigned nr_bits)
: v_(v),
nr_bits_(nr_bits) {
}
void visit(uint32_t word_index, uint64_t word) {
uint32_t bit_index = word_index * 64;
for (unsigned bit = 0; bit < 64; bit++, bit_index++)
v_.visit(bit_index, !!(word & (1 << bit)));
for (unsigned bit = 0; bit < 64 && bit_index < nr_bits_; bit++, bit_index++)
v_.visit(bit_index, !!(word & (1ULL << bit)));
}
private:
bitset_visitor &v_;
unsigned nr_bits_;
};
class damage_visitor {
@ -112,11 +119,11 @@ namespace persistent_data {
}
private:
optional<uint32_t> lifted_mult64(optional<uint32_t> const &m) {
boost::optional<uint32_t> lifted_mult64(boost::optional<uint32_t> const &m) {
if (!m)
return m;
return optional<uint32_t>(*m * 64);
return boost::optional<uint32_t>(*m * 64);
}
bitset_visitor &v_;
@ -184,7 +191,7 @@ namespace persistent_data {
if (n >= nr_bits_) {
std::ostringstream str;
str << "bitset index out of bounds ("
<< n << " >= " << nr_bits_ << endl;
<< n << " >= " << nr_bits_ << ")";
throw runtime_error(str.str());
}
}
@ -198,12 +205,12 @@ namespace persistent_data {
//----------------------------------------------------------------
persistent_data::bitset::bitset(tm_ptr tm)
persistent_data::bitset::bitset(transaction_manager &tm)
: impl_(new bitset_impl(tm))
{
}
persistent_data::bitset::bitset(tm_ptr tm, block_address root, unsigned nr_bits)
persistent_data::bitset::bitset(transaction_manager &tm, block_address root, unsigned nr_bits)
: impl_(new bitset_impl(tm, root, nr_bits))
{
}
@ -214,6 +221,12 @@ persistent_data::bitset::get_root() const
return impl_->get_root();
}
unsigned
persistent_data::bitset::get_nr_bits() const
{
return impl_->get_nr_bits();
}
void
persistent_data::bitset::grow(unsigned new_nr_bits, bool default_value)
{

View File

@ -16,8 +16,8 @@
// with thin-provisioning-tools. If not, see
// <http://www.gnu.org/licenses/>.
#ifndef BITSET_H
#define BITSET_H
#ifndef PERSISTENT_DATA_DATA_STRUCTURES_BITSET_H
#define PERSISTENT_DATA_DATA_STRUCTURES_BITSET_H
#include "persistent-data/run.h"
@ -49,11 +49,12 @@ namespace persistent_data {
class bitset {
public:
typedef boost::shared_ptr<bitset> ptr;
typedef persistent_data::transaction_manager::ptr tm_ptr;
bitset(tm_ptr tm);
bitset(tm_ptr tm, block_address root, unsigned nr_bits);
bitset(transaction_manager &tm);
bitset(transaction_manager &tm,
block_address root, unsigned nr_bits);
block_address get_root() const;
unsigned get_nr_bits() const;
void grow(unsigned new_nr_bits, bool default_value);
void destroy();

View File

@ -0,0 +1,146 @@
#include "persistent-data/data-structures/bloom_filter.h"
#include <stdexcept>
using namespace persistent_data;
//----------------------------------------------------------------
namespace {
static const uint64_t m1 = 0x9e37fffffffc0001ULL;
static const unsigned bits = 18;
static uint32_t hash1(block_address const &b) {
return (b * m1) >> bits;
}
static uint32_t hash2(block_address const &b) {
uint32_t n = b;
n = n ^ (n >> 16);
n = n * 0x85ebca6bu;
n = n ^ (n >> 13);
n = n * 0xc2b2ae35u;
n = n ^ (n >> 16);
return n;
}
void check_power_of_two(unsigned nr_bits) {
if (nr_bits & (nr_bits - 1))
throw std::runtime_error("bloom filter needs a power of two nr_bits");
}
}
//----------------------------------------------------------------
bloom_filter::bloom_filter(transaction_manager &tm,
unsigned nr_bits, unsigned nr_probes)
: tm_(tm),
bits_(tm),
nr_probes_(nr_probes),
mask_(nr_bits - 1)
{
check_power_of_two(nr_bits);
bits_.grow(nr_bits, false);
}
bloom_filter::bloom_filter(transaction_manager &tm, block_address root,
unsigned nr_bits, unsigned nr_probes)
: tm_(tm),
bits_(tm, root, nr_bits),
nr_probes_(nr_probes),
mask_(nr_bits - 1)
{
check_power_of_two(nr_bits);
}
block_address
bloom_filter::get_root() const
{
return bits_.get_root();
}
bool
bloom_filter::test(uint64_t b)
{
vector<unsigned> probes(nr_probes_);
fill_probes(b, probes);
for (unsigned p = 0; p < nr_probes_; p++)
if (!bits_.get(probes[p]))
return false;
return true;
}
void
bloom_filter::set(uint64_t b)
{
vector<unsigned> probes(nr_probes_);
fill_probes(b, probes);
for (unsigned p = 0; p < nr_probes_; p++)
bits_.set(probes[p], true);
}
void
bloom_filter::flush()
{
bits_.flush();
}
void
bloom_filter::fill_probes(block_address b, vector<unsigned> &probes) const
{
uint32_t h1 = hash1(b) & mask_;
uint32_t h2 = hash2(b) & mask_;
probes[0] = h1;
for (unsigned p = 1; p < nr_probes_; p++) {
h1 = (h1 + h2) & mask_;
h2 = (h2 + p) & mask_;
probes[p] = h1;
}
}
void
bloom_filter::print_debug(ostream &out)
{
print_residency(out);
map<unsigned, unsigned> runs;
for (unsigned i = 0; i < bits_.get_nr_bits();) {
bool v = bits_.get(i);
unsigned run_length = 1;
while (++i < bits_.get_nr_bits() && bits_.get(i) == v)
run_length++;
map<unsigned, unsigned>::iterator it = runs.find(run_length);
if (it != runs.end())
it->second++;
else
runs.insert(make_pair(run_length, 1));
}
{
map<unsigned, unsigned>::const_iterator it;
for (it = runs.begin(); it != runs.end(); ++it)
out << it->first << ": " << it->second << endl;
}
}
void
bloom_filter::print_residency(ostream &out)
{
unsigned count = 0;
for (unsigned i = 0; i < bits_.get_nr_bits(); i++)
if (bits_.get(i))
count++;
out << "residency: " << count << "/" << bits_.get_nr_bits() << endl;
}
//----------------------------------------------------------------

View File

@ -0,0 +1,45 @@
#ifndef PERSISTENT_DATA_DATA_STRUCTURES_BLOOM_FILTER_H
#define PERSISTENT_DATA_DATA_STRUCTURES_BLOOM_FILTER_H
#include "persistent-data/transaction_manager.h"
#include "persistent-data/data-structures/bitset.h"
#include <boost/shared_ptr.hpp>
//----------------------------------------------------------------
namespace persistent_data {
class bloom_filter {
public:
typedef boost::shared_ptr<bloom_filter> ptr;
// nr_bits must be a power of two
bloom_filter(transaction_manager &tm,
unsigned nr_bits, unsigned nr_probes);
bloom_filter(transaction_manager &tm, block_address root,
unsigned nr_bits_power, unsigned nr_probes);
block_address get_root() const;
bool test(uint64_t b); // not const due to caching effects in bitset
void set(uint64_t b);
void flush();
void print_debug(ostream &out);
private:
void print_residency(ostream &out);
void fill_probes(block_address b, vector<unsigned> &probes) const;
transaction_manager &tm_;
persistent_data::bitset bits_;
unsigned nr_probes_;
uint64_t mask_;
};
}
//----------------------------------------------------------------
#endif

View File

@ -19,7 +19,7 @@
#ifndef BTREE_H
#define BTREE_H
#include "persistent-data/endian_utils.h"
#include "base/endian_utils.h"
#include "persistent-data/transaction_manager.h"
#include "persistent-data/data-structures/ref_counter.h"
@ -43,22 +43,6 @@ namespace persistent_data {
space_map::ptr sm_;
};
// FIXME: move to sep file. I don't think it's directly used by
// the btree code.
struct uint64_traits {
typedef base::le64 disk_type;
typedef uint64_t value_type;
typedef no_op_ref_counter<uint64_t> 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);
}
};
struct block_traits {
typedef base::le64 disk_type;
typedef block_address value_type;
@ -179,12 +163,15 @@ namespace persistent_data {
private:
static unsigned calc_max_entries(void);
void check_fits_within_block() const;
void *key_ptr(unsigned i) const;
void *value_ptr(unsigned i) const;
block_address location_;
disk_node *raw_;
mutable bool checked_; // flag indicating we've checked the data fits in the block
};
//------------------------------------------------
@ -197,7 +184,7 @@ namespace persistent_data {
return node_ref<ValueTraits>(
b.get_location(),
reinterpret_cast<disk_node *>(
const_cast<unsigned char *>(b.data().raw())));
const_cast<void *>(b.data())));
}
template <typename ValueTraits>
@ -206,14 +193,13 @@ namespace persistent_data {
{
return node_ref<ValueTraits>(
b.get_location(),
reinterpret_cast<disk_node *>(
const_cast<unsigned char *>(b.data().raw())));
reinterpret_cast<disk_node *>(b.data()));
}
class ro_spine : private boost::noncopyable {
public:
ro_spine(transaction_manager::ptr tm,
block_manager<>::validator::ptr v)
ro_spine(transaction_manager &tm,
bcache::validator::ptr v)
: tm_(tm),
validator_(v) {
}
@ -226,8 +212,8 @@ namespace persistent_data {
}
private:
transaction_manager::ptr tm_;
block_manager<>::validator::ptr validator_;
transaction_manager &tm_;
bcache::validator::ptr validator_;
std::list<block_manager<>::read_ref> spine_;
};
@ -237,8 +223,8 @@ namespace persistent_data {
typedef transaction_manager::write_ref write_ref;
typedef boost::optional<block_address> maybe_block;
shadow_spine(transaction_manager::ptr tm,
block_manager<>::validator::ptr v)
shadow_spine(transaction_manager &tm,
bcache::validator::ptr v)
: tm_(tm),
validator_(v) {
@ -290,8 +276,8 @@ namespace persistent_data {
}
private:
transaction_manager::ptr tm_;
block_manager<>::validator::ptr validator_;
transaction_manager &tm_;
bcache::validator::ptr validator_;
std::list<block_manager<>::write_ref> spine_;
maybe_block root_;
};
@ -349,10 +335,10 @@ namespace persistent_data {
typedef typename btree_detail::node_ref<ValueTraits> leaf_node;
typedef typename btree_detail::node_ref<block_traits> internal_node;
btree(typename persistent_data::transaction_manager::ptr tm,
btree(transaction_manager &tm,
typename ValueTraits::ref_counter rc);
btree(typename transaction_manager::ptr tm,
btree(transaction_manager &tm,
block_address root,
typename ValueTraits::ref_counter rc);
@ -448,12 +434,12 @@ namespace persistent_data {
void inc_children(btree_detail::shadow_spine &spine,
RefCounter &leaf_rc);
typename persistent_data::transaction_manager::ptr tm_;
transaction_manager &tm_;
bool destroy_;
block_address root_;
block_ref_counter internal_rc_;
typename ValueTraits::ref_counter rc_;
typename block_manager<>::validator::ptr validator_;
typename bcache::validator::ptr validator_;
};
};

View File

@ -32,9 +32,9 @@ namespace {
using namespace btree_detail;
using namespace std;
struct btree_node_validator : public block_manager<>::validator {
virtual void check(buffer<> const &b, block_address location) const {
disk_node const *data = reinterpret_cast<disk_node const *>(&b);
struct btree_node_validator : public bcache::validator {
virtual void check(void const *raw, block_address location) const {
disk_node const *data = reinterpret_cast<disk_node const *>(raw);
node_header const *n = &data->header;
crc32c sum(BTREE_CSUM_XOR);
sum.append(&n->flags, MD_BLOCK_SIZE - sizeof(uint32_t));
@ -45,8 +45,8 @@ namespace {
throw checksum_error("bad block nr in btree node");
}
virtual void prepare(buffer<> &b, block_address location) const {
disk_node *data = reinterpret_cast<disk_node *>(&b);
virtual void prepare(void *raw, block_address location) const {
disk_node *data = reinterpret_cast<disk_node *>(raw);
node_header *n = &data->header;
n->blocknr = to_disk<base::le64, uint64_t>(location);
@ -64,7 +64,7 @@ namespace persistent_data {
inline void
ro_spine::step(block_address b)
{
spine_.push_back(tm_->read_lock(b, validator_));
spine_.push_back(tm_.read_lock(b, validator_));
if (spine_.size() > 2)
spine_.pop_front();
}
@ -72,11 +72,11 @@ namespace persistent_data {
inline bool
shadow_spine::step(block_address b)
{
pair<write_ref, bool> p = tm_->shadow(b, validator_);
pair<write_ref, bool> p = tm_.shadow(b, validator_);
try {
step(p.first);
} catch (...) {
tm_->get_sm()->dec(p.first.get_location());
tm_.get_sm()->dec(p.first.get_location());
throw;
}
return p.second;
@ -87,7 +87,8 @@ namespace persistent_data {
template <typename ValueTraits>
node_ref<ValueTraits>::node_ref(block_address location, disk_node *raw)
: location_(location),
raw_(raw)
raw_(raw),
checked_(false)
{
}
@ -330,6 +331,8 @@ namespace persistent_data {
void *
node_ref<ValueTraits>::key_ptr(unsigned i) const
{
check_fits_within_block();
return raw_->keys + i;
}
@ -337,6 +340,8 @@ namespace persistent_data {
void *
node_ref<ValueTraits>::value_ptr(unsigned i) const
{
check_fits_within_block();
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;
@ -357,40 +362,75 @@ namespace persistent_data {
}
}
template <typename ValueTraits>
void
node_ref<ValueTraits>::check_fits_within_block() const {
if (checked_)
return;
if (sizeof(typename ValueTraits::disk_type) != get_value_size()) {
std::ostringstream out;
out << "value size mismatch: expected " << sizeof(typename ValueTraits::disk_type)
<< ", but got " << get_value_size()
<< ". This is not the btree you are looking for." << std::endl;
throw std::runtime_error(out.str());
}
unsigned max = calc_max_entries();
if (max < get_nr_entries()) {
std::ostringstream out;
out << "Bad nr of elements: max per block = "
<< max << ", actual = " << get_nr_entries() << std::endl;
throw std::runtime_error(out.str());
}
checked_ = true;
}
//--------------------------------
template <unsigned Levels, typename ValueTraits>
btree<Levels, ValueTraits>::
btree(typename transaction_manager::ptr tm,
btree(transaction_manager &tm,
typename ValueTraits::ref_counter rc)
: tm_(tm),
destroy_(false),
internal_rc_(tm->get_sm()),
internal_rc_(tm.get_sm()),
rc_(rc),
validator_(new btree_node_validator)
{
using namespace btree_detail;
write_ref root = tm_->new_block(validator_);
write_ref root = tm_.new_block(validator_);
leaf_node n = to_node<ValueTraits>(root);
n.set_type(btree_detail::LEAF);
n.set_nr_entries(0);
n.set_max_entries();
n.set_value_size(sizeof(typename ValueTraits::disk_type));
if (Levels > 1) {
internal_node n = to_node<block_traits>(root);
n.set_type(btree_detail::LEAF);
n.set_nr_entries(0);
n.set_max_entries();
n.set_value_size(sizeof(typename block_traits::disk_type));
} else {
leaf_node n = to_node<ValueTraits>(root);
n.set_type(btree_detail::LEAF);
n.set_nr_entries(0);
n.set_max_entries();
n.set_value_size(sizeof(typename ValueTraits::disk_type));
}
root_ = root.get_location();
}
template <unsigned Levels, typename ValueTraits>
btree<Levels, ValueTraits>::
btree(typename transaction_manager::ptr tm,
btree(transaction_manager &tm,
block_address root,
typename ValueTraits::ref_counter rc)
: tm_(tm),
destroy_(false),
root_(root),
internal_rc_(tm->get_sm()),
internal_rc_(tm.get_sm()),
rc_(rc),
validator_(new btree_node_validator)
{
@ -519,7 +559,7 @@ namespace persistent_data {
typename btree<Levels, ValueTraits>::ptr
btree<Levels, ValueTraits>::clone() const
{
tm_->get_sm()->inc(root_);
tm_.get_sm()->inc(root_);
return ptr(new btree<Levels, ValueTraits>(tm_, root_, rc_));
}
@ -595,13 +635,13 @@ namespace persistent_data {
node_type type;
unsigned nr_left, nr_right;
write_ref left = tm_->new_block(validator_);
write_ref left = tm_.new_block(validator_);
node_ref<ValueTraits> l = to_node<ValueTraits>(left);
l.set_nr_entries(0);
l.set_max_entries();
l.set_value_size(sizeof(typename ValueTraits::disk_type));
write_ref right = tm_->new_block(validator_);
write_ref right = tm_.new_block(validator_);
node_ref<ValueTraits> r = to_node<ValueTraits>(right);
r.set_nr_entries(0);
r.set_max_entries();
@ -655,7 +695,7 @@ namespace persistent_data {
node_ref<ValueTraits> l = spine.template get_node<ValueTraits>();
block_address left = spine.get_block();
write_ref right = tm_->new_block(validator_);
write_ref right = tm_.new_block(validator_);
node_ref<ValueTraits> r = to_node<ValueTraits>(right);
unsigned nr_left = l.get_nr_entries() / 2;
@ -782,12 +822,15 @@ namespace persistent_data {
{
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<block_traits>(blk);
// FIXME: use a switch statement
if (o.get_type() == INTERNAL) {
if (v.visit_internal(loc, o))
if (v.visit_internal(loc, o)) {
for (unsigned i = 0; i < o.get_nr_entries(); i++)
tm_.prefetch(o.value_at(i));
for (unsigned i = 0; i < o.get_nr_entries(); i++) {
node_location loc2(loc);
@ -796,6 +839,7 @@ namespace persistent_data {
walk_tree(v, loc2, o.value_at(i));
}
}
} else if (loc.path.size() < Levels - 1) {
if (v.visit_internal_leaf(loc, o))

View File

@ -85,23 +85,31 @@ namespace persistent_data {
// different sub tree (by looking at the btree_path).
class path_tracker {
public:
path_tracker() {
// We push an empty path, to ensure there
// is always a current_path.
paths_.push_back(btree_path());
}
// returns the old path if the tree has changed.
boost::optional<btree_path> next_path(btree_path const &p) {
if (p != path_) {
btree_path tmp(path_);
path_ = p;
return boost::optional<btree_path>(tmp);
btree_path const *next_path(btree_path const &p) {
if (p != current_path()) {
if (paths_.size() == 2)
paths_.pop_front();
paths_.push_back(p);
return &paths_.front();
}
return boost::optional<btree_path>();
return NULL;
}
btree_path const &current_path() const {
return path_;
return paths_.back();
}
private:
btree_path path_;
std::list<btree_path> paths_;
};
//----------------------------------------------------------------
@ -189,11 +197,12 @@ namespace persistent_data {
private:
void visit_values(btree_path const &path,
node_ref<ValueTraits> const &n) {
btree_path p2(path);
unsigned nr = n.get_nr_entries();
for (unsigned i = 0; i < nr; i++) {
btree_path p2(path);
p2.push_back(n.key_at(i));
value_visitor_.visit(p2, n.value_at(i));
p2.pop_back();
}
}
@ -427,7 +436,7 @@ namespace persistent_data {
}
void update_path(btree_path const &path) {
boost::optional<btree_path> old_path = path_tracker_.next_path(path);
btree_path const *old_path = path_tracker_.next_path(path);
if (old_path)
// we need to emit any errors that
// were accrued against the old

View File

@ -0,0 +1,38 @@
#ifndef PERSISTENT_DATA_DATA_STRUCTURES_SIMPLE_TRAITS_H
#define PERSISTENT_DATA_DATA_STRUCTURES_SIMPLE_TRAITS_H
//----------------------------------------------------------------
namespace persistent_data {
struct uint64_traits {
typedef base::le64 disk_type;
typedef uint64_t value_type;
typedef no_op_ref_counter<uint64_t> 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);
}
};
struct uint32_traits {
typedef base::le32 disk_type;
typedef uint32_t value_type;
typedef no_op_ref_counter<uint32_t> ref_counter;
static void unpack(disk_type const &disk, value_type &value) {
value = base::to_cpu<uint32_t>(disk);
}
static void pack(value_type const &value, disk_type &disk) {
disk = base::to_disk<base::le32>(value);
}
};
}
//----------------------------------------------------------------
#endif