btree_damage_tracker
This commit is contained in:
parent
42a4221499
commit
08c5fde04f
@ -30,6 +30,68 @@ namespace persistent_data {
|
|||||||
range<uint64_t> lost_keys_;
|
range<uint64_t> lost_keys_;
|
||||||
std::string desc_;
|
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),
|
: counter_(counter),
|
||||||
avoid_repeated_visits_(true),
|
avoid_repeated_visits_(true),
|
||||||
value_visitor_(value_visitor),
|
value_visitor_(value_visitor),
|
||||||
damage_visitor_(damage_visitor) {
|
damage_visitor_(damage_visitor),
|
||||||
|
key_end_(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool visit_internal(node_location const &loc,
|
bool visit_internal(node_location const &loc,
|
||||||
@ -121,6 +184,8 @@ namespace persistent_data {
|
|||||||
if (loc.sub_root)
|
if (loc.sub_root)
|
||||||
new_root(loc.level);
|
new_root(loc.level);
|
||||||
|
|
||||||
|
update_key_end(n.key_at(n.get_nr_entries() - 1) + 1ull);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +204,11 @@ namespace persistent_data {
|
|||||||
if (loc.sub_root)
|
if (loc.sub_root)
|
||||||
new_root(loc.level);
|
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;
|
return false;
|
||||||
@ -285,19 +354,33 @@ namespace persistent_data {
|
|||||||
last_leaf_key_[level] = boost::optional<uint64_t>();
|
last_leaf_key_[level] = boost::optional<uint64_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_key_end(uint64_t end) {
|
||||||
|
key_end_ = max(end, key_end_);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename node>
|
template <typename node>
|
||||||
void report_damage(node const &n, std::string const &desc) {
|
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);
|
damage d(0, lost_keys, desc);
|
||||||
|
|
||||||
|
cerr << "damage: keys = " << lost_keys << " " << desc << endl;
|
||||||
damage_visitor_.visit(d);
|
damage_visitor_.visit(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
// damage tracking
|
||||||
|
|
||||||
void report_damage(std::string const &desc) {
|
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);
|
damage d(0, lost_keys, desc);
|
||||||
|
|
||||||
|
cerr << "damage: keys = " << lost_keys << " " << desc << endl;
|
||||||
damage_visitor_.visit(d);
|
damage_visitor_.visit(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
block_counter &counter_;
|
block_counter &counter_;
|
||||||
bool avoid_repeated_visits_;
|
bool avoid_repeated_visits_;
|
||||||
|
|
||||||
@ -306,6 +389,8 @@ namespace persistent_data {
|
|||||||
|
|
||||||
std::set<block_address> seen_;
|
std::set<block_address> seen_;
|
||||||
boost::optional<uint64_t> last_leaf_key_[Levels];
|
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