era_invalidate
This commit is contained in:
parent
344f4b1e08
commit
d3afa57082
@ -4,12 +4,16 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "version.h"
|
||||
#include "base/indented_stream.h"
|
||||
#include "era/era_array.h"
|
||||
#include "era/writeset_tree.h"
|
||||
#include "era/metadata.h"
|
||||
#include "era/xml_format.h"
|
||||
#include "persistent-data/file_utils.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
using namespace boost;
|
||||
using namespace era;
|
||||
using namespace std;
|
||||
|
||||
@ -17,14 +21,97 @@ using namespace std;
|
||||
|
||||
namespace {
|
||||
struct flags {
|
||||
flags() {
|
||||
flags()
|
||||
: metadata_snapshot_(false) {
|
||||
}
|
||||
|
||||
bool metadata_snapshot_;
|
||||
optional<uint32_t> era_threshold_;
|
||||
};
|
||||
|
||||
//--------------------------------
|
||||
|
||||
void emit_blocks() {
|
||||
|
||||
void walk_array(era_array const &array, uint32_t nr_blocks,
|
||||
uint32_t threshold, set<uint32_t> &blocks) {
|
||||
for (uint32_t b = 0; b < nr_blocks; b++) {
|
||||
uint32_t era = array.get(b);
|
||||
if (era >= threshold)
|
||||
blocks.insert(b);
|
||||
}
|
||||
}
|
||||
|
||||
class writesets_marked_since : public writeset_tree_detail::writeset_visitor {
|
||||
public:
|
||||
writesets_marked_since(uint32_t threshold, set<uint32_t> &blocks)
|
||||
: current_era_(0),
|
||||
threshold_(threshold),
|
||||
blocks_(blocks) {
|
||||
}
|
||||
|
||||
void writeset_begin(uint32_t era, uint32_t nr_bits) {
|
||||
current_era_ = era;
|
||||
}
|
||||
|
||||
void bit(uint32_t index, bool value) {
|
||||
if (value && current_era_ >= threshold_)
|
||||
blocks_.insert(index);
|
||||
}
|
||||
|
||||
void writeset_end() {
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t current_era_;
|
||||
uint32_t threshold_;
|
||||
set<uint32_t> &blocks_;
|
||||
};
|
||||
|
||||
void raise_metadata_damage() {
|
||||
throw std::runtime_error("metadata contains errors (run era_check for details).");
|
||||
}
|
||||
|
||||
struct fatal_writeset_tree_damage : public writeset_tree_detail::damage_visitor {
|
||||
void visit(writeset_tree_detail::missing_eras const &d) {
|
||||
raise_metadata_damage();
|
||||
}
|
||||
|
||||
void visit(writeset_tree_detail::damaged_writeset const &d) {
|
||||
raise_metadata_damage();
|
||||
}
|
||||
};
|
||||
|
||||
void walk_writesets(metadata const &md, uint32_t threshold, set<uint32_t> &result) {
|
||||
writesets_marked_since v(threshold, result);
|
||||
fatal_writeset_tree_damage dv;
|
||||
|
||||
walk_writeset_tree(md.tm_, *md.writeset_tree_, v, dv);
|
||||
}
|
||||
|
||||
void mark_blocks_since(metadata const &md, uint32_t threshold, set<uint32_t> &result) {
|
||||
walk_array(*md.era_array_, md.sb_.nr_blocks, threshold, result);
|
||||
walk_writesets(md, threshold, result);
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
|
||||
void emit_blocks(ostream &out, set<uint32_t> const &blocks) {
|
||||
indented_stream o(out);
|
||||
|
||||
o.indent();
|
||||
o << "<blocks>" << endl;
|
||||
|
||||
o.inc();
|
||||
{
|
||||
set<uint32_t>::const_iterator it;
|
||||
for (it = blocks.begin(); it != blocks.end(); ++it) {
|
||||
o.indent();
|
||||
o << "<block block=\"" << *it << "\"/>" << endl;
|
||||
}
|
||||
}
|
||||
o.dec();
|
||||
|
||||
o.indent();
|
||||
o << "</blocks>" << endl;
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
@ -37,16 +124,28 @@ namespace {
|
||||
|
||||
int invalidate(string const &dev, string const &output, flags const &fs) {
|
||||
try {
|
||||
set<uint32_t> blocks;
|
||||
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);
|
||||
//emit_blocks(md, e, fs);
|
||||
if (fs.metadata_snapshot_) {
|
||||
superblock sb = read_superblock(bm);
|
||||
if (!sb.metadata_snap)
|
||||
throw runtime_error("no metadata snapshot taken.");
|
||||
|
||||
metadata::ptr md(new metadata(bm, *sb.metadata_snap));
|
||||
mark_blocks_since(*md, *fs.era_threshold_, blocks);
|
||||
|
||||
} else {
|
||||
metadata::ptr md(new metadata(bm, metadata::OPEN));
|
||||
mark_blocks_since(*md, *fs.era_threshold_, blocks);
|
||||
}
|
||||
|
||||
if (want_stdout(output))
|
||||
emit_blocks(cout, blocks);
|
||||
|
||||
else {
|
||||
ofstream out(output.c_str());
|
||||
emitter::ptr e = create_xml_emitter(out);
|
||||
//emit_blocks(md, e, fs);
|
||||
emit_blocks(out, blocks);
|
||||
}
|
||||
|
||||
} catch (std::exception &e) {
|
||||
@ -58,7 +157,7 @@ namespace {
|
||||
}
|
||||
|
||||
void usage(ostream &out, string const &cmd) {
|
||||
out << "Usage: " << cmd << " [options] {device|file}" << endl
|
||||
out << "Usage: " << cmd << " [options] --written-since <era> {device|file}" << endl
|
||||
<< "Options:" << endl
|
||||
<< " {-h|--help}" << endl
|
||||
<< " {-o <xml file>}" << endl
|
||||
@ -79,11 +178,21 @@ int main(int argc, char **argv)
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "output", required_argument, NULL, 'o' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "metadata-snapshot", no_argument, NULL, 1},
|
||||
{ "written-since", required_argument, NULL, 2},
|
||||
{ NULL, no_argument, NULL, 0 }
|
||||
};
|
||||
|
||||
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
||||
switch(c) {
|
||||
case 1:
|
||||
fs.metadata_snapshot_ = true;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fs.era_threshold_ = lexical_cast<uint32_t>(optarg);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage(cout, basename(argv[0]));
|
||||
return 0;
|
||||
@ -108,6 +217,12 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!fs.era_threshold_) {
|
||||
cerr << "Please specify --written-since" << endl;
|
||||
usage(cerr, basename(argv[0]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return invalidate(argv[optind], output, fs);
|
||||
}
|
||||
|
||||
|
@ -41,11 +41,16 @@ metadata::metadata(block_manager<>::ptr bm, open_type ot)
|
||||
}
|
||||
}
|
||||
|
||||
metadata::metadata(block_manager<>::ptr bm, block_address metadata_snap)
|
||||
{
|
||||
open_metadata(bm);
|
||||
}
|
||||
|
||||
void
|
||||
metadata::open_metadata(block_manager<>::ptr bm)
|
||||
metadata::open_metadata(block_manager<>::ptr bm, block_address loc)
|
||||
{
|
||||
tm_ = open_tm(bm);
|
||||
sb_ = read_superblock(tm_->get_bm());
|
||||
sb_ = read_superblock(tm_->get_bm(), loc);
|
||||
|
||||
writeset_tree_ = writeset_tree::ptr(new writeset_tree(tm_,
|
||||
sb_.writeset_tree_root,
|
||||
|
@ -28,6 +28,7 @@ namespace era {
|
||||
typedef boost::shared_ptr<metadata> ptr;
|
||||
|
||||
metadata(block_manager<>::ptr bm, open_type ot);
|
||||
metadata(block_manager<>::ptr bm, block_address metadata_snap);
|
||||
void commit(bool clean_shutdown = true);
|
||||
|
||||
typedef persistent_data::transaction_manager tm;
|
||||
@ -38,7 +39,8 @@ namespace era {
|
||||
era_array::ptr era_array_;
|
||||
|
||||
private:
|
||||
void open_metadata(block_manager<>::ptr bm);
|
||||
void open_metadata(block_manager<>::ptr bm,
|
||||
block_address loc = SUPERBLOCK_LOCATION);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "persistent-data/errors.h"
|
||||
|
||||
using namespace base;
|
||||
using namespace boost;
|
||||
using namespace era;
|
||||
using namespace superblock_damage;
|
||||
using namespace persistent_data;
|
||||
@ -37,6 +38,8 @@ namespace {
|
||||
le64 writeset_tree_root;
|
||||
le64 era_array_root;
|
||||
|
||||
le64 metadata_snap;
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct superblock_traits {
|
||||
@ -143,6 +146,11 @@ superblock_traits::unpack(disk_type const &disk, value_type &value)
|
||||
era_detail_traits::unpack(disk.current_detail, value.current_detail);
|
||||
value.writeset_tree_root = to_cpu<uint64_t>(disk.writeset_tree_root);
|
||||
value.era_array_root = to_cpu<uint64_t>(disk.era_array_root);
|
||||
|
||||
block_address ms = to_cpu<uint64_t>(disk.metadata_snap);
|
||||
value.metadata_snap = (ms == SUPERBLOCK_LOCATION) ?
|
||||
optional<block_address>() :
|
||||
optional<block_address>(ms);
|
||||
}
|
||||
|
||||
void
|
||||
@ -163,6 +171,10 @@ superblock_traits::pack(value_type const &value, disk_type &disk)
|
||||
era_detail_traits::pack(value.current_detail, disk.current_detail);
|
||||
disk.writeset_tree_root = to_disk<le64>(value.writeset_tree_root);
|
||||
disk.era_array_root = to_disk<le64>(value.era_array_root);
|
||||
|
||||
disk.metadata_snap = value.metadata_snap ?
|
||||
to_disk<le64>(*value.metadata_snap) :
|
||||
to_disk<le64>(SUPERBLOCK_LOCATION);
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "persistent-data/block.h"
|
||||
#include "era/era_detail.h"
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
@ -63,6 +64,8 @@ namespace era {
|
||||
|
||||
// Big array holding the digested era/block info.
|
||||
uint64_t era_array_root;
|
||||
|
||||
boost::optional<persistent_data::block_address> metadata_snap;
|
||||
};
|
||||
|
||||
//--------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user