first drop of era_restore

This commit is contained in:
Joe Thornber 2014-08-07 15:43:01 +01:00
parent 1d12d0ff8e
commit 283ab4ad99
8 changed files with 324 additions and 6 deletions

View File

@ -63,6 +63,7 @@ SOURCE=\
era/writeset_tree.cc \ era/writeset_tree.cc \
era/metadata.cc \ era/metadata.cc \
era/metadata_dump.cc \ era/metadata_dump.cc \
era/restore_emitter.cc \
era/xml_format.cc \ era/xml_format.cc \
\ \
persistent-data/checksum.cc \ persistent-data/checksum.cc \
@ -443,7 +444,42 @@ ERA_INVALIDATE_SOURCE=\
ERA_INVALIDATE_OBJECTS=$(subst .cc,.o,$(ERA_INVALIDATE_SOURCE)) ERA_INVALIDATE_OBJECTS=$(subst .cc,.o,$(ERA_INVALIDATE_SOURCE))
era_invalidate: $(ERA_INVALIDATE_OBJECTS) era/era_invalidate.o era_invalidate: $(ERA_INVALIDATE_OBJECTS) era/era_invalidate.o
@echo " [LD] $@"
$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)
ERA_RESTORE_SOURCE=\
block-cache/block_cache.cc \
\
base/base64.cc \
base/error_state.cc \
base/endian_utils.cc \
base/xml_utils.cc \
\
era/writeset_tree.cc \
era/era_detail.cc \
era/era_array.cc \
era/metadata.cc \
era/metadata_dump.cc \
era/restore_emitter.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/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_RESTORE_OBJECTS=$(subst .cc,.o,$(ERA_RESTORE_SOURCE))
era_restore: $(ERA_RESTORE_OBJECTS) era/era_restore.o
@echo " [LD] $@" @echo " [LD] $@"
$(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT)

View File

@ -22,16 +22,22 @@ namespace era {
uint64_t writeset_root; uint64_t writeset_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)
: tm_(tm) {
} }
void inc(persistent_data::block_address b) { void inc(era_detail const &d) {
tm_->get_sm()->inc(d.writeset_root);
} }
void dec(persistent_data::block_address b) { void dec(persistent_data::block_address b) {
// I don't think we ever do this in the tools
throw std::runtime_error("not implemented");
} }
private:
persistent_data::transaction_manager::ptr tm_;
}; };
struct era_detail_traits { struct era_detail_traits {

115
era/era_restore.cc Normal file
View File

@ -0,0 +1,115 @@
#include "version.h"
#include "era/metadata.h"
#include "era/restore_emitter.h"
#include "era/xml_format.h"
#include "persistent-data/file_utils.h"
#include <boost/lexical_cast.hpp>
#include <fstream>
#include <getopt.h>
#include <iostream>
#include <libgen.h>
#include <string>
using namespace boost;
using namespace caching;
using namespace persistent_data;
using namespace std;
//----------------------------------------------------------------
namespace {
struct flags {
optional<string> input;
optional<string> output;
};
int restore(flags const &fs) {
try {
block_manager<>::ptr bm = open_bm(*fs.output, block_manager<>::READ_WRITE);
metadata::ptr md(new metadata(bm, metadata::CREATE));
emitter::ptr restorer = create_restore_emitter(md);
check_file_exists(*fs.input);
ifstream in(fs.input->c_str(), ifstream::in);
parse_xml(in, restorer);
} catch (std::exception &e) {
cerr << e.what() << endl;
return 1;
}
return 0;
}
void usage(ostream &out, string const &cmd) {
out << "Usage: " << cmd << " [options]" << endl
<< "Options:" << endl
<< " {-h|--help}" << endl
<< " {-i|--input} <input xml file>" << endl
<< " {-o|--output} <output device or file>" << endl
<< " {-V|--version}" << endl
<< endl;
}
}
int main(int argc, char **argv)
{
int c;
flags fs;
char const *prog_name = basename(argv[0]);
char const *short_opts = "hi:o:V";
option const long_opts[] = {
{ "help", no_argument, NULL, 'h'},
{ "input", required_argument, NULL, 'i' },
{ "output", required_argument, NULL, 'o'},
{ "version", no_argument, NULL, 'V'},
{ NULL, no_argument, NULL, 0 }
};
while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
switch(c) {
case 'h':
usage(cout, prog_name);
return 0;
case 'i':
fs.input = optional<string>(string(optarg));
break;
case 'o':
fs.output = optional<string>(string(optarg));
break;
case 'V':
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
return 0;
default:
usage(cerr, prog_name);
return 1;
}
}
if (argc != optind) {
usage(cerr, prog_name);
return 1;
}
if (!fs.input) {
cerr << "No input file provided." << endl << endl;
usage(cerr, prog_name);
return 1;
}
if (!fs.output) {
cerr << "No output file provided." << endl << endl;
usage(cerr, prog_name);
return 1;
}
return restore(fs);
}
//----------------------------------------------------------------

View File

@ -53,4 +53,38 @@ metadata::open_metadata(block_manager<>::ptr bm, block_address loc)
sb_.nr_blocks)); sb_.nr_blocks));
} }
void
metadata::commit()
{
commit_space_map();
commit_writesets();
commit_era_array();
commit_superblock();
}
void
metadata::commit_space_map()
{
metadata_sm_->commit();
metadata_sm_->copy_root(&sb_.metadata_space_map_root, sizeof(sb_.metadata_space_map_root));
}
void
metadata::commit_writesets()
{
sb_.writeset_tree_root = writeset_tree_->get_root();
}
void
metadata::commit_era_array()
{
sb_.era_array_root = era_array_->get_root();
}
void
metadata::commit_superblock()
{
write_superblock(tm_->get_bm(), sb_);
}
//---------------------------------------------------------------- //----------------------------------------------------------------

