From f803c44e93ad09d97ceb35790460011da6f7a0ff Mon Sep 17 00:00:00 2001 From: Ming-Hung Tsai Date: Tue, 2 Jun 2020 11:47:38 +0800 Subject: [PATCH] [btree] Implement btree::destroy() to delete the entire tree Also decrease the reference count of the mapped values. (e.g., bitmap blocks of btree_index_store) --- persistent-data/data-structures/btree.h | 3 + persistent-data/data-structures/btree.tcc | 112 +++++++++++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/persistent-data/data-structures/btree.h b/persistent-data/data-structures/btree.h index 3b84df7..c92a484 100644 --- a/persistent-data/data-structures/btree.h +++ b/persistent-data/data-structures/btree.h @@ -124,6 +124,9 @@ namespace persistent_data { template void inc_children(RefCounter &rc); + template + void dec_children(RefCounter &rc); + disk_node *raw() { return raw_; } diff --git a/persistent-data/data-structures/btree.tcc b/persistent-data/data-structures/btree.tcc index b24ec29..0c7ca3d 100644 --- a/persistent-data/data-structures/btree.tcc +++ b/persistent-data/data-structures/btree.tcc @@ -25,6 +25,7 @@ #include #include +#include //---------------------------------------------------------------- @@ -33,6 +34,56 @@ namespace { using namespace persistent_data; using namespace btree_detail; using namespace std; + + struct frame { + frame(block_address blocknr, + uint32_t level, + uint32_t nr_entries) + : blocknr_(blocknr), + level_(level), + nr_entries_(nr_entries), + current_child_(0) { + } + block_address blocknr_; + uint32_t level_; + uint32_t nr_entries_; + uint32_t current_child_; + }; + + // stack for postorder DFS traversal + // TODO: Refactor it into a spine-like class, e.g., btree_del_spine, + // "Spine" sounds better for btree operations. + struct btree_del_stack { + public: + btree_del_stack(transaction_manager &tm): tm_(tm) { + } + + void push_frame(block_address blocknr, + uint32_t level, + uint32_t nr_entries) { + if (tm_.get_sm()->get_count(blocknr) > 1) + tm_.get_sm()->dec(blocknr); + else + spine_.push(frame(blocknr, level, nr_entries)); + } + + void pop_frame() { + tm_.get_sm()->dec(spine_.top().blocknr_); + spine_.pop(); + } + + frame &top_frame() { + return spine_.top(); + } + + bool is_empty() { + return spine_.empty(); + } + + private: + transaction_manager &tm_; + std::stack spine_; + }; } //---------------------------------------------------------------- @@ -348,6 +399,21 @@ namespace persistent_data { } } + template + template + void + node_ref::dec_children(RefCounter &rc) + { + unsigned nr_entries = get_nr_entries(); + for (unsigned i = 0; i < nr_entries; i++) { + typename ValueTraits::value_type v; + typename ValueTraits::disk_type d; + ::memcpy(&d, value_ptr(i), sizeof(d)); + ValueTraits::unpack(d, v); + rc.dec(v); + } + } + template bool node_ref::value_sizes_match() const { @@ -565,15 +631,57 @@ namespace persistent_data { return ptr(new btree(tm_, root_, rc_)); } -#if 0 template void btree::destroy() { using namespace btree_detail; + btree_del_stack s(tm_); + + { + read_ref blk = tm_.read_lock(root_, validator_); + internal_node n = to_node(blk); + s.push_frame(root_, 0, n.get_nr_entries()); + } + + while (!s.is_empty()) { + frame &f = s.top_frame(); + + if (f.current_child_ >= f.nr_entries_) { + s.pop_frame(); + continue; + } + + // FIXME: Cache the read_ref object in the stack to avoid temporary objects? + read_ref current = tm_.read_lock(f.blocknr_, validator_); + internal_node n = to_node(current); + + if (n.get_type() == INTERNAL) { + // TODO: test performance penalty of prefetching + //if (!f.current_child_) + // for (unsigned i = 0; i < n.get_nr_entries(); i++) + // tm_.prefetch(n.value_at(i)); + + block_address b = n.value_at(f.current_child_); + read_ref leaf = tm_.read_lock(b, validator_); + internal_node o = to_node(leaf); + s.push_frame(b, f.level_, o.get_nr_entries()); + ++f.current_child_; + // internal leaf + } else if (f.level_ < Levels - 1) { + block_address b = n.value_at(f.current_child_); + read_ref leaf = tm_.read_lock(b, validator_); + internal_node o = to_node(leaf); + s.push_frame(b, f.level_ + 1, o.get_nr_entries()); + ++f.current_child_; + } else { + leaf_node o = to_node(current); + o.dec_children(rc_); // FIXME: move this into pop_frame() + s.pop_frame(); + } + } } -#endif template template