[everything] Fix circular shared pointer references.

We had a cycle from transaction_manager <-> space_map, and also from
the ref_counters back up to the tm.

This prevented objects being destroyed when various programs exited.

From now on we'll try and only use a shared ptr if ownership is
implied.  Otherwise a reference will be used (eg, for up pointers).
This commit is contained in:
Joe Thornber 2014-08-26 11:14:49 +01:00
parent 930cc9d412
commit a7c96c0e1e
31 changed files with 391 additions and 406 deletions

View File

@ -237,7 +237,7 @@ namespace {
out << "examining mapping array" << end_message(); out << "examining mapping array" << end_message();
{ {
nested_output::nest _ = out.push(); nested_output::nest _ = out.push();
mapping_array ma(tm, mapping_array::ref_counter(), sb.mapping_root, sb.cache_blocks); mapping_array ma(*tm, mapping_array::ref_counter(), sb.mapping_root, sb.cache_blocks);
check_mapping_array(ma, mapping_rep); check_mapping_array(ma, mapping_rep);
} }
} }
@ -250,7 +250,7 @@ namespace {
out << "examining hint array" << end_message(); out << "examining hint array" << end_message();
{ {
nested_output::nest _ = out.push(); nested_output::nest _ = out.push();
hint_array ha(tm, sb.policy_hint_size, sb.hint_root, sb.cache_blocks); hint_array ha(*tm, sb.policy_hint_size, sb.hint_root, sb.cache_blocks);
ha.check(hint_rep); ha.check(hint_rep);
} }
} }
@ -264,7 +264,7 @@ namespace {
out << "examining discard bitset" << end_message(); out << "examining discard bitset" << end_message();
{ {
nested_output::nest _ = out.push(); nested_output::nest _ = out.push();
persistent_data::bitset discards(tm, sb.discard_root, sb.discard_nr_blocks); persistent_data::bitset discards(*tm, sb.discard_root, sb.discard_nr_blocks);
} }
} }
} }

View File