View File

@ -29,7 +29,7 @@ namespace era {
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); metadata(block_manager<>::ptr bm, block_address metadata_snap);
void commit(bool clean_shutdown = true); void commit();
typedef persistent_data::transaction_manager tm; typedef persistent_data::transaction_manager tm;
tm::ptr tm_; tm::ptr tm_;
@ -41,6 +41,11 @@ namespace era {
private: private:
void open_metadata(block_manager<>::ptr bm, void open_metadata(block_manager<>::ptr bm,
block_address loc = SUPERBLOCK_LOCATION); block_address loc = SUPERBLOCK_LOCATION);
void commit_space_map();
void commit_writesets();
void commit_era_array();
void commit_superblock();
}; };
}; };

107
era/restore_emitter.cc Normal file
View File

@ -0,0 +1,107 @@
#include "era/restore_emitter.h"
#include "era/superblock.h"
using namespace era;
using namespace persistent_data;
//----------------------------------------------------------------
namespace {
class restorer : public emitter {
public:
restorer(metadata &md)
: md_(md),
in_superblock_(false),
in_writeset_(false),
in_era_array_(false) {
}
virtual void begin_superblock(std::string const &uuid,
uint32_t data_block_size,
pd::block_address nr_blocks,
uint32_t current_era) {
superblock &sb = md_.sb_;
memcpy(sb.uuid, reinterpret_cast<__u8 const *>(uuid.c_str()),
min<size_t>(sizeof(sb.uuid), uuid.length()));
sb.data_block_size = data_block_size;
sb.nr_blocks = nr_blocks;
sb.current_era = current_era;
nr_blocks = nr_blocks;
}
virtual void end_superblock() {
if (!in_superblock_)
throw runtime_error("missing superblock");
md_.commit();
}
virtual void begin_writeset(uint32_t era, uint32_t nr_bits) {
if (!in_superblock_)
throw runtime_error("missing superblock");
in_writeset_ = true;
era_ = era;
bits_.reset(new bitset(md_.tm_));
bits_->grow(nr_bits, false);
}
virtual void writeset_bit(uint32_t bit, bool value) {
bits_->set(bit, value);
}
virtual void end_writeset() {
in_writeset_ = false;
era_detail e;
e.nr_bits = bits_->get_nr_bits();
e.writeset_root = bits_->get_root();
uint64_t key[1] = {era_};
md_.writeset_tree_->insert(key, e);
}
virtual void begin_era_array() {
if (!in_superblock_)
throw runtime_error("missing superblock");
in_era_array_ = true;
}
virtual void era(pd::block_address block, uint32_t era) {
if (!in_era_array_)
throw runtime_error("missing era array");
md_.era_array_->set(block, era);
}
virtual void end_era_array() {
in_era_array_ = false;
}
private:
metadata &md_;
bool in_superblock_;
bool in_writeset_;
uint32_t era_;
pd::bitset::ptr bits_;
bool in_era_array_;
uint32_t nr_blocks_;
};
}
//----------------------------------------------------------------
emitter::ptr
era::create_restore_emitter(metadata &md)
{
return emitter::ptr(new restorer(md));
}
//----------------------------------------------------------------

15
era/restore_emitter.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef ERA_RESTORE_EMITTER_H
#define ERA_RESTORE_EMITTER_H
#include "era/emitter.h"
#include "era/metadata.h"
//----------------------------------------------------------------
namespace era {
emitter::ptr create_restore_emitter(metadata &md);
}
//----------------------------------------------------------------
#endif

View File

@ -1,5 +1,5 @@
#ifndef ERA_SUPERBLOCK_H #ifndef ERA_SUPERBLOCK_H
#define ERA_SUPERBLOCK_h #define ERA_SUPERBLOCK_H
#include "persistent-data/block.h" #include "persistent-data/block.h"
#include "era/era_detail.h" #include "era/era_detail.h"