More work on metadata_checker_t

This commit is contained in:
Joe Thornber 2013-05-01 16:33:42 +01:00
parent 647cb68b76
commit 3832fd5952

View File

@ -101,7 +101,8 @@ namespace {
metadata::ptr md(new metadata(bm_, metadata::CREATE, 128, 10240)); metadata::ptr md(new metadata(bm_, metadata::CREATE, 128, 10240));
emitter::ptr restorer = create_restore_emitter(md); emitter::ptr restorer = create_restore_emitter(md);
restorer->begin_superblock("test-generated", 0, 0, 128, 10240, boost::optional<uint64_t>()); restorer->begin_superblock("test-generated", 0, 0, 128, 10240,
boost::optional<uint64_t>());
list<uint32_t>::const_iterator it, end = devices_.end(); list<uint32_t>::const_iterator it, end = devices_.end();
for (it = devices_.begin(); it != end; ++it) { for (it = devices_.begin(); it != end; ++it) {
@ -122,6 +123,70 @@ namespace {
list<uint32_t> devices_; list<uint32_t> devices_;
}; };
class devices_visitor : public detail_tree::visitor {
public:
struct node_info {
bool leaf;
unsigned level;
block_address b;
range<uint64_t> keys;
};
typedef btree_detail::node_location node_location;
typedef boost::shared_ptr<devices_visitor> ptr;
virtual bool visit_internal(node_location const &loc,
detail_tree::internal_node const &n) {
record_node(false, loc.level, loc.key, n);
return true;
}
virtual bool visit_internal_leaf(node_location const &loc,
detail_tree::internal_node const &n) {
record_node(true, loc.level, loc.key, n);
return true;
}
virtual bool visit_leaf(node_location const &loc,
detail_tree::leaf_node const &n) {
record_node(true, loc.level, loc.key, n);
return true;
}
virtual void visit_complete() {
}
list<node_info> const &get_nodes() const {
return nodes_;
}
private:
template <typename N>
void record_node(bool leaf, unsigned level,
boost::optional<uint64_t> key,
N const &n) {
node_info ni;
ni.leaf = leaf;
ni.level = level;
ni.b = n.get_location();
if (n.get_nr_entries())
ni.keys = range<uint64_t>(n.key_at(0));
else {
if (key)
ni.keys = range<uint64_t>(*key);
else
ni.keys = range<uint64_t>();
}
nodes_.push_back(ni);
}
list<node_info> nodes_;
};
//-------------------------------- //--------------------------------
class damage_visitor_mock : public metadata_damage_visitor { class damage_visitor_mock : public metadata_damage_visitor {
@ -141,7 +206,7 @@ namespace {
class MetadataCheckerTests : public Test { class MetadataCheckerTests : public Test {
public: public:
MetadataCheckerTests() MetadataCheckerTests()
: bm_(create_bm<BLOCK_SIZE>()), : bm_(create_bm<BLOCK_SIZE>(NR_BLOCKS)),
builder_(bm_) { builder_(bm_) {
} }
@ -264,4 +329,28 @@ TEST_F(DeviceCheckerTests, fails_with_corrupt_root)
(*damage->begin())->visit(v); (*damage->begin())->visit(v);
} }
TEST_F(DeviceCheckerTests, damaging_some_btree_nodes_results_in_the_correct_devices_being_flagged_as_missing)
{
metadata_builder &b = get_builder();
for (unsigned i = 0; i < 1000; i++)
b.add_device(i);
b.build();
devices_visitor::ptr scanner(new devices_visitor);
transaction_manager::ptr tm = open_temporary_tm(bm_);
detail_tree::ptr devices(new detail_tree(tm, devices_root(),
device_details_traits::ref_counter()));
devices->visit_depth_first(scanner);
list<devices_visitor::node_info>::const_iterator it, end = scanner->get_nodes().end();
for (it = scanner->get_nodes().begin(); it != end; ++it) {
cerr << "block " << it->b << ", keys" << it->keys << endl;
}
damage_list_ptr damage = mk_checker()->check();
ASSERT_THAT(damage->size(), Eq(1u));
}
//---------------------------------------------------------------- //----------------------------------------------------------------