@ -38,7 +38,7 @@ namespace {
xx(4); xx(4);
template <uint32_t WIDTH> template <uint32_t WIDTH>
shared_ptr<array_base> mk_array(transaction_manager::ptr tm) { shared_ptr<array_base> mk_array(transaction_manager &tm) {
typedef hint_traits<WIDTH> traits; typedef hint_traits<WIDTH> traits;
typedef array<traits> ha; typedef array<traits> ha;
@ -47,7 +47,7 @@ namespace {
return r; return r;
} }
shared_ptr<array_base> mk_array(transaction_manager::ptr tm, uint32_t width) { shared_ptr<array_base> mk_array(transaction_manager &tm, uint32_t width) {
switch (width) { switch (width) {
#define xx(n) case n: return mk_array<n>(tm) #define xx(n) case n: return mk_array<n>(tm)
@ -76,7 +76,7 @@ namespace {
//-------------------------------- //--------------------------------
template <uint32_t WIDTH> template <uint32_t WIDTH>
shared_ptr<array_base> mk_array(transaction_manager::ptr tm, block_address root, unsigned nr_entries) { shared_ptr<array_base> mk_array(transaction_manager &tm, block_address root, unsigned nr_entries) {
typedef hint_traits<WIDTH> traits; typedef hint_traits<WIDTH> traits;
typedef array<traits> ha; typedef array<traits> ha;
@ -85,7 +85,7 @@ namespace {
return r; return r;
} }
shared_ptr<array_base> mk_array(transaction_manager::ptr tm, uint32_t width, block_address root, unsigned nr_entries) { shared_ptr<array_base> mk_array(transaction_manager &tm, uint32_t width, block_address root, unsigned nr_entries) {
switch (width) { switch (width) {
#define xx(n) case n: return mk_array<n>(tm, root, nr_entries) #define xx(n) case n: return mk_array<n>(tm, root, nr_entries)
all_widths all_widths
@ -230,13 +230,13 @@ missing_hints::visit(damage_visitor &v) const
//---------------------------------------------------------------- //----------------------------------------------------------------
hint_array::hint_array(tm_ptr tm, unsigned width) hint_array::hint_array(transaction_manager &tm, unsigned width)
: width_(check_width(width)), : width_(check_width(width)),
impl_(mk_array(tm, width)) impl_(mk_array(tm, width))
{ {
} }
hint_array::hint_array(hint_array::tm_ptr tm, unsigned width, hint_array::hint_array(transaction_manager &tm, unsigned width,
block_address root, unsigned nr_entries) block_address root, unsigned nr_entries)
: width_(check_width(width)), : width_(check_width(width)),
impl_(mk_array(tm, width, root, nr_entries)) impl_(mk_array(tm, width, root, nr_entries))

View File

@ -56,10 +56,9 @@ namespace caching {
class hint_array { class hint_array {
public: public:
typedef boost::shared_ptr<hint_array> ptr; typedef boost::shared_ptr<hint_array> ptr;
typedef persistent_data::transaction_manager::ptr tm_ptr;
hint_array(tm_ptr tm, unsigned width); hint_array(transaction_manager &tm, unsigned width);
hint_array(tm_ptr tm, unsigned width, block_address root, unsigned nr_entries); hint_array(transaction_manager &tm, unsigned width, block_address root, unsigned nr_entries);
unsigned get_nr_entries() const; unsigned get_nr_entries() const;

View File

@ -61,7 +61,7 @@ metadata::setup_hint_array(size_t width)
{ {
if (width > 0) if (width > 0)
hints_ = hint_array::ptr( hints_ = hint_array::ptr(
new hint_array(tm_, width)); new hint_array(*tm_, width));
} }
void void
@ -70,16 +70,16 @@ metadata::create_metadata(block_manager<>::ptr bm)
tm_ = open_tm(bm); tm_ = open_tm(bm);
space_map::ptr core = tm_->get_sm(); space_map::ptr core = tm_->get_sm();
metadata_sm_ = create_metadata_sm(tm_, tm_->get_bm()->get_nr_blocks()); metadata_sm_ = create_metadata_sm(*tm_, tm_->get_bm()->get_nr_blocks());
copy_space_maps(metadata_sm_, core); copy_space_maps(metadata_sm_, core);
tm_->set_sm(metadata_sm_); tm_->set_sm(metadata_sm_);
mappings_ = mapping_array::ptr(new mapping_array(tm_, mapping_array::ref_counter())); mappings_ = mapping_array::ptr(new mapping_array(*tm_, mapping_array::ref_counter()));
// We can't instantiate the hint array yet, since we don't know the // We can't instantiate the hint array yet, since we don't know the
// hint width. // hint width.
discard_bits_ = persistent_data::bitset::ptr(new persistent_data::bitset(tm_)); discard_bits_ = persistent_data::bitset::ptr(new persistent_data::bitset(*tm_));
} }
void void
@ -89,19 +89,19 @@ metadata::open_metadata(block_manager<>::ptr bm)
sb_ = read_superblock(tm_->get_bm()); sb_ = read_superblock(tm_->get_bm());
mappings_ = mapping_array::ptr( mappings_ = mapping_array::ptr(
new mapping_array(tm_, new mapping_array(*tm_,
mapping_array::ref_counter(), mapping_array::ref_counter(),
sb_.mapping_root, sb_.mapping_root,
sb_.cache_blocks)); sb_.cache_blocks));
if (sb_.hint_root) if (sb_.hint_root)
hints_ = hint_array::ptr( hints_ = hint_array::ptr(
new hint_array(tm_, sb_.policy_hint_size, new hint_array(*tm_, sb_.policy_hint_size,
sb_.hint_root, sb_.cache_blocks)); sb_.hint_root, sb_.cache_blocks));
if (sb_.discard_root) if (sb_.discard_root)
discard_bits_ = persistent_data::bitset::ptr( discard_bits_ = persistent_data::bitset::ptr(
new persistent_data::bitset(tm_, sb_.discard_root, sb_.discard_nr_blocks)); new persistent_data::bitset(*tm_, sb_.discard_root, sb_.discard_nr_blocks));
} }
void void

View File

@ -217,14 +217,14 @@ namespace {
writeset_tree_reporter wt_rep(out); writeset_tree_reporter wt_rep(out);
{ {
era_detail_traits::ref_counter rc(tm); era_detail_traits::ref_counter rc(tm);
writeset_tree wt(tm, sb.writeset_tree_root, rc); writeset_tree wt(*tm, sb.writeset_tree_root, rc);
check_writeset_tree(tm, wt, wt_rep); check_writeset_tree(tm, wt, wt_rep);
} }
era_array_reporter ea_rep(out); era_array_reporter ea_rep(out);
{ {
uint32_traits::ref_counter rc; uint32_traits::ref_counter rc;
era_array ea(tm, rc, sb.era_array_root, sb.nr_blocks); era_array ea(*tm, rc, sb.era_array_root, sb.nr_blocks);
check_era_array(ea, sb.current_era, ea_rep); check_era_array(ea, sb.current_era, ea_rep);
} }

View File

@ -51,12 +51,12 @@ metadata::create_metadata(block_manager<>::ptr bm)
tm_ = open_tm(bm); tm_ = open_tm(bm);
space_map::ptr core = tm_->get_sm(); space_map::ptr core = tm_->get_sm();
metadata_sm_ = create_metadata_sm(tm_, tm_->get_bm()->get_nr_blocks()); metadata_sm_ = create_metadata_sm(*tm_, tm_->get_bm()->get_nr_blocks());
copy_space_maps(metadata_sm_, core); copy_space_maps(metadata_sm_, core);
tm_->set_sm(metadata_sm_); tm_->set_sm(metadata_sm_);
writeset_tree_ = writeset_tree::ptr(new writeset_tree(tm_, era_detail_traits::ref_counter(tm_))); writeset_tree_ = writeset_tree::ptr(new writeset_tree(*tm_, era_detail_traits::ref_counter(tm_)));
era_array_ = era_array::ptr(new era_array(tm_, era_array_ = era_array::ptr(new era_array(*tm_,
uint32_traits::ref_counter())); uint32_traits::ref_counter()));
} }
@ -66,11 +66,11 @@ metadata::open_metadata(block_manager<>::ptr bm, block_address loc)
tm_ = open_tm(bm); tm_ = open_tm(bm);
sb_ = read_superblock(tm_->get_bm(), loc); sb_ = read_superblock(tm_->get_bm(), loc);
writeset_tree_ = writeset_tree::ptr(new writeset_tree(tm_, writeset_tree_ = writeset_tree::ptr(new writeset_tree(*tm_,
sb_.writeset_tree_root, sb_.writeset_tree_root,
era_detail_traits::ref_counter(tm_))); era_detail_traits::ref_counter(tm_)));
era_array_ = era_array::ptr(new era_array(tm_, era_array_ = era_array::ptr(new era_array(*tm_,
uint32_traits::ref_counter(), uint32_traits::ref_counter(),
sb_.era_array_root, sb_.era_array_root,
sb_.nr_blocks)); sb_.nr_blocks));

View File

@ -52,7 +52,7 @@ namespace {
in_writeset_ = true; in_writeset_ = true;
era_ = era; era_ = era;
bits_.reset(new bitset(md_.tm_)); bits_.reset(new bitset(*md_.tm_));
bits_->grow(nr_bits, false); bits_->grow(nr_bits, false);
} }

View File

@ -54,7 +54,7 @@ namespace {
void visit(btree_path const &path, era_detail const &era) { void visit(btree_path const &path, era_detail const &era) {
era_ = path[0]; era_ = path[0];
persistent_data::bitset bs(tm_, era.writeset_root, era.nr_bits); persistent_data::bitset bs(*tm_, era.writeset_root, era.nr_bits);
writeset_v_.writeset_begin(era_, era.nr_bits); writeset_v_.writeset_begin(era_, era.nr_bits);
bs.walk_bitset(*this); bs.walk_bitset(*this);
writeset_v_.writeset_end(); writeset_v_.writeset_end();

View File

@ -172,7 +172,7 @@ namespace persistent_data {
unsigned visit_array_block(ValueVisitor &vv, unsigned visit_array_block(ValueVisitor &vv,
btree_path const &p, btree_path const &p,
typename block_traits::value_type const &v) const { 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++) for (uint32_t i = 0; i < rb.nr_entries(); i++)
vv.visit(p[0] * rb.max_entries() + i, rb.get(i)); vv.visit(p[0] * rb.max_entries() + i, rb.get(i));
@ -207,8 +207,6 @@ namespace persistent_data {
unsigned entries_per_block_; unsigned entries_per_block_;
}; };
typedef typename persistent_data::transaction_manager::ptr tm_ptr;
typedef block_manager<>::write_ref write_ref; typedef block_manager<>::write_ref write_ref;
typedef block_manager<>::read_ref read_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::value_type value_type;
typedef typename ValueTraits::ref_counter ref_counter; typedef typename ValueTraits::ref_counter ref_counter;
array(tm_ptr tm, ref_counter rc) array(transaction_manager &tm, ref_counter rc)
: tm_(tm), : tm_(tm),
entries_per_block_(rblock::calc_max_entries()), entries_per_block_(rblock::calc_max_entries()),
nr_entries_(0), nr_entries_(0),
block_rc_(tm->get_sm(), *this), block_rc_(tm.get_sm(), *this),
block_tree_(tm, block_rc_), block_tree_(tm, block_rc_),
rc_(rc), rc_(rc),
validator_(new array_detail::array_block_validator) { validator_(new array_detail::array_block_validator) {
} }
array(tm_ptr tm, ref_counter rc, array(transaction_manager &tm, ref_counter rc,
block_address root, block_address root,
unsigned nr_entries) unsigned nr_entries)
: tm_(tm), : tm_(tm),
entries_per_block_(rblock::calc_max_entries()), entries_per_block_(rblock::calc_max_entries()),
nr_entries_(nr_entries), nr_entries_(nr_entries),
block_rc_(tm->get_sm(), *this), block_rc_(tm.get_sm(), *this),
block_tree_(tm, root, block_rc_), block_tree_(tm, root, block_rc_),
rc_(rc), rc_(rc),
validator_(new array_detail::array_block_validator) { validator_(new array_detail::array_block_validator) {
@ -393,7 +391,7 @@ namespace persistent_data {
wblock new_ablock(unsigned ablock_index) { wblock new_ablock(unsigned ablock_index) {
uint64_t key[1] = {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(); block_address location = b.get_location();
wblock wb(b, rc_); wblock wb(b, rc_);
@ -404,13 +402,13 @@ namespace persistent_data {
rblock get_ablock(unsigned ablock_index) const { rblock get_ablock(unsigned ablock_index) const {
block_address addr = lookup_block_address(ablock_index); 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) { wblock shadow_ablock(unsigned ablock_index) {
uint64_t key[1] = {ablock_index}; uint64_t key[1] = {ablock_index};
block_address addr = lookup_block_address(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_); wblock wb = wblock(p.first, rc_);
if (p.second) if (p.second)
@ -422,11 +420,11 @@ namespace persistent_data {
} }
void dec_ablock_entries(block_address addr) { 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(); b.dec_all_entries();
} }
tm_ptr tm_; transaction_manager &tm_;
unsigned entries_per_block_; unsigned entries_per_block_;
unsigned nr_entries_; unsigned nr_entries_;
block_ref_counter block_rc_; block_ref_counter block_rc_;

View File

@ -33,12 +33,12 @@ namespace persistent_data {
typedef boost::shared_ptr<bitset_impl> ptr; typedef boost::shared_ptr<bitset_impl> ptr;
typedef persistent_data::transaction_manager::ptr tm_ptr; typedef persistent_data::transaction_manager::ptr tm_ptr;
bitset_impl(tm_ptr tm) bitset_impl(transaction_manager &tm)
: nr_bits_(0), : nr_bits_(0),
array_(tm, rc_) { 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), : nr_bits_(nr_bits),
array_(tm, rc_, root, nr_bits / BITS_PER_ULL) { array_(tm, rc_, root, nr_bits / BITS_PER_ULL) {
} }
@ -203,12 +203,12 @@ namespace persistent_data {
//---------------------------------------------------------------- //----------------------------------------------------------------
persistent_data::bitset::bitset(tm_ptr tm) persistent_data::bitset::bitset(transaction_manager &tm)
: impl_(new bitset_impl(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)) : impl_(new bitset_impl(tm, root, nr_bits))
{ {
} }

View File

@ -49,10 +49,10 @@ namespace persistent_data {
class bitset { class bitset {
public: public:
typedef boost::shared_ptr<bitset> ptr; typedef boost::shared_ptr<bitset> ptr;
typedef persistent_data::transaction_manager::ptr tm_ptr;
bitset(tm_ptr tm); bitset(transaction_manager &tm);
bitset(tm_ptr tm, block_address root, unsigned nr_bits); bitset(transaction_manager &tm,
block_address root, unsigned nr_bits);
block_address get_root() const; block_address get_root() const;
unsigned get_nr_bits() const; unsigned get_nr_bits() const;
void grow(unsigned new_nr_bits, bool default_value); void grow(unsigned new_nr_bits, bool default_value);

View File

@ -34,7 +34,7 @@ namespace {
//---------------------------------------------------------------- //----------------------------------------------------------------
bloom_filter::bloom_filter(tm_ptr tm, bloom_filter::bloom_filter(transaction_manager &tm,
unsigned nr_bits, unsigned nr_probes) unsigned nr_bits, unsigned nr_probes)
: tm_(tm), : tm_(tm),
bits_(tm), bits_(tm),
@ -45,7 +45,7 @@ bloom_filter::bloom_filter(tm_ptr tm,
bits_.grow(nr_bits, false); bits_.grow(nr_bits, false);
} }
bloom_filter::bloom_filter(tm_ptr tm, block_address root, bloom_filter::bloom_filter(transaction_manager &tm, block_address root,
unsigned nr_bits, unsigned nr_probes) unsigned nr_bits, unsigned nr_probes)
: tm_(tm), : tm_(tm),
bits_(tm, root, nr_bits), bits_(tm, root, nr_bits),

View File

@ -12,13 +12,12 @@ namespace persistent_data {
class bloom_filter { class bloom_filter {
public: public:
typedef boost::shared_ptr<bloom_filter> ptr; typedef boost::shared_ptr<bloom_filter> ptr;
typedef persistent_data::transaction_manager::ptr tm_ptr;
// nr_bits must be a power of two // nr_bits must be a power of two
bloom_filter(tm_ptr tm, bloom_filter(transaction_manager &tm,
unsigned nr_bits, unsigned nr_probes); unsigned nr_bits, unsigned nr_probes);
bloom_filter(tm_ptr tm, block_address root, bloom_filter(transaction_manager &tm, block_address root,
unsigned nr_bits_power, unsigned nr_probes); unsigned nr_bits_power, unsigned nr_probes);
block_address get_root() const; block_address get_root() const;
@ -34,7 +33,7 @@ namespace persistent_data {
void fill_probes(block_address b, vector<unsigned> &probes) const; void fill_probes(block_address b, vector<unsigned> &probes) const;
tm_ptr tm_; transaction_manager &tm_;
persistent_data::bitset bits_; persistent_data::bitset bits_;
unsigned nr_probes_; unsigned nr_probes_;
uint64_t mask_; uint64_t mask_;

View File

@ -198,7 +198,7 @@ namespace persistent_data {
class ro_spine : private boost::noncopyable { class ro_spine : private boost::noncopyable {
public: public:
ro_spine(transaction_manager::ptr tm, ro_spine(transaction_manager &tm,
bcache::validator::ptr v) bcache::validator::ptr v)
: tm_(tm), : tm_(tm),
validator_(v) { validator_(v) {
@ -212,7 +212,7 @@ namespace persistent_data {
} }
private: private:
transaction_manager::ptr tm_; transaction_manager &tm_;
bcache::validator::ptr validator_; bcache::validator::ptr validator_;
std::list<block_manager<>::read_ref> spine_; std::list<block_manager<>::read_ref> spine_;
}; };
@ -223,7 +223,7 @@ namespace persistent_data {
typedef transaction_manager::write_ref write_ref; typedef transaction_manager::write_ref write_ref;
typedef boost::optional<block_address> maybe_block; typedef boost::optional<block_address> maybe_block;
shadow_spine(transaction_manager::ptr tm, shadow_spine(transaction_manager &tm,
bcache::validator::ptr v) bcache::validator::ptr v)
: tm_(tm), : tm_(tm),
@ -276,7 +276,7 @@ namespace persistent_data {
} }
private: private:
transaction_manager::ptr tm_; transaction_manager &tm_;
bcache::validator::ptr validator_; bcache::validator::ptr validator_;
std::list<block_manager<>::write_ref> spine_; std::list<block_manager<>::write_ref> spine_;
maybe_block root_; maybe_block root_;
@ -335,10 +335,10 @@ namespace persistent_data {
typedef typename btree_detail::node_ref<ValueTraits> leaf_node; typedef typename btree_detail::node_ref<ValueTraits> leaf_node;
typedef typename btree_detail::node_ref<block_traits> internal_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); typename ValueTraits::ref_counter rc);
btree(typename transaction_manager::ptr tm, btree(transaction_manager &tm,
block_address root, block_address root,
typename ValueTraits::ref_counter rc); typename ValueTraits::ref_counter rc);
@ -434,7 +434,7 @@ namespace persistent_data {
void inc_children(btree_detail::shadow_spine &spine, void inc_children(btree_detail::shadow_spine &spine,
RefCounter &leaf_rc); RefCounter &leaf_rc);
typename persistent_data::transaction_manager::ptr tm_; transaction_manager &tm_;
bool destroy_; bool destroy_;
block_address root_; block_address root_;
block_ref_counter internal_rc_; block_ref_counter internal_rc_;

View File

@ -64,7 +64,7 @@ namespace persistent_data {
inline void inline void
ro_spine::step(block_address b) 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) if (spine_.size() > 2)
spine_.pop_front(); spine_.pop_front();
} }
@ -72,11 +72,11 @@ namespace persistent_data {
inline bool inline bool
shadow_spine::step(block_address b) 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 { try {
step(p.first); step(p.first);
} catch (...) { } catch (...) {
tm_->get_sm()->dec(p.first.get_location()); tm_.get_sm()->dec(p.first.get_location());
throw; throw;
} }
return p.second; return p.second;
@ -392,17 +392,17 @@ namespace persistent_data {
template <unsigned Levels, typename ValueTraits> template <unsigned Levels, typename ValueTraits>
btree<Levels, ValueTraits>:: btree<Levels, ValueTraits>::
btree(typename transaction_manager::ptr tm, btree(transaction_manager &tm,
typename ValueTraits::ref_counter rc) typename ValueTraits::ref_counter rc)
: tm_(tm), : tm_(tm),
destroy_(false), destroy_(false),
internal_rc_(tm->get_sm()), internal_rc_(tm.get_sm()),
rc_(rc), rc_(rc),
validator_(new btree_node_validator) validator_(new btree_node_validator)
{ {
using namespace btree_detail; using namespace btree_detail;
write_ref root = tm_->new_block(validator_); write_ref root = tm_.new_block(validator_);
if (Levels > 1) { if (Levels > 1) {
internal_node n = to_node<block_traits>(root); internal_node n = to_node<block_traits>(root);
@ -424,13 +424,13 @@ namespace persistent_data {
template <unsigned Levels, typename ValueTraits> template <unsigned Levels, typename ValueTraits>
btree<Levels, ValueTraits>:: btree<Levels, ValueTraits>::
btree(typename transaction_manager::ptr tm, btree(transaction_manager &tm,
block_address root, block_address root,
typename ValueTraits::ref_counter rc) typename ValueTraits::ref_counter rc)
: tm_(tm), : tm_(tm),
destroy_(false), destroy_(false),
root_(root), root_(root),
internal_rc_(tm->get_sm()), internal_rc_(tm.get_sm()),
rc_(rc), rc_(rc),
validator_(new btree_node_validator) validator_(new btree_node_validator)
{ {
@ -559,7 +559,7 @@ namespace persistent_data {
typename btree<Levels, ValueTraits>::ptr typename btree<Levels, ValueTraits>::ptr
btree<Levels, ValueTraits>::clone() const btree<Levels, ValueTraits>::clone() const
{ {
tm_->get_sm()->inc(root_); tm_.get_sm()->inc(root_);
return ptr(new btree<Levels, ValueTraits>(tm_, root_, rc_)); return ptr(new btree<Levels, ValueTraits>(tm_, root_, rc_));
} }
@ -635,13 +635,13 @@ namespace persistent_data {
node_type type; node_type type;
unsigned nr_left, nr_right; 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); node_ref<ValueTraits> l = to_node<ValueTraits>(left);
l.set_nr_entries(0); l.set_nr_entries(0);
l.set_max_entries(); l.set_max_entries();
l.set_value_size(sizeof(typename ValueTraits::disk_type)); 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); node_ref<ValueTraits> r = to_node<ValueTraits>(right);
r.set_nr_entries(0); r.set_nr_entries(0);
r.set_max_entries(); r.set_max_entries();
@ -695,7 +695,7 @@ namespace persistent_data {
node_ref<ValueTraits> l = spine.template get_node<ValueTraits>(); node_ref<ValueTraits> l = spine.template get_node<ValueTraits>();
block_address left = spine.get_block(); 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); node_ref<ValueTraits> r = to_node<ValueTraits>(right);
unsigned nr_left = l.get_nr_entries() / 2; unsigned nr_left = l.get_nr_entries() / 2;
@ -822,14 +822,14 @@ 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<block_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) {
if (v.visit_internal(loc, o)) { if (v.visit_internal(loc, o)) {
for (unsigned i = 0; i < o.get_nr_entries(); i++) for (unsigned i = 0; i < o.get_nr_entries(); i++)
tm_->prefetch(o.value_at(i)); tm_.prefetch(o.value_at(i));
for (unsigned i = 0; i < o.get_nr_entries(); i++) { for (unsigned i = 0; i < o.get_nr_entries(); i++) {
node_location loc2(loc); node_location loc2(loc);

View File

@ -98,7 +98,7 @@ namespace {
typedef transaction_manager::read_ref read_ref; typedef transaction_manager::read_ref read_ref;
typedef transaction_manager::write_ref write_ref; typedef transaction_manager::write_ref write_ref;
bitmap(transaction_manager::ptr tm, bitmap(transaction_manager &tm,
index_entry const &ie, index_entry const &ie,
bcache::validator::ptr v) bcache::validator::ptr v)
: tm_(tm), : tm_(tm),
@ -107,7 +107,7 @@ namespace {
} }
ref_t lookup(unsigned b) const { ref_t lookup(unsigned b) const {
read_ref rr = tm_->read_lock(ie_.blocknr_, validator_); read_ref rr = tm_.read_lock(ie_.blocknr_, validator_);
void const *bits = bitmap_data(rr); void const *bits = bitmap_data(rr);
ref_t b1 = test_bit_le(bits, b * 2); ref_t b1 = test_bit_le(bits, b * 2);
ref_t b2 = test_bit_le(bits, b * 2 + 1); ref_t b2 = test_bit_le(bits, b * 2 + 1);
@ -117,7 +117,7 @@ namespace {
} }
void insert(unsigned b, ref_t n) { void insert(unsigned b, ref_t n) {
write_ref wr = tm_->shadow(ie_.blocknr_, validator_).first; write_ref wr = tm_.shadow(ie_.blocknr_, validator_).first;
void *bits = bitmap_data(wr); void *bits = bitmap_data(wr);
bool was_free = !test_bit_le(bits, b * 2) && !test_bit_le(bits, b * 2 + 1); bool was_free = !test_bit_le(bits, b * 2) && !test_bit_le(bits, b * 2 + 1);
if (n == 1 || n == 3) if (n == 1 || n == 3)
@ -158,7 +158,7 @@ namespace {
} }
void iterate(block_address offset, block_address hi, space_map::iterator &it) const { void iterate(block_address offset, block_address hi, space_map::iterator &it) const {
read_ref rr = tm_->read_lock(ie_.blocknr_, validator_); read_ref rr = tm_.read_lock(ie_.blocknr_, validator_);
void const *bits = bitmap_data(rr); void const *bits = bitmap_data(rr);
for (unsigned b = 0; b < hi; b++) { for (unsigned b = 0; b < hi; b++) {
@ -181,7 +181,7 @@ namespace {
return h + 1; return h + 1;
} }
transaction_manager::ptr tm_; transaction_manager &tm_;
bcache::validator::ptr validator_; bcache::validator::ptr validator_;
index_entry ie_; index_entry ie_;
@ -241,7 +241,7 @@ namespace {
typedef transaction_manager::write_ref write_ref; typedef transaction_manager::write_ref write_ref;
sm_disk(index_store::ptr indexes, sm_disk(index_store::ptr indexes,
transaction_manager::ptr tm) transaction_manager &tm)
: tm_(tm), : tm_(tm),
bitmap_validator_(new bitmap_block_validator), bitmap_validator_(new bitmap_block_validator),
indexes_(indexes), indexes_(indexes),
@ -251,7 +251,7 @@ namespace {
} }
sm_disk(index_store::ptr indexes, sm_disk(index_store::ptr indexes,
transaction_manager::ptr tm, transaction_manager &tm,
sm_root const &root) sm_root const &root)
: tm_(tm), : tm_(tm),
bitmap_validator_(new bitmap_block_validator), bitmap_validator_(new bitmap_block_validator),
@ -354,7 +354,7 @@ namespace {
indexes_->resize(bitmap_count); indexes_->resize(bitmap_count);
for (block_address i = old_bitmap_count; i < bitmap_count; i++) { for (block_address i = old_bitmap_count; i < bitmap_count; i++) {
write_ref wr = tm_->new_block(bitmap_validator_); write_ref wr = tm_.new_block(bitmap_validator_);
index_entry ie; index_entry ie;
ie.blocknr_ = wr.get_location(); ie.blocknr_ = wr.get_location();
@ -437,7 +437,7 @@ namespace {
} }
protected: protected:
transaction_manager::ptr get_tm() const { transaction_manager &get_tm() const {
return tm_; return tm_;
} }
@ -501,7 +501,7 @@ namespace {
ref_counts_.remove(key); ref_counts_.remove(key);
} }
transaction_manager::ptr tm_; transaction_manager &tm_;
bcache::validator::ptr bitmap_validator_; bcache::validator::ptr bitmap_validator_;
index_store::ptr indexes_; index_store::ptr indexes_;
block_address nr_blocks_; block_address nr_blocks_;
@ -544,12 +544,12 @@ namespace {
public: public:
typedef boost::shared_ptr<btree_index_store> ptr; typedef boost::shared_ptr<btree_index_store> ptr;
btree_index_store(transaction_manager::ptr tm) btree_index_store(transaction_manager &tm)
: tm_(tm), : tm_(tm),
bitmaps_(tm, index_entry_traits::ref_counter()) { bitmaps_(tm, index_entry_traits::ref_counter()) {
} }
btree_index_store(transaction_manager::ptr tm, btree_index_store(transaction_manager &tm,
block_address root) block_address root)
: tm_(tm), : tm_(tm),
bitmaps_(tm, root, index_entry_traits::ref_counter()) { bitmaps_(tm, root, index_entry_traits::ref_counter()) {
@ -592,7 +592,7 @@ namespace {
} }
private: private:
transaction_manager::ptr tm_; transaction_manager &tm_;
btree<1, index_entry_traits> bitmaps_; btree<1, index_entry_traits> bitmaps_;
}; };
@ -600,13 +600,13 @@ namespace {
public: public:
typedef boost::shared_ptr<metadata_index_store> ptr; typedef boost::shared_ptr<metadata_index_store> ptr;
metadata_index_store(transaction_manager::ptr tm) metadata_index_store(transaction_manager &tm)
: tm_(tm) { : tm_(tm) {
block_manager<>::write_ref wr = tm_->new_block(index_validator()); block_manager<>::write_ref wr = tm_.new_block(index_validator());
bitmap_root_ = wr.get_location(); bitmap_root_ = wr.get_location();
} }
metadata_index_store(transaction_manager::ptr tm, block_address root, block_address nr_indexes) metadata_index_store(transaction_manager &tm, block_address root, block_address nr_indexes)
: tm_(tm), : tm_(tm),
bitmap_root_(root) { bitmap_root_(root) {
resize(nr_indexes); resize(nr_indexes);
@ -627,7 +627,7 @@ namespace {
virtual void commit_ies() { virtual void commit_ies() {
std::pair<block_manager<>::write_ref, bool> p = std::pair<block_manager<>::write_ref, bool> p =
tm_->shadow(bitmap_root_, index_validator()); tm_.shadow(bitmap_root_, index_validator());
bitmap_root_ = p.first.get_location(); bitmap_root_ = p.first.get_location();
metadata_index *mdi = reinterpret_cast<metadata_index *>(p.first.data()); metadata_index *mdi = reinterpret_cast<metadata_index *>(p.first.data());
@ -661,14 +661,14 @@ namespace {
private: private:
void load_ies() { void load_ies() {
block_manager<>::read_ref rr = block_manager<>::read_ref rr =
tm_->read_lock(bitmap_root_, index_validator()); tm_.read_lock(bitmap_root_, index_validator());
metadata_index const *mdi = reinterpret_cast<metadata_index const *>(rr.data()); metadata_index const *mdi = reinterpret_cast<metadata_index const *>(rr.data());
for (unsigned i = 0; i < entries_.size(); i++) for (unsigned i = 0; i < entries_.size(); i++)
index_entry_traits::unpack(*(mdi->index + i), entries_[i]); index_entry_traits::unpack(*(mdi->index + i), entries_[i]);
} }
transaction_manager::ptr tm_; transaction_manager &tm_;
block_address bitmap_root_; block_address bitmap_root_;
std::vector<index_entry> entries_; std::vector<index_entry> entries_;
}; };
@ -677,7 +677,7 @@ namespace {
//---------------------------------------------------------------- //----------------------------------------------------------------
checked_space_map::ptr checked_space_map::ptr
persistent_data::create_disk_sm(transaction_manager::ptr tm, persistent_data::create_disk_sm(transaction_manager &tm,
block_address nr_blocks) block_address nr_blocks)
{ {
index_store::ptr store(new btree_index_store(tm)); index_store::ptr store(new btree_index_store(tm));
@ -688,7 +688,7 @@ persistent_data::create_disk_sm(transaction_manager::ptr tm,
} }
checked_space_map::ptr checked_space_map::ptr
persistent_data::open_disk_sm(transaction_manager::ptr tm, void *root) persistent_data::open_disk_sm(transaction_manager &tm, void *root)
{ {
sm_root_disk d; sm_root_disk d;
sm_root v; sm_root v;
@ -700,7 +700,7 @@ persistent_data::open_disk_sm(transaction_manager::ptr tm, void *root)
} }
checked_space_map::ptr checked_space_map::ptr
persistent_data::create_metadata_sm(transaction_manager::ptr tm, block_address nr_blocks) persistent_data::create_metadata_sm(transaction_manager &tm, block_address nr_blocks)
{ {
index_store::ptr store(new metadata_index_store(tm)); index_store::ptr store(new metadata_index_store(tm));
checked_space_map::ptr sm(new sm_disk(store, tm)); checked_space_map::ptr sm(new sm_disk(store, tm));
@ -711,7 +711,7 @@ persistent_data::create_metadata_sm(transaction_manager::ptr tm, block_address n
} }
checked_space_map::ptr checked_space_map::ptr
persistent_data::open_metadata_sm(transaction_manager::ptr tm, void *root) persistent_data::open_metadata_sm(transaction_manager &tm, void *root)
{ {
sm_root_disk d; sm_root_disk d;
sm_root v; sm_root v;

View File

@ -26,16 +26,16 @@
namespace persistent_data { namespace persistent_data {
checked_space_map::ptr checked_space_map::ptr
create_disk_sm(transaction_manager::ptr tm, block_address nr_blocks); create_disk_sm(transaction_manager &tm, block_address nr_blocks);
checked_space_map::ptr checked_space_map::ptr
open_disk_sm(transaction_manager::ptr tm, void *root); open_disk_sm(transaction_manager &tm, void *root);
checked_space_map::ptr checked_space_map::ptr
create_metadata_sm(transaction_manager::ptr tm, block_address nr_blocks); create_metadata_sm(transaction_manager &tm, block_address nr_blocks);
checked_space_map::ptr checked_space_map::ptr
open_metadata_sm(transaction_manager::ptr tm, void *root); open_metadata_sm(transaction_manager &tm, void *root);
} }
//---------------------------------------------------------------- //----------------------------------------------------------------

View File

@ -71,36 +71,36 @@ metadata::metadata(std::string const &dev_path, open_type ot,
if (sb_.version_ != 1) if (sb_.version_ != 1)
throw runtime_error("unknown metadata version"); throw runtime_error("unknown metadata version");
metadata_sm_ = open_metadata_sm(tm_, &sb_.metadata_space_map_root_); metadata_sm_ = open_metadata_sm(*tm_, &sb_.metadata_space_map_root_);
tm_->set_sm(metadata_sm_); tm_->set_sm(metadata_sm_);
data_sm_ = open_disk_sm(tm_, static_cast<void *>(&sb_.data_space_map_root_)); data_sm_ = open_disk_sm(*tm_, static_cast<void *>(&sb_.data_space_map_root_));
details_ = device_tree::ptr( details_ = device_tree::ptr(
new device_tree(tm_, sb_.device_details_root_, new device_tree(*tm_, sb_.device_details_root_,
device_tree_detail::device_details_traits::ref_counter())); device_tree_detail::device_details_traits::ref_counter()));
mappings_top_level_ = dev_tree::ptr( mappings_top_level_ = dev_tree::ptr(
new dev_tree(tm_, sb_.data_mapping_root_, new dev_tree(*tm_, sb_.data_mapping_root_,
mapping_tree_detail::mtree_ref_counter(tm_))); mapping_tree_detail::mtree_ref_counter(tm_)));
mappings_ = mapping_tree::ptr( mappings_ = mapping_tree::ptr(
new mapping_tree(tm_, sb_.data_mapping_root_, new mapping_tree(*tm_, sb_.data_mapping_root_,
mapping_tree_detail::block_time_ref_counter(data_sm_))); mapping_tree_detail::block_time_ref_counter(data_sm_)));
break; break;
case CREATE: case CREATE:
tm_ = open_tm(open_bm(dev_path, block_manager<>::READ_WRITE)); tm_ = open_tm(open_bm(dev_path, block_manager<>::READ_WRITE));
space_map::ptr core = tm_->get_sm(); space_map::ptr core = tm_->get_sm();
metadata_sm_ = create_metadata_sm(tm_, tm_->get_bm()->get_nr_blocks()); metadata_sm_ = create_metadata_sm(*tm_, tm_->get_bm()->get_nr_blocks());
copy_space_maps(metadata_sm_, core); copy_space_maps(metadata_sm_, core);
tm_->set_sm(metadata_sm_); tm_->set_sm(metadata_sm_);
data_sm_ = create_disk_sm(tm_, nr_data_blocks); data_sm_ = create_disk_sm(*tm_, nr_data_blocks);
details_ = device_tree::ptr(new device_tree(tm_, device_tree_detail::device_details_traits::ref_counter())); details_ = device_tree::ptr(new device_tree(*tm_, device_tree_detail::device_details_traits::ref_counter()));
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, mappings_ = mapping_tree::ptr(new mapping_tree(*tm_,
mapping_tree_detail::block_time_ref_counter(data_sm_))); mapping_tree_detail::block_time_ref_counter(data_sm_)));
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, mappings_->get_root(), mappings_top_level_ = dev_tree::ptr(new dev_tree(*tm_, mappings_->get_root(),
mapping_tree_detail::mtree_ref_counter(tm_))); mapping_tree_detail::mtree_ref_counter(tm_)));
::memset(&sb_, 0, sizeof(sb_)); ::memset(&sb_, 0, sizeof(sb_));
@ -125,11 +125,11 @@ metadata::metadata(std::string const &dev_path, block_address metadata_snap)
//metadata_sm_ = open_metadata_sm(tm_, &sb_.metadata_space_map_root_); //metadata_sm_ = open_metadata_sm(tm_, &sb_.metadata_space_map_root_);
//tm_->set_sm(metadata_sm_); //tm_->set_sm(metadata_sm_);
data_sm_ = open_disk_sm(tm_, static_cast<void *>(&sb_.data_space_map_root_)); data_sm_ = open_disk_sm(*tm_, static_cast<void *>(&sb_.data_space_map_root_));
details_ = device_tree::ptr(new device_tree(tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter())); details_ = device_tree::ptr(new device_tree(*tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter()));
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, sb_.data_mapping_root_, mappings_top_level_ = dev_tree::ptr(new dev_tree(*tm_, sb_.data_mapping_root_,
mapping_tree_detail::mtree_ref_counter(tm_))); mapping_tree_detail::mtree_ref_counter(tm_)));
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, sb_.data_mapping_root_, mappings_ = mapping_tree::ptr(new mapping_tree(*tm_, sb_.data_mapping_root_,
mapping_tree_detail::block_time_ref_counter(data_sm_))); mapping_tree_detail::block_time_ref_counter(data_sm_)));
} }
@ -146,29 +146,29 @@ metadata::metadata(block_manager<>::ptr bm, open_type ot,
if (sb_.version_ != 1) if (sb_.version_ != 1)
throw runtime_error("unknown metadata version"); throw runtime_error("unknown metadata version");
metadata_sm_ = open_metadata_sm(tm_, &sb_.metadata_space_map_root_); metadata_sm_ = open_metadata_sm(*tm_, &sb_.metadata_space_map_root_);
tm_->set_sm(metadata_sm_); tm_->set_sm(metadata_sm_);
data_sm_ = open_disk_sm(tm_, static_cast<void *>(&sb_.data_space_map_root_)); data_sm_ = open_disk_sm(*tm_, static_cast<void *>(&sb_.data_space_map_root_));
details_ = device_tree::ptr(new device_tree(tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter())); details_ = device_tree::ptr(new device_tree(*tm_, sb_.device_details_root_, device_tree_detail::device_details_traits::ref_counter()));
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, sb_.data_mapping_root_, mappings_top_level_ = dev_tree::ptr(new dev_tree(*tm_, sb_.data_mapping_root_,
mapping_tree_detail::mtree_ref_counter(tm_))); mapping_tree_detail::mtree_ref_counter(tm_)));
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, sb_.data_mapping_root_, mappings_ = mapping_tree::ptr(new mapping_tree(*tm_, sb_.data_mapping_root_,
mapping_tree_detail::block_time_ref_counter(data_sm_))); mapping_tree_detail::block_time_ref_counter(data_sm_)));
break; break;
case CREATE: case CREATE:
tm_ = open_tm(bm); tm_ = open_tm(bm);
space_map::ptr core = tm_->get_sm(); space_map::ptr core = tm_->get_sm();
metadata_sm_ = create_metadata_sm(tm_, tm_->get_bm()->get_nr_blocks()); metadata_sm_ = create_metadata_sm(*tm_, tm_->get_bm()->get_nr_blocks());
copy_space_maps(metadata_sm_, core); copy_space_maps(metadata_sm_, core);
tm_->set_sm(metadata_sm_); tm_->set_sm(metadata_sm_);
data_sm_ = create_disk_sm(tm_, nr_data_blocks); data_sm_ = create_disk_sm(*tm_, nr_data_blocks);
details_ = device_tree::ptr(new device_tree(tm_, device_tree_detail::device_details_traits::ref_counter())); details_ = device_tree::ptr(new device_tree(*tm_, device_tree_detail::device_details_traits::ref_counter()));
mappings_ = mapping_tree::ptr(new mapping_tree(tm_, mappings_ = mapping_tree::ptr(new mapping_tree(*tm_,
mapping_tree_detail::block_time_ref_counter(data_sm_))); mapping_tree_detail::block_time_ref_counter(data_sm_)));
mappings_top_level_ = dev_tree::ptr(new dev_tree(tm_, mappings_->get_root(), mappings_top_level_ = dev_tree::ptr(new dev_tree(*tm_, mappings_->get_root(),
mapping_tree_detail::mtree_ref_counter(tm_))); mapping_tree_detail::mtree_ref_counter(tm_)));
::memset(&sb_, 0, sizeof(sb_)); ::memset(&sb_, 0, sizeof(sb_));

View File

@ -200,7 +200,7 @@ namespace {
private: private:
void emit_mappings(block_address subtree_root) { void emit_mappings(block_address subtree_root) {
mapping_emitter me(e_); mapping_emitter me(e_);
single_mapping_tree tree(md_->tm_, subtree_root, single_mapping_tree tree(*md_->tm_, subtree_root,
mapping_tree_detail::block_time_ref_counter(md_->data_sm_)); mapping_tree_detail::block_time_ref_counter(md_->data_sm_));
walk_mapping_tree(tree, static_cast<mapping_tree_detail::mapping_visitor &>(me), *damage_policy_); walk_mapping_tree(tree, static_cast<mapping_tree_detail::mapping_visitor &>(me), *damage_policy_);
} }

View File

@ -134,7 +134,7 @@ namespace {
private: private:
single_mapping_tree::ptr new_mapping_tree() { single_mapping_tree::ptr new_mapping_tree() {
return single_mapping_tree::ptr( return single_mapping_tree::ptr(
new single_mapping_tree(md_->tm_, new single_mapping_tree(*md_->tm_,
mapping_tree_detail::block_time_ref_counter(md_->data_sm_))); mapping_tree_detail::block_time_ref_counter(md_->data_sm_)));
} }

View File

@ -194,7 +194,7 @@ namespace {
out << "examining devices tree" << end_message(); out << "examining devices tree" << end_message();
{ {
nested_output::nest _ = out.push(); nested_output::nest _ = out.push();
device_tree dtree(tm, sb.device_details_root_, device_tree dtree(*tm, sb.device_details_root_,
device_tree_detail::device_details_traits::ref_counter()); device_tree_detail::device_details_traits::ref_counter());
check_device_tree(dtree, dev_rep); check_device_tree(dtree, dev_rep);
} }
@ -204,7 +204,7 @@ namespace {
out << "examining top level of mapping tree" << end_message(); out << "examining top level of mapping tree" << end_message();
{ {
nested_output::nest _ = out.push(); nested_output::nest _ = out.push();
dev_tree dtree(tm, sb.data_mapping_root_, dev_tree dtree(*tm, sb.data_mapping_root_,
mapping_tree_detail::mtree_traits::ref_counter(tm)); mapping_tree_detail::mtree_traits::ref_counter(tm));
check_mapping_tree(dtree, mapping_rep); check_mapping_tree(dtree, mapping_rep);
} }
@ -213,7 +213,7 @@ namespace {
out << "examining mapping tree" << end_message(); out << "examining mapping tree" << end_message();
{ {
nested_output::nest _ = out.push(); nested_output::nest _ = out.push();
mapping_tree mtree(tm, sb.data_mapping_root_, mapping_tree mtree(*tm, sb.data_mapping_root_,
mapping_tree_detail::block_traits::ref_counter(tm->get_sm())); mapping_tree_detail::block_traits::ref_counter(tm->get_sm()));
check_mapping_tree(mtree, mapping_rep); check_mapping_tree(mtree, mapping_rep);
} }

View File

@ -450,7 +450,7 @@ namespace {
superblock_detail::superblock sb = read_superblock(bm); superblock_detail::superblock sb = read_superblock(bm);
dev_tree dtree(tm, sb.data_mapping_root_, dev_tree dtree(*tm, sb.data_mapping_root_,
mapping_tree_detail::mtree_traits::ref_counter(tm)); mapping_tree_detail::mtree_traits::ref_counter(tm));
dev_tree::key k = {*fs.snap1}; dev_tree::key k = {*fs.snap1};
@ -462,7 +462,7 @@ namespace {
app.die(out.str()); app.die(out.str());
} }
single_mapping_tree snap1(tm, *snap1_root, mapping_tree_detail::block_traits::ref_counter(tm->get_sm())); single_mapping_tree snap1(*tm, *snap1_root, mapping_tree_detail::block_traits::ref_counter(tm->get_sm()));
k[0] = *fs.snap2; k[0] = *fs.snap2;
boost::optional<uint64_t> snap2_root = dtree.lookup(k); boost::optional<uint64_t> snap2_root = dtree.lookup(k);
@ -473,7 +473,7 @@ namespace {
app.die(out.str()); app.die(out.str());
} }
single_mapping_tree snap2(tm, *snap2_root, mapping_tree_detail::block_traits::ref_counter(tm->get_sm())); single_mapping_tree snap2(*tm, *snap2_root, mapping_tree_detail::block_traits::ref_counter(tm->get_sm()));
btree_visit_values(snap1, mr1, damage_v); btree_visit_values(snap1, mr1, damage_v);
btree_visit_values(snap2, mr2, damage_v); btree_visit_values(snap2, mr2, damage_v);
} }

View File

@ -122,7 +122,7 @@ thin_pool::create_thin(thin_dev_t dev)
if (device_exists(dev)) if (device_exists(dev))
throw std::runtime_error("Device already exists"); throw std::runtime_error("Device already exists");
single_mapping_tree::ptr new_tree(new single_mapping_tree(md_->tm_, single_mapping_tree::ptr new_tree(new single_mapping_tree(*md_->tm_,
mapping_tree_detail::block_time_ref_counter(md_->data_sm_))); mapping_tree_detail::block_time_ref_counter(md_->data_sm_)));
md_->mappings_top_level_->insert(key, new_tree->get_root()); md_->mappings_top_level_->insert(key, new_tree->get_root());
md_->mappings_->set_root(md_->mappings_top_level_->get_root()); // FIXME: ugly md_->mappings_->set_root(md_->mappings_top_level_->get_root()); // FIXME: ugly
@ -140,7 +140,7 @@ thin_pool::create_snap(thin_dev_t dev, thin_dev_t origin)
if (!mtree_root) if (!mtree_root)
throw std::runtime_error("unknown origin"); throw std::runtime_error("unknown origin");
single_mapping_tree otree(md_->tm_, *mtree_root, single_mapping_tree otree(*md_->tm_, *mtree_root,
mapping_tree_detail::block_time_ref_counter(md_->data_sm_)); mapping_tree_detail::block_time_ref_counter(md_->data_sm_));
single_mapping_tree::ptr clone(otree.clone()); single_mapping_tree::ptr clone(otree.clone());

View File

@ -75,7 +75,7 @@ namespace {
transaction_manager::ptr tm = open_tm(bm); transaction_manager::ptr tm = open_tm(bm);
superblock_detail::superblock sb = read_superblock(bm); superblock_detail::superblock sb = read_superblock(bm);
mapping_tree mtree(tm, sb.data_mapping_root_, mapping_tree mtree(*tm, sb.data_mapping_root_,
mapping_tree_detail::block_traits::ref_counter(tm->get_sm())); mapping_tree_detail::block_traits::ref_counter(tm->get_sm()));
btree_visit_values(mtree, rv, dv); btree_visit_values(mtree, rv, dv);

View File

@ -37,7 +37,9 @@ namespace {
class ArrayTests : public Test { class ArrayTests : public Test {
public: public:
ArrayTests() ArrayTests()
: tm_(create_tm()) { : bm_(new block_manager<>("./test.data", NR_BLOCKS, 4, block_manager<>::READ_WRITE)),
sm_(new core_map(NR_BLOCKS)),
tm_(bm_, sm_) {
} }
void void
@ -76,15 +78,9 @@ namespace {
array64::ptr a_; array64::ptr a_;
private: private:
static transaction_manager::ptr block_manager<>::ptr bm_;
create_tm() { space_map::ptr sm_;
block_manager<>::ptr bm(new block_manager<>("./test.data", NR_BLOCKS, 4, block_manager<>::READ_WRITE)); transaction_manager tm_;
space_map::ptr sm(new core_map(NR_BLOCKS));
transaction_manager::ptr tm(new transaction_manager(bm, sm));
return tm;
}
transaction_manager::ptr tm_;
}; };
class value_visitor { class value_visitor {

View File

@ -32,34 +32,40 @@ using namespace testing;
namespace { namespace {
block_address const NR_BLOCKS = 102400; block_address const NR_BLOCKS = 102400;
transaction_manager::ptr class BitsetTests : public Test {
create_tm() { public:
block_manager<>::ptr bm(new block_manager<>("./test.data", NR_BLOCKS, 4, block_manager<>::READ_WRITE)); BitsetTests()
space_map::ptr sm(new core_map(NR_BLOCKS)); : bm_(new block_manager<>("./test.data", NR_BLOCKS, 4, block_manager<>::READ_WRITE)),
transaction_manager::ptr tm(new transaction_manager(bm, sm)); sm_(new core_map(NR_BLOCKS)),
return tm; tm_(bm_, sm_) {
} }
bitset::ptr bitset::ptr
create_bitset() { create_bitset() {
return bitset::ptr(new bitset(create_tm())); return bitset::ptr(new bitset(tm_));
} }
bitset::ptr bitset::ptr
open_bitset(block_address root, unsigned count) { open_bitset(block_address root, unsigned count) {
return bitset::ptr(new bitset(create_tm(), root, count)); return bitset::ptr(new bitset(tm_, root, count));
} }
private:
block_manager<>::ptr bm_;
space_map::ptr sm_;
transaction_manager tm_;
};
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
TEST(BitsetTests, create_empty_bitset) TEST_F(BitsetTests, create_empty_bitset)
{ {
bitset::ptr bs = create_bitset(); bitset::ptr bs = create_bitset();
ASSERT_THROW(bs->get(0), runtime_error); ASSERT_THROW(bs->get(0), runtime_error);
} }
TEST(BitsetTests, grow_default_false) TEST_F(BitsetTests, grow_default_false)
{ {
unsigned const COUNT = 100000; unsigned const COUNT = 100000;
@ -70,7 +76,7 @@ TEST(BitsetTests, grow_default_false)
ASSERT_FALSE(bs->get(i)); ASSERT_FALSE(bs->get(i));
} }
TEST(BitsetTests, grow_default_true) TEST_F(BitsetTests, grow_default_true)
{ {
unsigned const COUNT = 100000; unsigned const COUNT = 100000;
@ -81,7 +87,7 @@ TEST(BitsetTests, grow_default_true)
ASSERT_TRUE(bs->get(i)); ASSERT_TRUE(bs->get(i));
} }
TEST(BitsetTests, grow_throws_if_actualy_asked_to_shrink) TEST_F(BitsetTests, grow_throws_if_actualy_asked_to_shrink)
{ {
unsigned const COUNT = 100000; unsigned const COUNT = 100000;
@ -90,7 +96,7 @@ TEST(BitsetTests, grow_throws_if_actualy_asked_to_shrink)
ASSERT_THROW(bs->grow(COUNT / 2, false), runtime_error); ASSERT_THROW(bs->grow(COUNT / 2, false), runtime_error);
} }
TEST(BitsetTests, multiple_grow_calls) TEST_F(BitsetTests, multiple_grow_calls)
{ {
unsigned const COUNT = 100000; unsigned const COUNT = 100000;
unsigned const STEP = 37; unsigned const STEP = 37;
@ -121,7 +127,7 @@ TEST(BitsetTests, multiple_grow_calls)
} }
} }
TEST(BitsetTests, set_out_of_bounds_throws) TEST_F(BitsetTests, set_out_of_bounds_throws)
{ {
unsigned const COUNT = 100000; unsigned const COUNT = 100000;
bitset::ptr bs = create_bitset(); bitset::ptr bs = create_bitset();
@ -131,7 +137,7 @@ TEST(BitsetTests, set_out_of_bounds_throws)
ASSERT_THROW(bs->set(COUNT, true), runtime_error); ASSERT_THROW(bs->set(COUNT, true), runtime_error);
} }
TEST(BitsetTests, set_works) TEST_F(BitsetTests, set_works)
{ {
unsigned const COUNT = 100000; unsigned const COUNT = 100000;
bitset::ptr bs = create_bitset(); bitset::ptr bs = create_bitset();
@ -144,7 +150,7 @@ TEST(BitsetTests, set_works)
ASSERT_THAT(bs->get(i), Eq(i % 7 ? true : false)); ASSERT_THAT(bs->get(i), Eq(i % 7 ? true : false));
} }
TEST(BitsetTests, reopen_works) TEST_F(BitsetTests, reopen_works)
{ {
unsigned const COUNT = 100000; unsigned const COUNT = 100000;
block_address root; block_address root;

View File

@ -31,7 +31,7 @@ namespace {
BloomFilterTests() BloomFilterTests()
: bm_(create_bm<BLOCK_SIZE>(NR_BLOCKS)), : bm_(create_bm<BLOCK_SIZE>(NR_BLOCKS)),
sm_(setup_core_map()), sm_(setup_core_map()),
tm_(new transaction_manager(bm_, sm_)) { tm_(bm_, sm_) {
} }
set<block_address> generate_random_blocks(unsigned count, set<block_address> generate_random_blocks(unsigned count,
@ -73,7 +73,7 @@ namespace {
with_temp_directory dir_; with_temp_directory dir_;
block_manager<>::ptr bm_; block_manager<>::ptr bm_;
space_map::ptr sm_; space_map::ptr sm_;
transaction_manager::ptr tm_; transaction_manager tm_;
boost::random::mt19937 rng_; boost::random::mt19937 rng_;
}; };

View File

@ -25,7 +25,7 @@ namespace {
BTreeCounterTests() BTreeCounterTests()
: bm_(create_bm<BLOCK_SIZE>(NR_BLOCKS)), : bm_(create_bm<BLOCK_SIZE>(NR_BLOCKS)),
sm_(setup_core_map()), sm_(setup_core_map()),
tm_(new transaction_manager(bm_, sm_)) { tm_(bm_, sm_) {
} }
void check_nr_metadata_blocks_is_ge(unsigned n) { void check_nr_metadata_blocks_is_ge(unsigned n) {
@ -38,7 +38,7 @@ namespace {
with_temp_directory dir_; with_temp_directory dir_;
block_manager<>::ptr bm_; block_manager<>::ptr bm_;
space_map::ptr sm_; space_map::ptr sm_;
transaction_manager::ptr tm_; transaction_manager tm_;
uint64_traits::ref_counter rc_; uint64_traits::ref_counter rc_;
btree<1, uint64_traits>::ptr tree_; btree<1, uint64_traits>::ptr tree_;

View File

@ -281,7 +281,7 @@ namespace {
DamageTests() DamageTests()
: bm_(create_bm<BLOCK_SIZE>(NR_BLOCKS)), : bm_(create_bm<BLOCK_SIZE>(NR_BLOCKS)),
sm_(setup_core_map()), sm_(setup_core_map()),
tm_(new transaction_manager(bm_, sm_)) { tm_(bm_, sm_) {
} }
virtual ~DamageTests() {} virtual ~DamageTests() {}
@ -315,7 +315,7 @@ namespace {
with_temp_directory dir_; with_temp_directory dir_;
block_manager<>::ptr bm_; block_manager<>::ptr bm_;
space_map::ptr sm_; space_map::ptr sm_;
transaction_manager::ptr tm_; transaction_manager tm_;
thing_traits::ref_counter rc_; thing_traits::ref_counter rc_;
boost::optional<btree_layout> layout_; boost::optional<btree_layout> layout_;

View File

@ -31,21 +31,28 @@ using namespace testing;
namespace { namespace {
block_address const NR_BLOCKS = 102400; block_address const NR_BLOCKS = 102400;
transaction_manager::ptr class BtreeTests : public Test {
create_tm() { public:
block_manager<>::ptr bm(new block_manager<>("./test.data", NR_BLOCKS, 4, block_manager<>::READ_WRITE)); BtreeTests()
space_map::ptr sm(new core_map(NR_BLOCKS)); : bm_(new block_manager<>("./test.data", NR_BLOCKS, 4, block_manager<>::READ_WRITE)),
transaction_manager::ptr tm(new transaction_manager(bm, sm)); sm_(new core_map(NR_BLOCKS)),
return tm; tm_(bm_, sm_) {
} }
btree<1, uint64_traits>::ptr btree<1, uint64_traits>::ptr
create_btree() { create_btree() {
uint64_traits::ref_counter rc; uint64_traits::ref_counter rc;
return btree<1, uint64_traits>::ptr(
new btree<1, uint64_traits>(tm_, rc));
}
private:
block_manager<>::ptr bm_;
space_map::ptr sm_;
transaction_manager tm_;
};
return btree<1, uint64_traits>::ptr(
new btree<1, uint64_traits>(create_tm(), rc));
}
// Checks that a btree is well formed. // Checks that a btree is well formed.
// //
@ -99,7 +106,7 @@ namespace {
//---------------------------------------------------------------- //----------------------------------------------------------------
TEST(BtreeTests, empty_btree_contains_nothing) TEST_F(BtreeTests, empty_btree_contains_nothing)
{ {
btree<1, uint64_traits>::ptr tree = create_btree(); btree<1, uint64_traits>::ptr tree = create_btree();
check_constraints(tree); check_constraints(tree);
@ -110,7 +117,7 @@ TEST(BtreeTests, empty_btree_contains_nothing)
} }
} }
TEST(BtreeTests, insert_works) TEST_F(BtreeTests, insert_works)
{ {
unsigned const COUNT = 100000; unsigned const COUNT = 100000;
@ -129,7 +136,7 @@ TEST(BtreeTests, insert_works)
check_constraints(tree); check_constraints(tree);
} }
TEST(BtreeTests, insert_does_not_insert_imaginary_values) TEST_F(BtreeTests, insert_does_not_insert_imaginary_values)
{ {
btree<1, uint64_traits>::ptr tree = create_btree(); btree<1, uint64_traits>::ptr tree = create_btree();
uint64_t key[1] = {0}; uint64_t key[1] = {0};
@ -156,7 +163,7 @@ TEST(BtreeTests, insert_does_not_insert_imaginary_values)
check_constraints(tree); check_constraints(tree);
} }
TEST(BtreeTests, clone) TEST_F(BtreeTests, clone)
{ {
typedef btree<1, uint64_traits> tree64; typedef btree<1, uint64_traits> tree64;

View File

@ -33,278 +33,258 @@ namespace {
block_address const SUPERBLOCK = 0; block_address const SUPERBLOCK = 0;
block_address const MAX_LOCKS = 8; block_address const MAX_LOCKS = 8;
transaction_manager::ptr class SpaceMapTests : public Test {
create_tm() { public:
block_manager<>::ptr bm( SpaceMapTests()
new block_manager<>("./test.data", NR_BLOCKS, MAX_LOCKS, block_manager<>::READ_WRITE)); : bm_(new block_manager<>("./test.data", NR_BLOCKS, MAX_LOCKS, block_manager<>::READ_WRITE)),
space_map::ptr sm(new core_map(NR_BLOCKS)); sm_(new core_map(NR_BLOCKS)),
transaction_manager::ptr tm( tm_(bm_, sm_) {
new transaction_manager(bm, sm));
return tm;
}
struct sm_core_creator {
static space_map::ptr
create() {
return space_map::ptr(new persistent_data::core_map(NR_BLOCKS));
}
};
struct sm_careful_alloc_creator {
static space_map::ptr
create() {
return create_careful_alloc_sm(
checked_space_map::ptr(
new core_map(NR_BLOCKS)));
}
};
struct sm_recursive_creator {
static checked_space_map::ptr
create() {
return create_recursive_sm(
checked_space_map::ptr(
new core_map(NR_BLOCKS)));
}
};
struct sm_disk_creator {
static persistent_space_map::ptr
create() {
transaction_manager::ptr tm = create_tm();
return persistent_data::create_disk_sm(tm, NR_BLOCKS);
} }
static persistent_space_map::ptr struct sm_core_creator {
open(void *root) { static space_map::ptr
transaction_manager::ptr tm = create_tm(); create(transaction_manager &tm) {
return persistent_data::open_disk_sm(tm, root); return space_map::ptr(new persistent_data::core_map(NR_BLOCKS));
} }
}; };
struct sm_metadata_creator { struct sm_careful_alloc_creator {
static persistent_space_map::ptr static space_map::ptr
create() { create(transaction_manager &tm) {
transaction_manager::ptr tm = create_tm(); return create_careful_alloc_sm(
return persistent_data::create_metadata_sm(tm, NR_BLOCKS); checked_space_map::ptr(
new core_map(NR_BLOCKS)));
}
};
struct sm_recursive_creator {
static checked_space_map::ptr
create(transaction_manager &tm) {
return create_recursive_sm(
checked_space_map::ptr(
new core_map(NR_BLOCKS)));
}
};
struct sm_disk_creator {
static persistent_space_map::ptr
create(transaction_manager &tm) {
return persistent_data::create_disk_sm(tm, NR_BLOCKS);
}
static persistent_space_map::ptr
open(transaction_manager &tm, void *root) {
return persistent_data::open_disk_sm(tm, root);
}
};
struct sm_metadata_creator {
static persistent_space_map::ptr
create(transaction_manager &tm) {
return persistent_data::create_metadata_sm(tm, NR_BLOCKS);
}
static persistent_space_map::ptr
open(transaction_manager &tm, void *root) {
return persistent_data::open_metadata_sm(tm, root);
}
};
//--------------------------------
void test_get_nr_blocks(space_map::ptr sm) {
ASSERT_THAT(sm->get_nr_blocks(), Eq(NR_BLOCKS));
} }
static persistent_space_map::ptr void test_get_nr_free(space_map::ptr sm) {
open(void *root) { ASSERT_THAT(sm->get_nr_free(), Eq(NR_BLOCKS));
transaction_manager::ptr tm = create_tm();
return persistent_data::open_metadata_sm(tm, root); for (unsigned i = 0; i < NR_BLOCKS; i++) {
boost::optional<block_address> mb = sm->new_block();
ASSERT_TRUE(mb);
ASSERT_THAT(sm->get_nr_free(), Eq(NR_BLOCKS - i - 1));
}
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->dec(i);
ASSERT_THAT(sm->get_nr_free(), Eq(i + 1));
}
} }
};
//-------------------------------- void test_runs_out_of_space(space_map::ptr sm) {
boost::optional<block_address> mb;
void test_get_nr_blocks(space_map::ptr sm) for (unsigned i = 0; i < NR_BLOCKS; i++)
{ mb = sm->new_block();
ASSERT_THAT(sm->get_nr_blocks(), Eq(NR_BLOCKS));
}
void test_get_nr_free(space_map::ptr sm) mb = sm->new_block();
{ ASSERT_FALSE(mb);
ASSERT_THAT(sm->get_nr_free(), Eq(NR_BLOCKS)); }
for (unsigned i = 0; i < NR_BLOCKS; i++) { void test_inc_and_dec(space_map::ptr sm) {
block_address b = 63;
for (unsigned i = 0; i < 50; i++) {
ASSERT_THAT(sm->get_count(b), Eq(i));
sm->inc(b);
}
for (unsigned i = 50; i > 0; i--) {
ASSERT_THAT(sm->get_count(b), Eq(i));
sm->dec(b);
}
}
void test_not_allocated_twice(space_map::ptr sm) {
boost::optional<block_address> mb = sm->new_block(); boost::optional<block_address> mb = sm->new_block();
ASSERT_TRUE(mb); ASSERT_TRUE(mb);
ASSERT_THAT(sm->get_nr_free(), Eq(NR_BLOCKS - i - 1));
for (;;) {
boost::optional<block_address> b = sm->new_block();
if (!b)
break;
if (b)
ASSERT_TRUE(*b != *mb);
}
} }
for (unsigned i = 0; i < NR_BLOCKS; i++) { void test_set_count(space_map::ptr sm) {
sm->dec(i); sm->set_count(43, 5);
ASSERT_THAT(sm->get_nr_free(), Eq(i + 1)); ASSERT_THAT(sm->get_count(43), Eq(5u));
}
}
void test_runs_out_of_space(space_map::ptr sm)
{
boost::optional<block_address> mb;
for (unsigned i = 0; i < NR_BLOCKS; i++)
mb = sm->new_block();
mb = sm->new_block();
ASSERT_FALSE(mb);
}
void test_inc_and_dec(space_map::ptr sm)
{
block_address b = 63;
for (unsigned i = 0; i < 50; i++) {
ASSERT_THAT(sm->get_count(b), Eq(i));
sm->inc(b);
} }
for (unsigned i = 50; i > 0; i--) { void test_set_affects_nr_allocated(space_map::ptr sm) {
ASSERT_THAT(sm->get_count(b), Eq(i)); for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->dec(b); sm->set_count(i, 1);
} ASSERT_THAT(sm->get_nr_free(), Eq(NR_BLOCKS - i - 1));
} }
void test_not_allocated_twice(space_map::ptr sm) for (unsigned i = 0; i < NR_BLOCKS; i++) {
{ sm->set_count(i, 0);
boost::optional<block_address> mb = sm->new_block(); ASSERT_THAT(sm->get_nr_free(), Eq(i + 1));
ASSERT_TRUE(mb); }
for (;;) {
boost::optional<block_address> b = sm->new_block();
if (!b)
break;
if (b)
ASSERT_TRUE(*b != *mb);
}
}
void test_set_count(space_map::ptr sm)
{
sm->set_count(43, 5);
ASSERT_THAT(sm->get_count(43), Eq(5u));
}
void test_set_affects_nr_allocated(space_map::ptr sm)
{
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->set_count(i, 1);
ASSERT_THAT(sm->get_nr_free(), Eq(NR_BLOCKS - i - 1));
} }
for (unsigned i = 0; i < NR_BLOCKS; i++) { // Ref counts below 3 gets stored as bitmaps, above 3 they go into
sm->set_count(i, 0); // a btree with uint32_t values. Worth checking this thoroughly,
ASSERT_THAT(sm->get_nr_free(), Eq(i + 1)); // especially for the metadata format which may have complications
} // due to recursion.
} void test_high_ref_counts(space_map::ptr sm) {
srand(1234);
// Ref counts below 3 gets stored as bitmaps, above 3 they go into for (unsigned i = 0; i < NR_BLOCKS; i++)
// a btree with uint32_t values. Worth checking this thoroughly, sm->set_count(i, rand() % 6789);
// especially for the metadata format which may have complications
// due to recursion.
void test_high_ref_counts(space_map::ptr sm)
{
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
sm->set_count(i, rand() % 6789);
sm->commit();
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->inc(i);
sm->inc(i);
if (i % 1000)
sm->commit();
}
sm->commit();
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
ASSERT_THAT(sm->get_count(i), Eq((rand() % 6789u) + 2u));
for (unsigned i = 0; i < NR_BLOCKS; i++)
sm->dec(i);
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
ASSERT_THAT(sm->get_count(i), Eq((rand() % 6789u) + 1u));
}
template <typename SMCreator>
void test_sm_reopen()
{
unsigned char buffer[128];
{
persistent_space_map::ptr sm = SMCreator::create();
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++)
sm->inc(i);
sm->commit(); sm->commit();
ASSERT_THAT(sm->root_size(), Le(sizeof(buffer))); for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->copy_root(buffer, sizeof(buffer)); sm->inc(i);
sm->inc(i);
if (i % 1000)
sm->commit();
}
sm->commit();
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
ASSERT_THAT(sm->get_count(i), Eq((rand() % 6789u) + 2u));
for (unsigned i = 0; i < NR_BLOCKS; i++)
sm->dec(i);
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
ASSERT_THAT(sm->get_count(i), Eq((rand() % 6789u) + 1u));
} }
{ template <typename SMCreator>
persistent_space_map::ptr sm = SMCreator::open(buffer); void test_sm_reopen() {
unsigned char buffer[128];
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++) {
ASSERT_THAT(sm->get_count(i), Eq(1u)); persistent_space_map::ptr sm = SMCreator::create(tm_);
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++)
sm->inc(i);
sm->commit();
ASSERT_THAT(sm->root_size(), Le(sizeof(buffer)));
sm->copy_root(buffer, sizeof(buffer));
}
{
persistent_space_map::ptr sm = SMCreator::open(tm_, buffer);
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++)
ASSERT_THAT(sm->get_count(i), Eq(1u));
}
} }
}
typedef void (*sm_test)(space_map::ptr); template <typename SMCreator>
void do_tests() {
template <typename SMCreator, unsigned NTests> test_get_nr_blocks(SMCreator::create(tm_));
void do_tests(sm_test (&tests)[NTests]) test_get_nr_free(SMCreator::create(tm_));
{ test_runs_out_of_space(SMCreator::create(tm_));
for (unsigned t = 0; t < NTests; t++) { test_inc_and_dec(SMCreator::create(tm_));
space_map::ptr sm = SMCreator::create(); test_not_allocated_twice(SMCreator::create(tm_));
tests[t](sm); test_set_count(SMCreator::create(tm_));
test_set_affects_nr_allocated(SMCreator::create(tm_));
test_high_ref_counts(SMCreator::create(tm_));
} }
}
sm_test space_map_tests[] = { void
test_get_nr_blocks, copy_space_maps(space_map::ptr lhs, space_map::ptr rhs) {
test_get_nr_free, for (block_address b = 0; b < rhs->get_nr_blocks(); b++) {
test_runs_out_of_space, uint32_t count = rhs->get_count(b);
test_inc_and_dec, if (count > 0)
test_not_allocated_twice, lhs->set_count(b, rhs->get_count(b));
test_set_count, }
test_set_affects_nr_allocated, }
test_high_ref_counts
block_manager<>::ptr bm_;
space_map::ptr sm_;
transaction_manager tm_;
}; };
void
copy_space_maps(space_map::ptr lhs, space_map::ptr rhs) {
for (block_address b = 0; b < rhs->get_nr_blocks(); b++) {
uint32_t count = rhs->get_count(b);
if (count > 0)
lhs->set_count(b, rhs->get_count(b));
}
}
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
TEST(SpaceMapTests, test_sm_core) TEST_F(SpaceMapTests, test_sm_core)
{ {
do_tests<sm_core_creator>(space_map_tests); do_tests<sm_core_creator>();
} }
TEST(SpaceMapTests, test_sm_careful_alloc) TEST_F(SpaceMapTests, test_sm_careful_alloc)
{ {
do_tests<sm_careful_alloc_creator>(space_map_tests); do_tests<sm_careful_alloc_creator>();
} }
TEST(SpaceMapTests, test_sm_recursive) TEST_F(SpaceMapTests, test_sm_recursive)
{ {
do_tests<sm_recursive_creator>(space_map_tests); do_tests<sm_recursive_creator>();
} }
TEST(SpaceMapTests, test_sm_disk) TEST_F(SpaceMapTests, test_sm_disk)
{ {
do_tests<sm_disk_creator>(space_map_tests); do_tests<sm_disk_creator>();
test_sm_reopen<sm_disk_creator>(); test_sm_reopen<sm_disk_creator>();
} }
TEST(SpaceMapTests, test_sm_metadata) TEST_F(SpaceMapTests, test_sm_metadata)
{ {
do_tests<sm_metadata_creator>(space_map_tests); do_tests<sm_metadata_creator>();
test_sm_reopen<sm_metadata_creator>(); test_sm_reopen<sm_metadata_creator>();
} }
TEST(SpaceMapTests, test_metadata_and_disk) TEST_F(SpaceMapTests, test_metadata_and_disk)
{ {
block_manager<>::ptr bm( block_manager<>::ptr bm(
new block_manager<>("./test.data", NR_BLOCKS, MAX_LOCKS, block_manager<>::READ_WRITE)); new block_manager<>("./test.data", NR_BLOCKS, MAX_LOCKS, block_manager<>::READ_WRITE));
space_map::ptr core_sm(new core_map(NR_BLOCKS)); space_map::ptr core_sm(new core_map(NR_BLOCKS));
transaction_manager::ptr tm(new transaction_manager(bm, core_sm)); transaction_manager::ptr tm(new transaction_manager(bm, core_sm));
persistent_space_map::ptr metadata_sm = persistent_data::create_metadata_sm(tm, NR_BLOCKS); persistent_space_map::ptr metadata_sm = persistent_data::create_metadata_sm(*tm, NR_BLOCKS);
copy_space_maps(metadata_sm, core_sm); copy_space_maps(metadata_sm, core_sm);
tm->set_sm(metadata_sm); tm->set_sm(metadata_sm);
persistent_space_map::ptr data_sm_ = create_disk_sm(tm, NR_BLOCKS * 2); persistent_space_map::ptr data_sm_ = create_disk_sm(*tm, NR_BLOCKS * 2);
} }
//---------------------------------------------------------------- //----------------------------------------------------------------