first drop of era_restore
This commit is contained in:
parent
1d12d0ff8e
commit
283ab4ad99
38
Makefile.in
38
Makefile.in
@ -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)
|
||||||
|
|
||||||
|
@ -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
115
era/era_restore.cc
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
@ -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_);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -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
107
era/restore_emitter.cc
Normal 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
15
era/restore_emitter.h
Normal 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
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user