era_check, era_dump
This commit is contained in:
parent
bed0f369a8
commit
9e0540e1b6
41
Makefile.in
41
Makefile.in
@ -26,6 +26,7 @@ PROGRAMS=\
|
|||||||
cache_repair \
|
cache_repair \
|
||||||
\
|
\
|
||||||
era_check \
|
era_check \
|
||||||
|
era_dump \
|
||||||
\
|
\
|
||||||
thin_check \
|
thin_check \
|
||||||
thin_dump \
|
thin_dump \
|
||||||
@ -49,9 +50,13 @@ SOURCE=\
|
|||||||
caching/restore_emitter.cc \
|
caching/restore_emitter.cc \
|
||||||
caching/xml_format.cc \
|
caching/xml_format.cc \
|
||||||
\
|
\
|
||||||
|
era/era_array.cc \
|
||||||
era/era_detail.cc \
|
era/era_detail.cc \
|
||||||
era/superblock.cc \
|
era/superblock.cc \
|
||||||
era/bloom_tree.cc \
|
era/bloom_tree.cc \
|
||||||
|
era/metadata.cc \
|
||||||
|
era/metadata_dump.cc \
|
||||||
|
era/xml_format.cc \
|
||||||
\
|
\
|
||||||
persistent-data/checksum.cc \
|
persistent-data/checksum.cc \
|
||||||
persistent-data/error_set.cc \
|
persistent-data/error_set.cc \
|
||||||
@ -301,8 +306,10 @@ ERA_CHECK_SOURCE=\
|
|||||||
base/endian_utils.cc \
|
base/endian_utils.cc \
|
||||||
\
|
\
|
||||||
era/bloom_tree.cc \
|
era/bloom_tree.cc \
|
||||||
era/superblock.cc \
|
|
||||||
era/era_detail.cc \
|
era/era_detail.cc \
|
||||||
|
era/era_array.cc \
|
||||||
|
era/metadata.cc \
|
||||||
|
era/superblock.cc \
|
||||||
\
|
\
|
||||||
persistent-data/checksum.cc \
|
persistent-data/checksum.cc \
|
||||||
persistent-data/error_set.cc \
|
persistent-data/error_set.cc \
|
||||||
@ -323,6 +330,38 @@ era_check: $(ERA_CHECK_OBJECTS) era/era_check.o
|
|||||||
@echo " [LD] $@"
|
@echo " [LD] $@"
|
||||||
$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)
|
$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)
|
||||||
|
|
||||||
|
ERA_DUMP_SOURCE=\
|
||||||
|
base/base64.cc \
|
||||||
|
base/error_state.cc \
|
||||||
|
base/endian_utils.cc \
|
||||||
|
\
|
||||||
|
era/bloom_tree.cc \
|
||||||
|
era/era_detail.cc \
|
||||||
|
era/era_array.cc \
|
||||||
|
era/metadata.cc \
|
||||||
|
era/metadata_dump.cc \
|
||||||
|
era/superblock.cc \
|
||||||
|
era/xml_format.cc \
|
||||||
|
\
|
||||||
|
persistent-data/checksum.cc \
|
||||||
|
persistent-data/error_set.cc \
|
||||||
|
persistent-data/file_utils.cc \
|
||||||
|
persistent-data/hex_dump.cc \
|
||||||
|
persistent-data/lock_tracker.cc \
|
||||||
|
persistent-data/data-structures/btree.cc \
|
||||||
|
persistent-data/data-structures/bitset.cc \
|
||||||
|
persistent-data/space_map.cc \
|
||||||
|
persistent-data/space-maps/disk.cc \
|
||||||
|
persistent-data/space-maps/recursive.cc \
|
||||||
|
persistent-data/space-maps/careful_alloc.cc \
|
||||||
|
persistent-data/transaction_manager.cc \
|
||||||
|
|
||||||
|
ERA_DUMP_OBJECTS=$(subst .cc,.o,$(ERA_DUMP_SOURCE))
|
||||||
|
|
||||||
|
era_dump: $(ERA_DUMP_OBJECTS) era/era_dump.o
|
||||||
|
@echo " [LD] $@"
|
||||||
|
$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
|
||||||
|
|
||||||
#----------------------------------------------------------------
|
#----------------------------------------------------------------
|
||||||
|
|
||||||
DEPEND_FILES=\
|
DEPEND_FILES=\
|
||||||
|
@ -15,7 +15,7 @@ namespace {
|
|||||||
|
|
||||||
void raise_metadata_damage() {
|
void raise_metadata_damage() {
|
||||||
throw std::runtime_error("metadata contains errors (run cache_check for details).\n"
|
throw std::runtime_error("metadata contains errors (run cache_check for details).\n"
|
||||||
"perhaps you wanted to run with --repair");
|
"perhaps you wanted to run with --repair ?");
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------
|
//--------------------------------
|
||||||
|
@ -55,11 +55,13 @@ namespace {
|
|||||||
void visit(btree_path const &path, era_detail const &era) {
|
void visit(btree_path const &path, era_detail const &era) {
|
||||||
era_ = path[0];
|
era_ = path[0];
|
||||||
bitset bs(tm_, era.bloom_root, era.nr_bits);
|
bitset bs(tm_, era.bloom_root, era.nr_bits);
|
||||||
|
bloom_v_.bloom_begin(era_, era.nr_blocks, era.nr_bits, era.nr_set);
|
||||||
bs.walk_bitset(*this);
|
bs.walk_bitset(*this);
|
||||||
|
bloom_v_.bloom_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(uint32_t index, bool value) {
|
void visit(uint32_t index, bool value) {
|
||||||
bloom_v_.visit(index, value);
|
bloom_v_.bit(index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(bitset_detail::missing_bits const &d) {
|
void visit(bitset_detail::missing_bits const &d) {
|
||||||
@ -109,7 +111,14 @@ era::walk_bloom_tree(persistent_data::transaction_manager::ptr tm,
|
|||||||
namespace {
|
namespace {
|
||||||
class noop_bloom_visitor : public bloom_tree_detail::bloom_visitor {
|
class noop_bloom_visitor : public bloom_tree_detail::bloom_visitor {
|
||||||
public:
|
public:
|
||||||
void visit(uint32_t index, bool value) {
|
void bloom_begin(uint32_t era, uint32_t nr_blocks,
|
||||||
|
uint32_t nr_bits, uint32_t nr_set) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void bit(uint32_t index, bool value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void bloom_end() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -63,7 +63,11 @@ namespace era {
|
|||||||
typedef boost::shared_ptr<bloom_visitor> ptr;
|
typedef boost::shared_ptr<bloom_visitor> ptr;
|
||||||
|
|
||||||
virtual ~bloom_visitor() {}
|
virtual ~bloom_visitor() {}
|
||||||
virtual void visit(uint32_t index, bool value) = 0;
|
|
||||||
|
virtual void bloom_begin(uint32_t era, uint32_t nr_blocks,
|
||||||
|
uint32_t nr_bits, uint32_t nr_set) = 0;
|
||||||
|
virtual void bit(uint32_t index, bool value) = 0;
|
||||||
|
virtual void bloom_end() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
era/emitter.h
Normal file
35
era/emitter.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef ERA_EMITTER_H
|
||||||
|
#define ERA_EMITTER_H
|
||||||
|
|
||||||
|
#include "persistent-data/block.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace era {
|
||||||
|
namespace pd = persistent_data;
|
||||||
|
|
||||||
|
class emitter {
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<emitter> ptr;
|
||||||
|
|
||||||
|
virtual ~emitter() {}
|
||||||
|
|
||||||
|
virtual void begin_superblock(std::string const &uuid,
|
||||||
|
uint32_t data_block_size,
|
||||||
|
pd::block_address nr_blocks,
|
||||||
|
uint32_t current_era) = 0;
|
||||||
|
virtual void end_superblock() = 0;
|
||||||
|
|
||||||
|
virtual void begin_bloom(uint32_t era, uint32_t nr_bits, pd::block_address nr_blocks) = 0;
|
||||||
|
virtual void bloom_bit(uint32_t bit, bool value) = 0;
|
||||||
|
virtual void end_bloom() = 0;
|
||||||
|
|
||||||
|
virtual void begin_era_array() = 0;
|
||||||
|
virtual void era(pd::block_address block, uint32_t era) = 0;
|
||||||
|
virtual void end_era_array() = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
87
era/era_array.cc
Normal file
87
era/era_array.cc
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "era/era_array.h"
|
||||||
|
|
||||||
|
using namespace era;
|
||||||
|
using namespace era_array_detail;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
missing_eras::missing_eras(string const &desc, run<uint32_t> const &eras)
|
||||||
|
: damage(desc),
|
||||||
|
eras_(eras)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
missing_eras::visit(damage_visitor &v) const
|
||||||
|
{
|
||||||
|
v.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_era::invalid_era(string const &desc, block_address block, uint32_t era)
|
||||||
|
: damage(desc),
|
||||||
|
block_(block),
|
||||||
|
era_(era)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
invalid_era::visit(damage_visitor &v) const
|
||||||
|
{
|
||||||
|
v.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class check_era_visitor : public era_array_visitor {
|
||||||
|
public:
|
||||||
|
check_era_visitor(damage_visitor &visitor, uint32_t current_era)
|
||||||
|
: visitor_(visitor),
|
||||||
|
current_era_(current_era) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit(uint32_t cblock, uint32_t era) {
|
||||||
|
if (era > current_era_)
|
||||||
|
visitor_.visit(invalid_era("era too great", cblock, era));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
damage_visitor &visitor_;
|
||||||
|
uint32_t current_era_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ll_damage_visitor {
|
||||||
|
public:
|
||||||
|
ll_damage_visitor(damage_visitor &v)
|
||||||
|
: v_(v) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit(array_detail::damage const &d) {
|
||||||
|
v_.visit(missing_eras(d.desc_, d.lost_keys_));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
damage_visitor &v_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
era::walk_era_array(era_array const &array,
|
||||||
|
era_array_visitor &ev,
|
||||||
|
era_array_detail::damage_visitor &dv)
|
||||||
|
{
|
||||||
|
ll_damage_visitor ll(dv);
|
||||||
|
array.visit_values(ev, ll);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
era::check_era_array(era_array const &array,
|
||||||
|
uint32_t current_era,
|
||||||
|
era_array_detail::damage_visitor &dv)
|
||||||
|
{
|
||||||
|
check_era_visitor cv(dv, current_era);
|
||||||
|
walk_era_array(array, cv, dv);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
78
era/era_array.h
Normal file
78
era/era_array.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#ifndef ERA_ARRAY_H
|
||||||
|
#define ERA_ARRAY_H
|
||||||
|
|
||||||
|
#include "persistent-data/data-structures/array.h"
|
||||||
|
#include "persistent-data/data-structures/simple_traits.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace era {
|
||||||
|
namespace era_array_detail {
|
||||||
|
class damage_visitor;
|
||||||
|
|
||||||
|
class damage {
|
||||||
|
public:
|
||||||
|
damage(std::string const &desc)
|
||||||
|
: desc_(desc) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~damage() {}
|
||||||
|
virtual void visit(damage_visitor &v) const = 0;
|
||||||
|
|
||||||
|
std::string get_desc() const {
|
||||||
|
return desc_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string desc_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct missing_eras : public damage {
|
||||||
|
missing_eras(std::string const &desc, run<uint32_t> const &eras);
|
||||||
|
virtual void visit(damage_visitor &v) const;
|
||||||
|
|
||||||
|
run<uint32_t> eras_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct invalid_era : public damage {
|
||||||
|
invalid_era(std::string const &desc, block_address block, uint32_t era);
|
||||||
|
virtual void visit(damage_visitor &v) const;
|
||||||
|
|
||||||
|
block_address block_;
|
||||||
|
uint32_t era_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class damage_visitor {
|
||||||
|
public:
|
||||||
|
virtual ~damage_visitor() {}
|
||||||
|
|
||||||
|
void visit(era_array_detail::damage const &d) {
|
||||||
|
d.visit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit(missing_eras const &d) = 0;
|
||||||
|
virtual void visit(invalid_era const &d) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef persistent_data::array<uint32_traits> era_array;
|
||||||
|
|
||||||
|
class era_array_visitor {
|
||||||
|
public:
|
||||||
|
virtual ~era_array_visitor() {}
|
||||||
|
|
||||||
|
virtual void visit(uint32_t index, uint32_t era) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void walk_era_array(era_array const &array,
|
||||||
|
era_array_visitor &ev,
|
||||||
|
era_array_detail::damage_visitor &dv);
|
||||||
|
|
||||||
|
void check_era_array(era_array const &array,
|
||||||
|
uint32_t current_era,
|
||||||
|
era_array_detail::damage_visitor &dv);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
@ -15,6 +15,7 @@
|
|||||||
#include "base/error_state.h"
|
#include "base/error_state.h"
|
||||||
#include "base/nested_output.h"
|
#include "base/nested_output.h"
|
||||||
#include "era/bloom_tree.h"
|
#include "era/bloom_tree.h"
|
||||||
|
#include "era/era_array.h"
|
||||||
#include "era/superblock.h"
|
#include "era/superblock.h"
|
||||||
#include "persistent-data/block.h"
|
#include "persistent-data/block.h"
|
||||||
#include "persistent-data/file_utils.h"
|
#include "persistent-data/file_utils.h"
|
||||||
@ -98,7 +99,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void visit(bloom_tree_detail::missing_eras const &d) {
|
void visit(bloom_tree_detail::missing_eras const &d) {
|
||||||
out() << "missing eras" << end_message();
|
out() << "missing eras from bloom tree" << end_message();
|
||||||
{
|
{
|
||||||
nested_output::nest _ = push();
|
nested_output::nest _ = push();
|
||||||
out() << d.get_desc() << end_message();
|
out() << d.get_desc() << end_message();
|
||||||
@ -125,6 +126,38 @@ namespace {
|
|||||||
using reporter_base::get_error;
|
using reporter_base::get_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class era_array_reporter : public era_array_detail::damage_visitor, reporter_base {
|
||||||
|
public:
|
||||||
|
era_array_reporter(nested_output &o)
|
||||||
|
: reporter_base(o) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(era_array_detail::missing_eras const &d) {
|
||||||
|
out() << "missing eras from era array" << end_message();
|
||||||
|
{
|
||||||
|
nested_output::nest _ = push();
|
||||||
|
out() << d.get_desc() << end_message();
|
||||||
|
out() << "Effected eras: [" << d.eras_.begin_.get()
|
||||||
|
<< ", " << d.eras_.end_.get() << ")" << end_message();
|
||||||
|
}
|
||||||
|
|
||||||
|
mplus_error(FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(era_array_detail::invalid_era const &d) {
|
||||||
|
out() << "invalid era in era array" << end_message();
|
||||||
|
{
|
||||||
|
nested_output::nest _ = push();
|
||||||
|
out() << d.get_desc() << end_message();
|
||||||
|
out() << "block: " << d.block_ << ", era: " << d.era_ << end_message();
|
||||||
|
}
|
||||||
|
|
||||||
|
mplus_error(FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
using reporter_base::get_error;
|
||||||
|
};
|
||||||
|
|
||||||
//--------------------------------
|
//--------------------------------
|
||||||
|
|
||||||
transaction_manager::ptr open_tm(block_manager<>::ptr bm) {
|
transaction_manager::ptr open_tm(block_manager<>::ptr bm) {
|
||||||
@ -184,12 +217,22 @@ namespace {
|
|||||||
transaction_manager::ptr tm = open_tm(bm);
|
transaction_manager::ptr tm = open_tm(bm);
|
||||||
|
|
||||||
bloom_tree_reporter bt_rep(out);
|
bloom_tree_reporter bt_rep(out);
|
||||||
era_detail_traits::ref_counter rc(tm);
|
{
|
||||||
bloom_tree bt(tm, rc);
|
era_detail_traits::ref_counter rc(tm);
|
||||||
check_bloom_tree(tm, bt, bt_rep);
|
bloom_tree bt(tm, sb.bloom_tree_root, rc);
|
||||||
|
check_bloom_tree(tm, bt, bt_rep);
|
||||||
|
}
|
||||||
|
|
||||||
|
era_array_reporter ea_rep(out);
|
||||||
|
{
|
||||||
|
uint32_traits::ref_counter rc;
|
||||||
|
era_array ea(tm, rc, sb.era_array_root, sb.nr_blocks);
|
||||||
|
check_era_array(ea, ea_rep);
|
||||||
|
}
|
||||||
|
|
||||||
return combine_errors(sb_rep.get_error(),
|
return combine_errors(sb_rep.get_error(),
|
||||||
bt_rep.get_error());
|
combine_errors(bt_rep.get_error(),
|
||||||
|
ea_rep.get_error()));
|
||||||
}
|
}
|
||||||
|
|
||||||
int check(string const &path, flags const &fs) {
|
int check(string const &path, flags const &fs) {
|
||||||
|
@ -26,11 +26,16 @@ namespace era {
|
|||||||
uint64_t bloom_root;
|
uint64_t bloom_root;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME: implement
|
||||||
struct era_detail_ref_counter {
|
struct era_detail_ref_counter {
|
||||||
era_detail_ref_counter(persistent_data::transaction_manager::ptr tm);
|
era_detail_ref_counter(persistent_data::transaction_manager::ptr tm) {
|
||||||
|
}
|
||||||
|
|
||||||
void inc(persistent_data::block_address b);
|
void inc(persistent_data::block_address b) {
|
||||||
void dec(persistent_data::block_address b);
|
}
|
||||||
|
|
||||||
|
void dec(persistent_data::block_address b) {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct era_detail_traits {
|
struct era_detail_traits {
|
||||||
|
118
era/era_dump.cc
Normal file
118
era/era_dump.cc
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#include <fstream>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
#include "era/era_array.h"
|
||||||
|
#include "era/bloom_tree.h"
|
||||||
|
#include "era/metadata.h"
|
||||||
|
#include "era/metadata_dump.h"
|
||||||
|
#include "era/xml_format.h"
|
||||||
|
#include "persistent-data/file_utils.h"
|
||||||
|
|
||||||
|
using namespace era;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct flags {
|
||||||
|
flags()
|
||||||
|
: repair_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool repair_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
string const STDOUT_PATH("-");
|
||||||
|
|
||||||
|
bool want_stdout(string const &output) {
|
||||||
|
return output == STDOUT_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dump(string const &dev, string const &output, flags const &fs) {
|
||||||
|
try {
|
||||||
|
block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY);
|
||||||
|
metadata::ptr md(new metadata(bm, metadata::OPEN));
|
||||||
|
|
||||||
|
if (want_stdout(output)) {
|
||||||
|
emitter::ptr e = create_xml_emitter(cout);
|
||||||
|
metadata_dump(md, e, fs.repair_);
|
||||||
|
} else {
|
||||||
|
ofstream out(output.c_str());
|
||||||
|
emitter::ptr e = create_xml_emitter(out);
|
||||||
|
metadata_dump(md, e, fs.repair_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
cerr << e.what() << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(ostream &out, string const &cmd) {
|
||||||
|
out << "Usage: " << cmd << " [options] {device|file}" << endl
|
||||||
|
<< "Options:" << endl
|
||||||
|
<< " {-h|--help}" << endl
|
||||||
|
<< " {-o <xml file>}" << endl
|
||||||
|
<< " {-V|--version}" << endl
|
||||||
|
<< " {--repair}" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
flags fs;
|
||||||
|
string output("-");
|
||||||
|
char const shortopts[] = "ho:V";
|
||||||
|
|
||||||
|
option const longopts[] = {
|
||||||
|
{ "help", no_argument, NULL, 'h' },
|
||||||
|
{ "output", required_argument, NULL, 'o' },
|
||||||
|
{ "version", no_argument, NULL, 'V' },
|
||||||
|
{ "repair", no_argument, NULL, 1 },
|
||||||
|
{ NULL, no_argument, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
||||||
|
switch(c) {
|
||||||
|
case 1:
|
||||||
|
fs.repair_ = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
usage(cout, basename(argv[0]));
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
output = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'V':
|
||||||
|
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
usage(cerr, basename(argv[0]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == optind) {
|
||||||
|
cerr << "No input file provided." << endl;
|
||||||
|
usage(cerr, basename(argv[0]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dump(argv[optind], output, fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
60
era/metadata.cc
Normal file
60
era/metadata.cc
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "era/metadata.h"
|
||||||
|
#include "persistent-data/space-maps/core.h"
|
||||||
|
|
||||||
|
using namespace era;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
unsigned const METADATA_CACHE_SIZ = 1024;
|
||||||
|
|
||||||
|
// FIXME: duplication
|
||||||
|
transaction_manager::ptr
|
||||||
|
open_tm(block_manager<>::ptr bm) {
|
||||||
|
space_map::ptr sm(new core_map(bm->get_nr_blocks()));
|
||||||
|
sm->inc(SUPERBLOCK_LOCATION);
|
||||||
|
transaction_manager::ptr tm(new transaction_manager(bm, sm));
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
copy_space_maps(space_map::ptr lhs, space_map::ptr rhs) {
|
||||||
|
for (block_address b = 0; b < rhs->get_nr_blocks(); b++) {
|
||||||
|
uint32_t count = rhs->get_count(b);
|
||||||
|
if (count > 0)
|
||||||
|
lhs->set_count(b, rhs->get_count(b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata::metadata(block_manager<>::ptr bm, open_type ot)
|
||||||
|
{
|
||||||
|
switch (ot) {
|
||||||
|
case CREATE:
|
||||||
|
// finish
|
||||||
|
throw runtime_error("not imlemented");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPEN:
|
||||||
|
open_metadata(bm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
metadata::open_metadata(block_manager<>::ptr bm)
|
||||||
|
{
|
||||||
|
tm_ = open_tm(bm);
|
||||||
|
sb_ = read_superblock(tm_->get_bm());
|
||||||
|
|
||||||
|
bloom_tree_ = bloom_tree::ptr(new bloom_tree(tm_,
|
||||||
|
sb_.bloom_tree_root,
|
||||||
|
era_detail_traits::ref_counter(tm_)));
|
||||||
|
|
||||||
|
era_array_ = era_array::ptr(new era_array(tm_,
|
||||||
|
uint32_traits::ref_counter(),
|
||||||
|
sb_.era_array_root,
|
||||||
|
sb_.nr_blocks));
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
47
era/metadata.h
Normal file
47
era/metadata.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef ERA_METADATA_H
|
||||||
|
#define ERA_METADATA_H
|
||||||
|
|
||||||
|
#include "base/endian_utils.h"
|
||||||
|
|
||||||
|
#include "persistent-data/block.h"
|
||||||
|
#include "persistent-data/data-structures/array.h"
|
||||||
|
#include "persistent-data/data-structures/bitset.h"
|
||||||
|
#include "persistent-data/space-maps/disk.h"
|
||||||
|
#include "persistent-data/transaction_manager.h"
|
||||||
|
|
||||||
|
#include "era/superblock.h"
|
||||||
|
#include "era/bloom_tree.h"
|
||||||
|
#include "era/era_array.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace era {
|
||||||
|
class metadata {
|
||||||
|
public:
|
||||||
|
enum open_type {
|
||||||
|
CREATE,
|
||||||
|
OPEN
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef block_manager<>::read_ref read_ref;
|
||||||
|
typedef block_manager<>::write_ref write_ref;
|
||||||
|
typedef boost::shared_ptr<metadata> ptr;
|
||||||
|
|
||||||
|
metadata(block_manager<>::ptr bm, open_type ot);
|
||||||
|
void commit(bool clean_shutdown = true);
|
||||||
|
|
||||||
|
typedef persistent_data::transaction_manager tm;
|
||||||
|
tm::ptr tm_;
|
||||||
|
superblock sb_;
|
||||||
|
checked_space_map::ptr metadata_sm_;
|
||||||
|
bloom_tree::ptr bloom_tree_;
|
||||||
|
era_array::ptr era_array_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void open_metadata(block_manager<>::ptr bm);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
135
era/metadata_dump.cc
Normal file
135
era/metadata_dump.cc
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include "era/metadata_dump.h"
|
||||||
|
#include "era/era_array.h"
|
||||||
|
|
||||||
|
using namespace era;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
string to_string(unsigned char const *data) {
|
||||||
|
// FIXME: we're assuming the data is zero terminated here
|
||||||
|
return std::string(reinterpret_cast<char const *>(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void raise_metadata_damage() {
|
||||||
|
throw std::runtime_error("metadata contains errors (run era_check for details).\n"
|
||||||
|
"perhaps you wanted to run with --repair ?");
|
||||||
|
}
|
||||||
|
|
||||||
|
class bloom_tree_emitter : public bloom_tree_detail::bloom_visitor {
|
||||||
|
public:
|
||||||
|
bloom_tree_emitter(emitter::ptr e)
|
||||||
|
: e_(e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void bloom_begin(uint32_t era, uint32_t nr_blocks, uint32_t nr_bits, uint32_t nr_set) {
|
||||||
|
e_->begin_bloom(era, nr_bits, nr_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void bit(uint32_t bit, bool value) {
|
||||||
|
e_->bloom_bit(bit, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void bloom_end() {
|
||||||
|
e_->end_bloom();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
emitter::ptr e_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ignore_bloom_tree_damage : public bloom_tree_detail::damage_visitor {
|
||||||
|
void visit(bloom_tree_detail::missing_eras const &d) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(bloom_tree_detail::damaged_bloom_filter const &d) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fatal_bloom_tree_damage : public bloom_tree_detail::damage_visitor {
|
||||||
|
void visit(bloom_tree_detail::missing_eras const &d) {
|
||||||
|
raise_metadata_damage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(bloom_tree_detail::damaged_bloom_filter const &d) {
|
||||||
|
raise_metadata_damage();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
class era_array_emitter : public era_array_visitor {
|
||||||
|
public:
|
||||||
|
era_array_emitter(emitter::ptr e)
|
||||||
|
: e_(e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit(uint32_t index, uint32_t era) {
|
||||||
|
e_->era(index, era);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
emitter::ptr e_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ignore_era_array_damage : public era_array_detail::damage_visitor {
|
||||||
|
void visit(era_array_detail::missing_eras const &d) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(era_array_detail::invalid_era const &d) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class fatal_era_array_damage : public era_array_detail::damage_visitor {
|
||||||
|
void visit(era_array_detail::missing_eras const &d) {
|
||||||
|
raise_metadata_damage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(era_array_detail::invalid_era const &d) {
|
||||||
|
raise_metadata_damage();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
void
|
||||||
|
era::metadata_dump(metadata::ptr md, emitter::ptr e, bool repair)
|
||||||
|
{
|
||||||
|
superblock const &sb = md->sb_;
|
||||||
|
|
||||||
|
e->begin_superblock(to_string(sb.uuid), sb.data_block_size,
|
||||||
|
sb.nr_blocks,
|
||||||
|
sb.current_era);
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bloom_tree_emitter visitor(e);
|
||||||
|
|
||||||
|
ignore_bloom_tree_damage ignore;
|
||||||
|
fatal_bloom_tree_damage fatal;
|
||||||
|
bloom_tree_detail::damage_visitor &dv = repair ?
|
||||||
|
static_cast<bloom_tree_detail::damage_visitor &>(ignore) :
|
||||||
|
static_cast<bloom_tree_detail::damage_visitor &>(fatal);
|
||||||
|
|
||||||
|
walk_bloom_tree(md->tm_, *md->bloom_tree_, visitor, dv);
|
||||||
|
}
|
||||||
|
|
||||||
|
e->begin_era_array();
|
||||||
|
{
|
||||||
|
era_array_emitter visitor(e);
|
||||||
|
|
||||||
|
ignore_era_array_damage ignore;
|
||||||
|
fatal_era_array_damage fatal;
|
||||||
|
era_array_detail::damage_visitor &dv = repair ?
|
||||||
|
static_cast<era_array_detail::damage_visitor &>(ignore) :
|
||||||
|
static_cast<era_array_detail::damage_visitor &>(fatal);
|
||||||
|
|
||||||
|
walk_era_array(*md->era_array_, visitor, dv);
|
||||||
|
}
|
||||||
|
e->end_era_array();
|
||||||
|
}
|
||||||
|
e->end_superblock();
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
15
era/metadata_dump.h
Normal file
15
era/metadata_dump.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef ERA_METADATA_DUMP_H
|
||||||
|
#define ERA_METADATA_DUMP_H
|
||||||
|
|
||||||
|
#include "era/metadata.h"
|
||||||
|
#include "era/emitter.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace era {
|
||||||
|
void metadata_dump(metadata::ptr md, emitter::ptr out, bool repair);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
103
era/xml_format.cc
Normal file
103
era/xml_format.cc
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "era/xml_format.h"
|
||||||
|
|
||||||
|
using namespace boost;
|
||||||
|
using namespace era;
|
||||||
|
using namespace persistent_data;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class xml_emitter : public emitter {
|
||||||
|
public:
|
||||||
|
xml_emitter(ostream &out)
|
||||||
|
: out_(out),
|
||||||
|
indent_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin_superblock(std::string const &uuid,
|
||||||
|
uint32_t block_size,
|
||||||
|
pd::block_address nr_blocks,
|
||||||
|
uint32_t current_era) {
|
||||||
|
indent();
|
||||||
|
out_ << "<superblock uuid=\"" << uuid << "\""
|
||||||
|
<< " block_size=\"" << block_size << "\""
|
||||||
|
<< " nr_blocks=\"" << nr_blocks << "\""
|
||||||
|
<< " current_era=\"" << current_era << "\">" << endl;
|
||||||
|
inc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void end_superblock() {
|
||||||
|
dec();
|
||||||
|
indent();
|
||||||
|
out_ << "</superblock>" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin_bloom(uint32_t era, uint32_t nr_bits,
|
||||||
|
pd::block_address nr_blocks) {
|
||||||
|
indent();
|
||||||
|
out_ << "<bloom era=\"" << era << "\""
|
||||||
|
<< " nr_bits=\"" << nr_bits << "\""
|
||||||
|
<< " nr_blocks=\"" << nr_blocks << "\">" << endl;
|
||||||
|
inc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bloom_bit(uint32_t bit, bool value) {
|
||||||
|
indent();
|
||||||
|
// FIXME: collect all the bits, then uuencode
|
||||||
|
out_ << "<bit bit=\"" << bit << "\" value=\"" << value << "\">" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void end_bloom() {
|
||||||
|
dec();
|
||||||
|
indent();
|
||||||
|
out_ << "</bloom>" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin_era_array() {
|
||||||
|
indent();
|
||||||
|
out_ << "<era_array>" << endl;
|
||||||
|
inc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void era(pd::block_address block, uint32_t era) {
|
||||||
|
indent();
|
||||||
|
out_ << "<era block=\"" << block
|
||||||
|
<< "\" era=\"" << era << "\">" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void end_era_array() {
|
||||||
|
dec();
|
||||||
|
indent();
|
||||||
|
out_ << "</era_array>" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// FIXME: factor out a common class with the thin_provisioning emitter
|
||||||
|
void indent() {
|
||||||
|
for (unsigned i = 0; i < indent_ * 2; i++)
|
||||||
|
out_ << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
void inc() {
|
||||||
|
indent_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dec() {
|
||||||
|
indent_--;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream &out_;
|
||||||
|
unsigned indent_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
emitter::ptr
|
||||||
|
era::create_xml_emitter(std::ostream &out)
|
||||||
|
{
|
||||||
|
return emitter::ptr(new xml_emitter(out));
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
17
era/xml_format.h
Normal file
17
era/xml_format.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef ERA_XML_FORMAT_H
|
||||||
|
#define ERA_XML_FORMAT_H
|
||||||
|
|
||||||
|
#include "emitter.h"
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace era {
|
||||||
|
emitter::ptr create_xml_emitter(std::ostream &out);
|
||||||
|
void parse_xml(std::istream &in, emitter::ptr e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
@ -27,6 +27,8 @@ namespace {
|
|||||||
|
|
||||||
namespace persistent_data {
|
namespace persistent_data {
|
||||||
namespace bitset_detail {
|
namespace bitset_detail {
|
||||||
|
size_t BITS_PER_ULL = 64;
|
||||||
|
|
||||||
class bitset_impl {
|
class bitset_impl {
|
||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<bitset_impl> ptr;
|
typedef boost::shared_ptr<bitset_impl> ptr;
|
||||||
@ -39,7 +41,7 @@ namespace persistent_data {
|
|||||||
|
|
||||||
bitset_impl(tm_ptr tm, block_address root, unsigned nr_bits)
|
bitset_impl(tm_ptr tm, block_address root, unsigned nr_bits)
|
||||||
: nr_bits_(nr_bits),
|
: nr_bits_(nr_bits),
|
||||||
array_(tm, rc_, root, nr_bits) {
|
array_(tm, rc_, root, nr_bits / BITS_PER_ULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
block_address get_root() const {
|
block_address get_root() const {
|
||||||
|
@ -43,22 +43,6 @@ namespace persistent_data {
|
|||||||
space_map::ptr sm_;
|
space_map::ptr sm_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: move to sep file. I don't think it's directly used by
|
|
||||||
// the btree code.
|
|
||||||
struct uint64_traits {
|
|
||||||
typedef base::le64 disk_type;
|
|
||||||
typedef uint64_t value_type;
|
|
||||||
typedef no_op_ref_counter<uint64_t> ref_counter;
|
|
||||||
|
|
||||||
static void unpack(disk_type const &disk, value_type &value) {
|
|
||||||
value = base::to_cpu<uint64_t>(disk);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pack(value_type const &value, disk_type &disk) {
|
|
||||||
disk = base::to_disk<base::le64>(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct block_traits {
|
struct block_traits {
|
||||||
typedef base::le64 disk_type;
|
typedef base::le64 disk_type;
|
||||||
typedef block_address value_type;
|
typedef block_address value_type;
|
||||||
|
38
persistent-data/data-structures/simple_traits.h
Normal file
38
persistent-data/data-structures/simple_traits.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef PERSISTENT_DATA_DATA_STRUCTURES_SIMPLE_TRAITS_H
|
||||||
|
#define PERSISTENT_DATA_DATA_STRUCTURES_SIMPLE_TRAITS_H
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace persistent_data {
|
||||||
|
struct uint64_traits {
|
||||||
|
typedef base::le64 disk_type;
|
||||||
|
typedef uint64_t value_type;
|
||||||
|
typedef no_op_ref_counter<uint64_t> ref_counter;
|
||||||
|
|
||||||
|
static void unpack(disk_type const &disk, value_type &value) {
|
||||||
|
value = base::to_cpu<uint64_t>(disk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pack(value_type const &value, disk_type &disk) {
|
||||||
|
disk = base::to_disk<base::le64>(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uint32_traits {
|
||||||
|
typedef base::le32 disk_type;
|
||||||
|
typedef uint32_t value_type;
|
||||||
|
typedef no_op_ref_counter<uint32_t> ref_counter;
|
||||||
|
|
||||||
|
static void unpack(disk_type const &disk, value_type &value) {
|
||||||
|
value = base::to_cpu<uint32_t>(disk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pack(value_type const &value, disk_type &disk) {
|
||||||
|
disk = base::to_disk<base::le32>(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user