btree_damage_tracker
This commit is contained in:
parent
42a4221499
commit
08c5fde04f
@ -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_;
|
||||
};
|
||||
}
|
||||
|
||||
|
101
unit-tests/damage_tracker_t.cc
Normal file
101
unit-tests/damage_tracker_t.cc
Normal 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));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
Loading…
Reference in New Issue
Block a user