[thin_delta] Add superblock and diff tags

This commit is contained in:
Joe Thornber 2015-03-25 10:09:39 +00:00
parent 182be112fa
commit 0e72f772d0

View File

@ -6,9 +6,11 @@
#include "version.h" #include "version.h"
#include "base/indented_stream.h"
#include "persistent-data/data-structures/btree_damage_visitor.h" #include "persistent-data/data-structures/btree_damage_visitor.h"
#include "persistent-data/run.h" #include "persistent-data/run.h"
#include "persistent-data/space-maps/core.h" #include "persistent-data/space-maps/core.h"
#include "persistent-data/space-maps/disk.h"
#include "persistent-data/file_utils.h" #include "persistent-data/file_utils.h"
#include "thin-provisioning/superblock.h" #include "thin-provisioning/superblock.h"
#include "thin-provisioning/mapping_tree.h" #include "thin-provisioning/mapping_tree.h"
@ -27,8 +29,11 @@ namespace local {
} }
void usage(ostream &out) { void usage(ostream &out) {
out << "Usage: " << cmd_ << " [options] --snap1 <snap> --snap2 <snap> <device or file>\n" out << "Usage: " << cmd_ << " [options] <device or file>\n"
<< "Options:\n" << "Options:\n"
<< " {--thin1, --snap1}\n"
<< " {--thin2, --snap2}\n"
<< " {-m, --metadata-snap}\n"
<< " {--verbose}\n" << " {--verbose}\n"
<< " {-h|--help}\n" << " {-h|--help}\n"
<< " {-V|--version}" << endl; << " {-V|--version}" << endl;
@ -201,7 +206,7 @@ namespace local {
class diff_emitter { class diff_emitter {
public: public:
diff_emitter(ostream &out) diff_emitter(indented_stream &out)
: out_(out) { : out_(out) {
} }
@ -212,18 +217,22 @@ namespace local {
virtual void complete() = 0; virtual void complete() = 0;
protected: protected:
ostream &out() { void indent() {
out_.indent();
}
indented_stream &out() {
return out_; return out_;
} }
private: private:
ostream &out_; indented_stream &out_;
}; };
class simple_emitter : public diff_emitter { class simple_emitter : public diff_emitter {
public: public:
simple_emitter(ostream &out) simple_emitter(indented_stream &out)
: diff_emitter(out) { : diff_emitter(out) {
} }
@ -272,6 +281,7 @@ namespace local {
if (!current_type_) if (!current_type_)
return; return;
indent();
switch (*current_type_) { switch (*current_type_) {
case LEFT_ONLY: case LEFT_ONLY:
out() << "<left_only"; out() << "<left_only";
@ -300,27 +310,30 @@ namespace local {
class verbose_emitter : public diff_emitter { class verbose_emitter : public diff_emitter {
public: public:
verbose_emitter(ostream &out) verbose_emitter(indented_stream &out)
: diff_emitter(out) { : diff_emitter(out) {
} }
void left_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) { void left_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) {
begin_block(LEFT_ONLY); begin_block(LEFT_ONLY);
out() << " <range begin=\"" << vbegin << "\"" indent();
out() << "<range begin=\"" << vbegin << "\""
<< " data_begin=\"" << dbegin << "\"" << " data_begin=\"" << dbegin << "\""
<< " length=\"" << len << "\"/>\n"; << " length=\"" << len << "\"/>\n";
} }
void right_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) { void right_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) {
begin_block(RIGHT_ONLY); begin_block(RIGHT_ONLY);
out() << " <range begin=\"" << vbegin << "\"" indent();
out() << "<range begin=\"" << vbegin << "\""
<< " data_begin=\"" << dbegin << "\"" << " data_begin=\"" << dbegin << "\""
<< " length=\"" << len << "\"/>\n"; << " length=\"" << len << "\"/>\n";
} }
void blocks_differ(uint64_t vbegin, uint64_t left_dbegin, uint64_t right_dbegin, uint64_t len) { void blocks_differ(uint64_t vbegin, uint64_t left_dbegin, uint64_t right_dbegin, uint64_t len) {
begin_block(DIFFER); begin_block(DIFFER);
out() << " <range begin=\"" << vbegin << "\"" indent();
out() << "<range begin=\"" << vbegin << "\""
<< " left_data_begin=\"" << left_dbegin << "\"" << " left_data_begin=\"" << left_dbegin << "\""
<< " right_data_begin=\"" << right_dbegin << "\"" << " right_data_begin=\"" << right_dbegin << "\""
<< " length=\"" << len << "\"/>\n"; << " length=\"" << len << "\"/>\n";
@ -328,7 +341,8 @@ namespace local {
void blocks_same(uint64_t vbegin, uint64_t dbegin, uint64_t len) { void blocks_same(uint64_t vbegin, uint64_t dbegin, uint64_t len) {
begin_block(SAME); begin_block(SAME);
out() << " <range begin=\"" << vbegin << "\"" indent();
out() << "<range begin=\"" << vbegin << "\""
<< " data_begin=\"" << dbegin << "\"" << " data_begin=\"" << dbegin << "\""
<< " length=\"" << len << "\"/>\n"; << " length=\"" << len << "\"/>\n";
} }
@ -359,6 +373,7 @@ namespace local {
} }
void open(block_type t) { void open(block_type t) {
indent();
switch (t) { switch (t) {
case LEFT_ONLY: case LEFT_ONLY:
out() << "<left_only>\n"; out() << "<left_only>\n";
@ -376,24 +391,27 @@ namespace local {
out() << "<same>\n"; out() << "<same>\n";
break; break;
} }
out().inc();
} }
void close(block_type t) { void close(block_type t) {
out().dec();
indent();
switch (t) { switch (t) {
case LEFT_ONLY: case LEFT_ONLY:
out() << "</left_only>\n\n"; out() << "</left_only>\n";
break; break;
case RIGHT_ONLY: case RIGHT_ONLY:
out() << "</right_only>\n\n"; out() << "</right_only>\n";
break; break;
case DIFFER: case DIFFER:
out() << "</different>\n\n"; out() << "</different>\n";
break; break;
case SAME: case SAME:
out() << "</same>\n\n"; out() << "</same>\n";
break; break;
} }
@ -466,16 +484,59 @@ namespace local {
e.complete(); e.complete();
} }
// FIXME: duplication with xml_format
void begin_superblock(indented_stream &out,
string const &uuid,
uint64_t time,
uint64_t trans_id,
uint32_t data_block_size,
uint64_t nr_data_blocks,
boost::optional<uint64_t> metadata_snap) {
out.indent();
out << "<superblock uuid=\"" << uuid << "\""
<< " time=\"" << time << "\""
<< " transaction=\"" << trans_id << "\""
<< " data_block_size=\"" << data_block_size << "\""
<< " nr_data_blocks=\"" << nr_data_blocks;
if (metadata_snap)
out << "\" metadata_snap=\"" << *metadata_snap;
out << "\">\n";
out.inc();
}
void end_superblock(indented_stream &out) {
out.dec();
out.indent();
out << "</superblock>\n";
}
void begin_diff(indented_stream &out, uint64_t snap1, uint64_t snap2) {
out.indent();
out << "<diff left=\"" << snap1 << "\" right=\"" << snap2 << "\">\n";
out.inc();
}
void end_diff(indented_stream &out) {
out.dec();
out.indent();
out << "</diff>\n";
}
void delta_(application &app, flags const &fs) { void delta_(application &app, flags const &fs) {
mapping_recorder mr1; mapping_recorder mr1;
mapping_recorder mr2; mapping_recorder mr2;
damage_visitor damage_v; damage_visitor damage_v;
superblock_detail::superblock sb;
checked_space_map::ptr data_sm;
{ {
block_manager<>::ptr bm = open_bm(*fs.dev); block_manager<>::ptr bm = open_bm(*fs.dev);
transaction_manager::ptr tm = open_tm(bm); transaction_manager::ptr tm = open_tm(bm);
superblock_detail::superblock sb = read_superblock(bm); sb = read_superblock(bm);
data_sm = open_disk_sm(*tm, static_cast<void *>(&sb.data_space_map_root_));
dev_tree dtree(*tm, sb.data_mapping_root_, dev_tree dtree(*tm, sb.data_mapping_root_,
mapping_tree_detail::mtree_traits::ref_counter(tm)); mapping_tree_detail::mtree_traits::ref_counter(tm));
@ -508,13 +569,26 @@ namespace local {
mr2.complete(); mr2.complete();
} }
indented_stream is(cout);
begin_superblock(is, "", sb.time_,
sb.trans_id_,
sb.data_block_size_,
data_sm->get_nr_blocks(),
sb.metadata_snap_ ?
boost::optional<block_address>(sb.metadata_snap_) :
boost::optional<block_address>());
begin_diff(is, *fs.snap1, *fs.snap2);
if (fs.verbose) { if (fs.verbose) {
verbose_emitter e(cout); verbose_emitter e(is);
dump_diff(mr1.get_mappings(), mr2.get_mappings(), e); dump_diff(mr1.get_mappings(), mr2.get_mappings(), e);
} else { } else {
simple_emitter e(cout); simple_emitter e(is);
dump_diff(mr1.get_mappings(), mr2.get_mappings(), e); dump_diff(mr1.get_mappings(), mr2.get_mappings(), e);
} }
end_diff(is);
end_superblock(is);
} }
int delta(application &app, flags const &fs) { int delta(application &app, flags const &fs) {
@ -541,13 +615,15 @@ int thin_delta_main(int argc, char **argv)
flags fs; flags fs;
local::application app(basename(argv[0])); local::application app(basename(argv[0]));
char const shortopts[] = "hV"; char const shortopts[] = "hVm";
option const longopts[] = { option const longopts[] = {
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
{ "thin1", required_argument, NULL, 1 },
{ "snap1", required_argument, NULL, 1 }, { "snap1", required_argument, NULL, 1 },
{ "thin2", required_argument, NULL, 2 },
{ "snap2", required_argument, NULL, 2 }, { "snap2", required_argument, NULL, 2 },
{ "metadata-snap", no_argument, NULL, 3 }, { "metadata-snap", no_argument, NULL, 'm' },
{ "verbose", no_argument, NULL, 4 } { "verbose", no_argument, NULL, 4 }
}; };
@ -569,7 +645,7 @@ int thin_delta_main(int argc, char **argv)
fs.snap2 = app.parse_snap(optarg); fs.snap2 = app.parse_snap(optarg);
break; break;
case 3: case 'm':
abort(); abort();
break; break;