era_invalidate
This commit is contained in:
parent
344f4b1e08
commit
d3afa57082
@ -4,12 +4,16 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "base/indented_stream.h"
|
||||||
#include "era/era_array.h"
|
#include "era/era_array.h"
|
||||||
#include "era/writeset_tree.h"
|
#include "era/writeset_tree.h"
|
||||||
#include "era/metadata.h"
|
#include "era/metadata.h"
|
||||||
#include "era/xml_format.h"
|
#include "era/xml_format.h"
|
||||||
#include "persistent-data/file_utils.h"
|
#include "persistent-data/file_utils.h"
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
using namespace boost;
|
||||||
using namespace era;
|
using namespace era;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -17,14 +21,97 @@ using namespace std;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct flags {
|
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) {
|
int invalidate(string const &dev, string const &output, flags const &fs) {
|
||||||
try {
|
try {
|
||||||
|
set<uint32_t> blocks;
|
||||||
block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY);
|
block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY);
|
||||||
metadata::ptr md(new metadata(bm, metadata::OPEN));
|
|
||||||
|
|
||||||
if (want_stdout(output)) {
|
if (fs.metadata_snapshot_) {
|
||||||
emitter::ptr e = create_xml_emitter(cout);
|
superblock sb = read_superblock(bm);
|
||||||
//emit_blocks(md, e, fs);
|
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 {
|
} 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());
|
ofstream out(output.c_str());
|
||||||
emitter::ptr e = create_xml_emitter(out);
|
emit_blocks(out, blocks);
|
||||||
//emit_blocks(md, e, fs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
@ -58,7 +157,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void usage(ostream &out, string const &cmd) {
|
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
|
<< "Options:" << endl
|
||||||
<< " {-h|--help}" << endl
|
<< " {-h|--help}" << endl
|
||||||
<< " {-o <xml file>}" << endl
|
<< " {-o <xml file>}" << endl
|
||||||
@ -79,11 +178,21 @@ int main(int argc, char **argv)
|
|||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "output", required_argument, NULL, 'o' },
|
{ "output", required_argument, NULL, 'o' },
|
||||||
{ "version", no_argument, NULL, 'V' },
|
{ "version", no_argument, NULL, 'V' },
|
||||||
|
{ "metadata-snapshot", no_argument, NULL, 1},
|
||||||
|
{ "written-since", required_argument, NULL, 2},
|
||||||
{ NULL, no_argument, NULL, 0 }
|
{ NULL, no_argument, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
|
case 1:
|
||||||
|
fs.metadata_snapshot_ = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
fs.era_threshold_ = lexical_cast<uint32_t>(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(cout, basename(argv[0]));
|
usage(cout, basename(argv[0]));
|
||||||
return 0;
|
return 0;
|
||||||
@ -108,6 +217,12 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
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);
|
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
|
void
|
||||||
metadata::open_metadata(block_manager<>::ptr bm)
|
metadata::open_metadata(block_manager<>::ptr bm, block_address loc)
|
||||||
{
|
{
|
||||||
tm_ = open_tm(bm);
|
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_,
|
writeset_tree_ = writeset_tree::ptr(new writeset_tree(tm_,
|
||||||
sb_.writeset_tree_root,
|
sb_.writeset_tree_root,
|
||||||
|
@ -28,6 +28,7 @@ namespace era {
|
|||||||
typedef boost::shared_ptr<metadata> ptr;
|
typedef boost::shared_ptr<metadata> ptr;
|
||||||
|
|
||||||
metadata(block_manager<>::ptr bm, open_type ot);
|
metadata(block_manager<>::ptr bm, open_type ot);
|
||||||
|
metadata(block_manager<>::ptr bm, block_address metadata_snap);
|
||||||
void commit(bool clean_shutdown = true);
|
void commit(bool clean_shutdown = true);
|
||||||
|
|
||||||
typedef persistent_data::transaction_manager tm;
|
typedef persistent_data::transaction_manager tm;
|
||||||
@ -38,7 +39,8 @@ namespace era {
|
|||||||
era_array::ptr era_array_;
|
era_array::ptr era_array_;
|
||||||
|
|
||||||
private:
|
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"
|
#include "persistent-data/errors.h"
|
||||||
|
|
||||||
using namespace base;
|
using namespace base;
|
||||||
|
using namespace boost;
|
||||||
using namespace era;
|
using namespace era;
|
||||||
using namespace superblock_damage;
|
using namespace superblock_damage;
|
||||||
using namespace persistent_data;
|
using namespace persistent_data;
|
||||||
@ -37,6 +38,8 @@ namespace {
|
|||||||
le64 writeset_tree_root;
|
le64 writeset_tree_root;
|
||||||
le64 era_array_root;
|
le64 era_array_root;
|
||||||
|
|
||||||
|
le64 metadata_snap;
|
||||||
|
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct superblock_traits {
|
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);
|
era_detail_traits::unpack(disk.current_detail, value.current_detail);
|
||||||
value.writeset_tree_root = to_cpu<uint64_t>(disk.writeset_tree_root);
|
value.writeset_tree_root = to_cpu<uint64_t>(disk.writeset_tree_root);
|
||||||
value.era_array_root = to_cpu<uint64_t>(disk.era_array_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
|
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);
|
era_detail_traits::pack(value.current_detail, disk.current_detail);
|
||||||
disk.writeset_tree_root = to_disk<le64>(value.writeset_tree_root);
|
disk.writeset_tree_root = to_disk<le64>(value.writeset_tree_root);
|
||||||
disk.era_array_root = to_disk<le64>(value.era_array_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 "persistent-data/block.h"
|
||||||
#include "era/era_detail.h"
|
#include "era/era_detail.h"
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@ -63,6 +64,8 @@ namespace era {
|
|||||||
|
|
||||||
// Big array holding the digested era/block info.
|
// Big array holding the digested era/block info.
|
||||||
uint64_t era_array_root;
|
uint64_t era_array_root;
|
||||||
|
|
||||||
|
boost::optional<persistent_data::block_address> metadata_snap;
|
||||||
};
|
};
|
||||||
|
|
||||||
//--------------------------------
|
//--------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user