From 83a09e1a2a4f5fa9fd1316237c70957c666aba89 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Thu, 20 Jun 2013 14:27:40 +0100 Subject: [PATCH] [btree] use a block_ref_counter for internal nodes --- Makefile.in | 2 ++ persistent-data/data-structures/btree.cc | 28 +++++++++++++++ persistent-data/data-structures/btree.h | 36 ++++++++++++++++--- persistent-data/data-structures/btree.tcc | 27 +++++++------- .../data-structures/btree_checker.h | 6 ++-- .../data-structures/btree_damage_visitor.h | 6 ++-- thin-provisioning/metadata_dumper.cc | 8 ++--- unit-tests/btree_t.cc | 2 +- 8 files changed, 88 insertions(+), 27 deletions(-) create mode 100644 persistent-data/data-structures/btree.cc diff --git a/Makefile.in b/Makefile.in index 4d1b3df..f8d233a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -38,6 +38,8 @@ PDATA_SOURCE=\ persistent-data/lock_tracker.cc \ persistent-data/transaction_manager.cc \ \ + persistent-data/data-structures/btree.cc \ + \ persistent-data/space_map.cc \ persistent-data/space-maps/disk.cc \ persistent-data/space-maps/recursive.cc \ diff --git a/persistent-data/data-structures/btree.cc b/persistent-data/data-structures/btree.cc new file mode 100644 index 0000000..0421bdc --- /dev/null +++ b/persistent-data/data-structures/btree.cc @@ -0,0 +1,28 @@ +#include "persistent-data/data-structures/btree.h" + +using namespace persistent_data; + +//---------------------------------------------------------------- + +block_ref_counter::block_ref_counter(space_map::ptr sm) + : sm_(sm) { +} + +void +block_ref_counter::set(block_address const &b, uint32_t rc) { + sm_->set_count(b, rc); +} + +void +block_ref_counter::inc(block_address const &b) { + sm_->inc(b); +} + +void +block_ref_counter::dec(block_address const &b) { + sm_->dec(b); +} + +//---------------------------------------------------------------- + + diff --git a/persistent-data/data-structures/btree.h b/persistent-data/data-structures/btree.h index 683aee2..8582ad6 100644 --- a/persistent-data/data-structures/btree.h +++ b/persistent-data/data-structures/btree.h @@ -31,6 +31,20 @@ //---------------------------------------------------------------- namespace persistent_data { + class block_ref_counter : public ref_counter { + public: + block_ref_counter(space_map::ptr sm); + + virtual void set(block_address const &v, uint32_t rc); + virtual void inc(block_address const &v); + virtual void dec(block_address const &v); + + private: + space_map::ptr sm_; + }; + + // FIXME: move to sep file. I don't think it's directly used by + // the btree code. struct uint64_traits { typedef base::le64 disk_type; typedef uint64_t value_type; @@ -45,6 +59,20 @@ namespace persistent_data { } }; + struct block_traits { + typedef base::le64 disk_type; + typedef block_address value_type; + typedef block_ref_counter ref_counter; + + static void unpack(disk_type const &disk, value_type &value) { + value = base::to_cpu(disk); + } + + static void pack(value_type const &value, disk_type &disk) { + disk = base::to_disk(value); + } + }; + namespace btree_detail { using namespace base; using namespace std; @@ -243,11 +271,11 @@ namespace persistent_data { return spine_.size() > 1; } - node_ref get_parent() { + node_ref get_parent() { if (spine_.size() < 2) throw std::runtime_error("no parent"); - return to_node(spine_.front()); + return to_node(spine_.front()); } block_address get_parent_location() const { @@ -316,7 +344,7 @@ namespace persistent_data { typedef typename block_manager<>::read_ref read_ref; typedef typename block_manager<>::write_ref write_ref; typedef typename btree_detail::node_ref leaf_node; - typedef typename btree_detail::node_ref internal_node; + typedef typename btree_detail::node_ref internal_node; btree(typename persistent_data::transaction_manager::ptr tm, typename ValueTraits::ref_counter rc); @@ -420,7 +448,7 @@ namespace persistent_data { typename persistent_data::transaction_manager::ptr tm_; bool destroy_; block_address root_; - no_op_ref_counter internal_rc_; + block_ref_counter internal_rc_; typename ValueTraits::ref_counter rc_; typename block_manager<>::validator::ptr validator_; }; diff --git a/persistent-data/data-structures/btree.tcc b/persistent-data/data-structures/btree.tcc index 422d2b9..1655bbb 100644 --- a/persistent-data/data-structures/btree.tcc +++ b/persistent-data/data-structures/btree.tcc @@ -60,6 +60,7 @@ namespace { //---------------------------------------------------------------- namespace persistent_data { + inline void ro_spine::step(block_address b) { @@ -356,7 +357,7 @@ namespace persistent_data { } } -//---------------------------------------------------------------- + //-------------------------------- template btree:: @@ -364,6 +365,7 @@ namespace persistent_data { typename ValueTraits::ref_counter rc) : tm_(tm), destroy_(false), + internal_rc_(tm->get_sm()), rc_(rc), validator_(new btree_node_validator) { @@ -388,6 +390,7 @@ namespace persistent_data { : tm_(tm), destroy_(false), root_(root), + internal_rc_(tm->get_sm()), rc_(rc), validator_(new btree_node_validator) { @@ -426,7 +429,7 @@ namespace persistent_data { for (unsigned level = 0; level < Levels - 1; ++level) { optional mroot = - lookup_raw >(spine, root, key[level]); + lookup_raw >(spine, root, key[level]); if (!mroot) return maybe_value(); @@ -467,9 +470,9 @@ namespace persistent_data { shadow_spine spine(tm_, validator_); for (unsigned level = 0; level < Levels - 1; ++level) { - bool need_insert = insert_location(spine, block, key[level], &index, internal_rc_); + bool need_insert = insert_location(spine, block, key[level], &index, internal_rc_); - internal_node n = spine.template get_node(); + internal_node n = spine.template get_node(); if (need_insert) { btree new_tree(tm_, rc_); n.insert_at(index, key[level], new_tree.get_root()); @@ -556,7 +559,7 @@ namespace persistent_data { if (!mi || *mi < 0) return optional(); - node_ref internal = spine.template get_node(); + node_ref internal = spine.template get_node(); block = internal.value_at(*mi); } } @@ -623,11 +626,11 @@ namespace persistent_data { { // The parent may have changed value type, so we re-get it. - internal_node p = spine.template get_node(); + internal_node p = spine.template get_node(); p.set_type(btree_detail::INTERNAL); p.set_max_entries(); p.set_nr_entries(2); - p.set_value_size(sizeof(typename uint64_traits::disk_type)); + p.set_value_size(sizeof(typename block_traits::disk_type)); p.overwrite_at(0, l.key_at(0), left.get_location()); p.overwrite_at(1, r.key_at(0), right.get_location()); @@ -703,15 +706,15 @@ namespace persistent_data { p.set_value(i, spine.get_block()); } - internal_node internal = spine.template get_node(); + internal_node internal = spine.template get_node(); // Split the node if we're full if (internal.get_type() == INTERNAL) - split_node(spine, i, key, top); + split_node(spine, i, key, top); else split_node(spine, i, key, top); - internal = spine.template get_node(); + internal = spine.template get_node(); i = internal.lower_bound(key); if (internal.get_type() == btree_detail::LEAF) break; @@ -780,7 +783,7 @@ namespace persistent_data { using namespace btree_detail; read_ref blk = tm_->read_lock(b, validator_); - internal_node o = to_node(blk); + internal_node o = to_node(blk); // FIXME: use a switch statement if (o.get_type() == INTERNAL) { @@ -817,7 +820,7 @@ namespace persistent_data { void btree::inc_children(btree_detail::shadow_spine &spine, RefCounter &leaf_rc) { - node_ref nr = spine.template get_node(); + node_ref nr = spine.template get_node(); if (nr.get_type() == INTERNAL) nr.inc_children(internal_rc_); else { diff --git a/persistent-data/data-structures/btree_checker.h b/persistent-data/data-structures/btree_checker.h index da2cff4..2791da0 100644 --- a/persistent-data/data-structures/btree_checker.h +++ b/persistent-data/data-structures/btree_checker.h @@ -66,12 +66,12 @@ namespace persistent_data { } bool visit_internal(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { return check_internal(loc, n); } bool visit_internal_leaf(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { return check_leaf(loc, n); } @@ -91,7 +91,7 @@ namespace persistent_data { private: bool check_internal(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { if (!already_visited(n) && check_block_nr(n) && check_max_entries(n) && diff --git a/persistent-data/data-structures/btree_damage_visitor.h b/persistent-data/data-structures/btree_damage_visitor.h index 6dda87f..801251b 100644 --- a/persistent-data/data-structures/btree_damage_visitor.h +++ b/persistent-data/data-structures/btree_damage_visitor.h @@ -146,14 +146,14 @@ namespace persistent_data { } bool visit_internal(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { update_path(loc.path); return check_internal(loc, n); } bool visit_internal_leaf(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { update_path(loc.path); return check_leaf(loc, n); @@ -200,7 +200,7 @@ namespace persistent_data { } bool check_internal(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { if (!already_visited(n) && check_block_nr(n) && check_max_entries(n) && diff --git a/thin-provisioning/metadata_dumper.cc b/thin-provisioning/metadata_dumper.cc index 9275ef7..d42e9b7 100644 --- a/thin-provisioning/metadata_dumper.cc +++ b/thin-provisioning/metadata_dumper.cc @@ -44,7 +44,7 @@ namespace { } bool visit_internal(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { if (!checker_.visit_internal(loc, n)) { found_errors_ = true; @@ -55,7 +55,7 @@ namespace { } bool visit_internal_leaf(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { if (!checker_.visit_internal_leaf(loc, n)) { found_errors_ = true; return false; @@ -148,12 +148,12 @@ namespace { } bool visit_internal(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { return checker_.visit_internal(loc, n); } bool visit_internal_leaf(node_location const &loc, - btree_detail::node_ref const &n) { + btree_detail::node_ref const &n) { return checker_.visit_internal_leaf(loc, n); } diff --git a/unit-tests/btree_t.cc b/unit-tests/btree_t.cc index 4f08a82..4eca176 100644 --- a/unit-tests/btree_t.cc +++ b/unit-tests/btree_t.cc @@ -53,7 +53,7 @@ namespace { class constraint_visitor : public btree<1, uint64_traits>::visitor { public: typedef btree_detail::node_location node_location; - typedef btree_detail::node_ref internal_node; + typedef btree_detail::node_ref internal_node; typedef btree_detail::node_ref leaf_node; bool visit_internal(node_location const &loc,