btree_damage_tracker

This commit is contained in:
Joe Thornber 2013-05-13 11:27:38 +01:00
parent 42a4221499
commit 08c5fde04f
2 changed files with 190 additions and 4 deletions

View File

@ -30,6 +30,68 @@ namespace persistent_data {
range<uint64_t> lost_keys_;
std::string desc_;
};
class damage_tracker {
public:
damage_tracker()
: damaged_(false),
damage_begin_(0) {
}
typedef range<block_address> range64;
typedef boost::optional<range64> maybe_range64;
void bad_node() {
damaged_ = true;
}
maybe_range64 good_internal(block_address begin) {
maybe_range64 r;
if (damaged_) {
r = maybe_range64(range64(damage_begin_, begin));
damaged_ = false;
}
damage_begin_ = begin;
return r;
}
// remembe 'end' is the one-past-the-end value, so
// take the last key in the leaf and add one.
maybe_range64 good_leaf(block_address begin, block_address end) {
maybe_range64 r;
if (damaged_) {
r = maybe_range64(range64(damage_begin_, begin));
damaged_ = false;
}
damage_begin_ = end;
return r;
}
maybe_range64 end() {
if (damaged_)
return maybe_range64(damage_begin_);
else
return maybe_range64();
}
private:
bool damaged_;
block_address damage_begin_;
};
inline
std::ostream &operator <<(std::ostream &out, damage_tracker::maybe_range64 const &mr) {
if (mr)
out << "Just " << *mr;
else
out << "Nothing";
return out;
}
}
//----------------------------------------------------------------
@ -68,7 +130,8 @@ namespace persistent_data {
: counter_(counter),
avoid_repeated_visits_(true),
value_visitor_(value_visitor),
damage_visitor_(damage_visitor) {
damage_visitor_(damage_visitor),
key_end_(0) {
}
bool visit_internal(node_location const &loc,
@ -121,6 +184,8 @@ namespace persistent_data {
if (loc.sub_root)
new_root(loc.level);
update_key_end(n.key_at(n.get_nr_entries() - 1) + 1ull);
return true;
}
@ -139,7 +204,11 @@ namespace persistent_data {
if (loc.sub_root)
new_root(loc.level);
return check_leaf_key(loc.level, n);
bool r = check_leaf_key(loc.level, n);
if (r)
update_key_end(n.key_at(n.get_nr_entries() - 1) + 1ull);
return r;
}
return false;
@ -285,19 +354,33 @@ namespace persistent_data {
last_leaf_key_[level] = boost::optional<uint64_t>();
}
void update_key_end(uint64_t end) {
key_end_ = max(end, key_end_);
}
template <typename node>
void report_damage(node const &n, std::string const &desc) {
range<uint64_t> lost_keys;
range<uint64_t> lost_keys(key_end_);
damage d(0, lost_keys, desc);
cerr << "damage: keys = " << lost_keys << " " << desc << endl;
damage_visitor_.visit(d);
}
//--------------------------------
// damage tracking
void report_damage(std::string const &desc) {
range<uint64_t> lost_keys;
range<uint64_t> lost_keys(key_end_);
damage d(0, lost_keys, desc);
cerr << "damage: keys = " << lost_keys << " " << desc << endl;
damage_visitor_.visit(d);
}
//--------------------------------
block_counter &counter_;
bool avoid_repeated_visits_;
@ -306,6 +389,8 @@ namespace persistent_data {
std::set<block_address> seen_;
boost::optional<uint64_t> last_leaf_key_[Levels];
uint64_t key_end_;
};
}

View File

@ -0,0 +1,101 @@
#include "gmock/gmock.h"
#include "test_utils.h"
#include "persistent-data/data-structures/btree_damage_visitor.h"
using namespace std;
using namespace persistent_data;
using namespace test;
using namespace testing;
//----------------------------------------------------------------
namespace {
typedef range<block_address> range64;
typedef damage_tracker::maybe_range64 mr64;
class DamageTrackerTests : public Test {
public:
void assert_no_damage(mr64 const &mr) const {
ASSERT_THAT(mr, Eq(mr64()));
}
void assert_damage(mr64 const &mr, range64 const &expected) const {
ASSERT_THAT(mr, Eq(mr64(expected)));
}
damage_tracker dt;
};
};
//----------------------------------------------------------------
TEST_F(DamageTrackerTests, good_leaf)
{
assert_no_damage(dt.good_leaf(0, 10));
assert_no_damage(dt.end());
}
TEST_F(DamageTrackerTests, bad_node)
{
dt.bad_node();
assert_damage(dt.end(), range64(0ull));
}
TEST_F(DamageTrackerTests, good_bad)
{
dt.good_leaf(0, 10);
dt.bad_node();
assert_damage(dt.end(), range64(10ull));
}
TEST_F(DamageTrackerTests, bad_good)
{
dt.bad_node();
assert_damage(dt.good_leaf(10, 20), range64(0ull, 10ull));
}
TEST_F(DamageTrackerTests, good_bad_good)
{
dt.good_leaf(0, 10);
dt.bad_node();
assert_damage(dt.good_leaf(20, 30), range64(10ull, 20ull));
assert_no_damage(dt.end());
}
TEST_F(DamageTrackerTests, bad_good_bad)
{
dt.bad_node();
dt.good_leaf(10, 20);
dt.bad_node();
assert_damage(dt.end(), range64(20ull));
}
TEST_F(DamageTrackerTests, gi_bl_gl)
{
dt.good_internal(0);
dt.bad_node();
assert_damage(dt.good_leaf(10, 20), range64(0ull, 10ull));
assert_no_damage(dt.end());
}
TEST_F(DamageTrackerTests, gi_gl_bl_bi)
{
dt.good_internal(0);
dt.good_leaf(0, 10);
dt.bad_node();
dt.bad_node();
assert_damage(dt.end(), range64(10ull));
}
TEST_F(DamageTrackerTests, gi_bi_gi_bl_gl)
{
dt.good_internal(0);
dt.bad_node();
assert_damage(dt.good_internal(10), range64(0ull, 10ull));
dt.bad_node();
assert_damage(dt.good_leaf(15, 20), range64(10ull, 15ull));
}
//----------------------------------------------------------------