[cache_dump, cache_restore] restore/dump cycle works

This commit is contained in:
Joe Thornber 2013-09-19 13:45:56 +01:00
parent c476de1756
commit 61e90998c0
13 changed files with 129 additions and 39 deletions

View File

@ -23,7 +23,7 @@ GEM
multi_test (0.0.2) multi_test (0.0.2)
rspec-expectations (2.14.2) rspec-expectations (2.14.2)
diff-lcs (>= 1.1.3, < 2.0) diff-lcs (>= 1.1.3, < 2.0)
thinp_xml (0.0.9) thinp_xml (0.0.10)
ejt_command_line (= 0.0.2) ejt_command_line (= 0.0.2)
PLATFORMS PLATFORMS

View File

@ -4,14 +4,24 @@
#include <iostream> #include <iostream>
#include "version.h" #include "version.h"
#include "caching/metadata.h"
#include "caching/xml_format.h" #include "caching/xml_format.h"
#include "persistent-data/file_utils.h"
using namespace std; using namespace std;
using namespace caching; using namespace caching;
using namespace caching::superblock_detail;
//---------------------------------------------------------------- //----------------------------------------------------------------
namespace { 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));
}
//--------------------------------
string const STDOUT_PATH("-"); string const STDOUT_PATH("-");
bool want_stdout(string const &output) { bool want_stdout(string const &output) {
@ -19,16 +29,30 @@ namespace {
} }
int dump_(string const &dev, ostream &out) { int dump_(string const &dev, ostream &out) {
block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY);
metadata::ptr md(new metadata(bm, metadata::OPEN));
emitter::ptr e = create_xml_emitter(out); emitter::ptr e = create_xml_emitter(out);
superblock const &sb = md->sb_;
e->begin_superblock(to_string(sb.uuid), sb.data_block_size, sb.cache_blocks, to_string(sb.policy_name));
e->end_superblock();
return 0; return 0;
} }
int dump(string const &dev, string const &output) { int dump(string const &dev, string const &output) {
if (want_stdout(output)) { try {
ofstream out(output.c_str()); if (want_stdout(output))
return dump_(dev, out); return dump_(dev, cout);
} else else {
return dump_(dev, cout); ofstream out(output.c_str());
return dump_(dev, out);
}
} catch (std::exception &e) {
cerr << e.what() << endl;
return 1;
}
} }
void usage(ostream &out, string const &cmd) { void usage(ostream &out, string const &cmd) {

View File

@ -20,7 +20,7 @@ using namespace std;
namespace { namespace {
int restore(string const &xml_file, string const &dev) { int restore(string const &xml_file, string const &dev) {
try { try {
block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY); block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_WRITE);
metadata::ptr md(new metadata(bm, metadata::CREATE)); metadata::ptr md(new metadata(bm, metadata::CREATE));
emitter::ptr restorer = create_restore_emitter(md); emitter::ptr restorer = create_restore_emitter(md);

View File

@ -7,6 +7,11 @@
namespace caching { namespace caching {
namespace mapping_array_detail { namespace mapping_array_detail {
enum mapping_flags {
M_VALID = 1,
M_DIRTY = 2
};
struct mapping { struct mapping {
uint64_t oblock_; uint64_t oblock_;
uint32_t flags_; uint32_t flags_;

View File

@ -1,4 +1,5 @@
#include "caching/metadata.h" #include "caching/metadata.h"
#include "caching/superblock.h"
#include "persistent-data/space-maps/core.h" #include "persistent-data/space-maps/core.h"
using namespace caching; using namespace caching;
@ -27,18 +28,6 @@ namespace {
lhs->set_count(b, rhs->get_count(b)); lhs->set_count(b, rhs->get_count(b));
} }
} }
void init_superblock(superblock &sb) {
#if 0
sb.magic_ = SUPERBLOCK_MAGIC;
sb.version_ = 1;
sb.data_mapping_root_ = mappings_->get_root();
sb.device_details_root_ = details_->get_root();
sb.data_block_size_ = data_block_size;
sb.metadata_block_size_ = MD_BLOCK_SIZE;
sb.metadata_nr_blocks_ = tm_->get_bm()->get_nr_blocks();
#endif
}
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -46,22 +35,16 @@ namespace {
metadata::metadata(block_manager<>::ptr bm, open_type ot) metadata::metadata(block_manager<>::ptr bm, open_type ot)
{ {
switch (ot) { switch (ot) {
case OPEN: case CREATE:
throw runtime_error("not implemented"); create_metadata(bm);
break; break;
case CREATE: case OPEN:
tm_ = open_tm(bm); open_metadata(bm);
space_map::ptr core = tm_->get_sm(); break;
metadata_sm_ = create_metadata_sm(tm_, tm_->get_bm()->get_nr_blocks());
copy_space_maps(metadata_sm_, core);
tm_->set_sm(metadata_sm_);
mappings_ = mapping_array::ptr(new mapping_array(tm_, mapping_array::ref_counter())); default:
// hints_ = hint_array::ptr(new hint_array(tm_)); throw runtime_error("unhandled open_type");
::memset(&sb_, 0, sizeof(sb_));
init_superblock(sb_);
} }
} }
@ -77,4 +60,42 @@ metadata::commit()
superblock_traits::pack(sb_, *disk); superblock_traits::pack(sb_, *disk);
} }
void
metadata::init_superblock()
{
#if 0
sb_.magic_ = SUPERBLOCK_MAGIC;
sb_.version_ = 1;
sb_.data_mapping_root_ = mappings_->get_root();
sb_.device_details_root_ = details_->get_root();
sb_.data_block_size_ = data_block_size;
sb_.metadata_block_size_ = MD_BLOCK_SIZE;
sb_.metadata_nr_blocks_ = tm_->get_bm()->get_nr_blocks();
#endif
}
void
metadata::create_metadata(block_manager<>::ptr bm)
{
tm_ = open_tm(bm);
::memset(&sb_, 0, sizeof(sb_));
init_superblock();
space_map::ptr core = tm_->get_sm();
metadata_sm_ = create_metadata_sm(tm_, tm_->get_bm()->get_nr_blocks());
copy_space_maps(metadata_sm_, core);
tm_->set_sm(metadata_sm_);
mappings_ = mapping_array::ptr(new mapping_array(tm_, mapping_array::ref_counter()));
// hints_ = hint_array::ptr(new hint_array(tm_));
}
void
metadata::open_metadata(block_manager<>::ptr bm)
{
tm_ = open_tm(bm);
sb_ = read_superblock(tm_->get_bm());
}
//---------------------------------------------------------------- //----------------------------------------------------------------

View File

@ -35,6 +35,12 @@ namespace caching {
checked_space_map::ptr metadata_sm_; checked_space_map::ptr metadata_sm_;
mapping_array::ptr mappings_; mapping_array::ptr mappings_;
//hint_array::ptr hints_; //hint_array::ptr hints_;
private:
void init_superblock();
void create_metadata(block_manager<>::ptr bm);
void open_metadata(block_manager<>::ptr bm);
}; };
}; };

View File

@ -1,14 +1,15 @@
#include "caching/restore_emitter.h" #include "caching/restore_emitter.h"
#include "caching/superblock.h" #include "caching/superblock.h"
#include "caching/mapping_array.h"
using namespace std;
using namespace caching; using namespace caching;
using namespace mapping_array_detail;
using namespace std;
using namespace superblock_detail;
//---------------------------------------------------------------- //----------------------------------------------------------------
namespace { namespace {
using namespace superblock_detail;
class restorer : public emitter { class restorer : public emitter {
public: public:
restorer(metadata::ptr md) restorer(metadata::ptr md)
@ -54,6 +55,11 @@ namespace {
sb.read_misses = 0; sb.read_misses = 0;
sb.write_hits = 0; sb.write_hits = 0;
sb.write_misses = 0; sb.write_misses = 0;
struct mapping unmapped_value;
unmapped_value.oblock_ = 0;
unmapped_value.flags_ = 0;
md_->mappings_->grow(nr_cache_blocks, unmapped_value);
} }
virtual void end_superblock() { virtual void end_superblock() {

View File

@ -141,8 +141,7 @@ caching::superblock_validator()
//-------------------------------- //--------------------------------
superblock_detail::superblock superblock_detail::superblock
caching::read_superblock(persistent_data::block_manager<>::ptr bm, caching::read_superblock(block_manager<>::ptr bm, block_address location)
persistent_data::block_address location)
{ {
using namespace superblock_detail; using namespace superblock_detail;
@ -160,6 +159,24 @@ caching::read_superblock(persistent_data::block_manager<>::ptr bm)
return read_superblock(bm, SUPERBLOCK_LOCATION); return read_superblock(bm, SUPERBLOCK_LOCATION);
} }
void
caching::write_superblock(block_manager<>::ptr bm,
block_address location,
superblock_detail::superblock const &sb)
{
using namespace superblock_detail;
block_manager<>::write_ref w = bm->write_lock(location, superblock_validator());
superblock_traits::pack(sb, *reinterpret_cast<superblock_disk *>(&w.data()));
}
void
caching::write_superblock(block_manager<>::ptr bm,
superblock_detail::superblock const &sb)
{
write_superblock(bm, SUPERBLOCK_LOCATION, sb);
}
void void
caching::check_superblock(persistent_data::block_manager<>::ptr bm, caching::check_superblock(persistent_data::block_manager<>::ptr bm,
superblock_detail::damage_visitor &visitor) superblock_detail::damage_visitor &visitor)

View File

@ -130,6 +130,13 @@ namespace caching {
superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm); superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm);
superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm, superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm,
persistent_data::block_address location); persistent_data::block_address location);
void write_superblock(persistent_data::block_manager<>::ptr bm,
superblock_detail::superblock const &sb);
void write_superblock(persistent_data::block_manager<>::ptr bm,
persistent_data::block_address location,
superblock_detail::superblock const &sb);
void check_superblock(persistent_data::block_manager<>::ptr bm, void check_superblock(persistent_data::block_manager<>::ptr bm,
superblock_detail::damage_visitor &visitor); superblock_detail::damage_visitor &visitor);
} }

View File

@ -41,6 +41,7 @@ Feature: cache_dump
No input file provided. No input file provided.
""" """
@announce
Scenario: dump/restore is a noop Scenario: dump/restore is a noop
Given valid cache metadata Given valid cache metadata
When I cache_dump When I cache_dump

View File

@ -53,6 +53,7 @@ Feature: thin_restore
No output file provided. No output file provided.
""" """
@announce
Scenario: successfully restores a valid xml file Scenario: successfully restores a valid xml file
Given a small xml file Given a small xml file
And an empty dev file And an empty dev file

View File

@ -74,14 +74,14 @@ end
Given(/^valid cache metadata$/) do Given(/^valid cache metadata$/) do
in_current_dir do in_current_dir do
system("cache_xml create --nr-cache-blocks uniform[1000-5000] --nr-mappings uniform[500-1000] > #{xml_file}") system("cache_xml create --nr-cache-blocks uniform[1000..5000] --nr-mappings uniform[500..1000] > #{xml_file}")
end end
run_simple("dd if=/dev/zero of=#{dev_file} bs=4k count=1024") run_simple("dd if=/dev/zero of=#{dev_file} bs=4k count=1024")
run_simple("cache_restore -i #{xml_file} -o #{dev_file}") run_simple("cache_restore -i #{xml_file} -o #{dev_file}")
end end
Then(/^cache dumps (\d+) and (\d+) should be identical$/) do |arg1, arg2| Then(/^cache dumps (\d+) and (\d+) should be identical$/) do |d1, d2|
run_simple("diff -ub #{dump_files[d1.to_i]} #{dump_files[d2.to_i]}", true) run_simple("diff -ub #{dump_files[d1.to_i]} #{dump_files[d2.to_i]}", true)
end end

View File

@ -122,6 +122,8 @@ namespace thin_provisioning {
persistent_data::block_manager<>::validator::ptr superblock_validator(); persistent_data::block_manager<>::validator::ptr superblock_validator();
// FIXME: should we put init_superblock in here too?
superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm); superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm);
superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm, persistent_data::block_address location); superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm, persistent_data::block_address location);
void check_superblock(persistent_data::block_manager<>::ptr bm, void check_superblock(persistent_data::block_manager<>::ptr bm,