From 29c2831f3e69bcbd02c82d1a5e21655c82d7b120 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Mon, 22 Aug 2011 14:14:10 +0100 Subject: [PATCH] [btree_t] check for duplicate blocks --- btree.h | 9 ++++++++- unit-tests/btree_t.cc | 31 ++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/btree.h b/btree.h index aae571c..02f3b86 100644 --- a/btree.h +++ b/btree.h @@ -70,7 +70,11 @@ namespace persistent_data { template class node_ref { public: - explicit node_ref(disk_node *raw); + explicit node_ref(block_address b, disk_node *raw); + + block_address get_location() const { + return location_; + } node_type get_type() const; void set_type(node_type t); @@ -126,6 +130,7 @@ namespace persistent_data { void *key_ptr(unsigned i) const; void *value_ptr(unsigned i) const; + block_address location_; disk_node *raw_; }; @@ -137,6 +142,7 @@ namespace persistent_data { { // FIXME: this should return a const read_ref somehow. return node_ref( + b.get_location(), reinterpret_cast( const_cast(b.data()))); } @@ -146,6 +152,7 @@ namespace persistent_data { to_node(typename block_manager::write_ref &b) { return node_ref( + b.get_location(), reinterpret_cast( const_cast(b.data()))); } diff --git a/unit-tests/btree_t.cc b/unit-tests/btree_t.cc index fa40eb0..6b28e19 100644 --- a/unit-tests/btree_t.cc +++ b/unit-tests/btree_t.cc @@ -31,19 +31,36 @@ namespace { create_tm(), rc)); } + // Checks that a btree is well formed. + // + // i) No block should be in the tree more than once. + // class constraint_visitor : public btree<1, uint64_traits, 4096>::visitor { - private: + public: void visit_internal(unsigned level, btree_detail::node_ref const &n) { - // cout << "internal: level = " << level << ", nr_entries = " << n.get_nr_entries() << endl; + check_duplicate_block(n.get_location()); } void visit_internal_leaf(unsigned level, btree_detail::node_ref const &n) { - // cout << "internal_leaf !" << endl; + check_duplicate_block(n.get_location()); } void visit_leaf(unsigned level, btree_detail::node_ref const &n) { - // cout << "leaf: level = " << level << ", nr_entries = " << n.get_nr_entries() << endl; + check_duplicate_block(n.get_location()); } + + private: + void check_duplicate_block(block_address b) { + if (seen_.count(b)) { + ostringstream out; + out << "duplicate block in btree: " << b; + throw runtime_error(out.str()); + } + + seen_.insert(b); + } + + set seen_; }; void check_constraints(btree<1, uint64_traits, 4096>::ptr tree) { @@ -59,6 +76,7 @@ namespace { BOOST_AUTO_TEST_CASE(empty_btree_contains_nothing) { auto tree = create_btree(); + check_constraints(tree); for (uint64_t i = 0; i < 1000; i++) { uint64_t key[1] = {i}; @@ -68,18 +86,21 @@ BOOST_AUTO_TEST_CASE(empty_btree_contains_nothing) BOOST_AUTO_TEST_CASE(insert_works) { - unsigned const COUNT = 1000000; + unsigned const COUNT = 100000; auto tree = create_btree(); for (uint64_t i = 0; i < COUNT; i++) { uint64_t key[1] = {i * 7}; uint64_t value = i; + tree->insert(key, value); auto l = tree->lookup(key); BOOST_CHECK(l); BOOST_CHECK_EQUAL(*l, i); } + + check_constraints(tree); } //----------------------------------------------------------------