[thin_delta] Support comparing two specific subtrees

This commit is contained in:
Ming-Hung Tsai
2020-10-20 14:50:21 +08:00
parent 1d5b52b0dd
commit 7ceb500fc8

View File

@ -36,6 +36,8 @@ namespace {
boost::optional<uint64_t> metadata_snap; boost::optional<uint64_t> metadata_snap;
boost::optional<uint64_t> snap1; boost::optional<uint64_t> snap1;
boost::optional<uint64_t> snap2; boost::optional<uint64_t> snap2;
boost::optional<uint64_t> root1;
boost::optional<uint64_t> root2;
}; };
//-------------------------------- //--------------------------------
@ -481,9 +483,26 @@ namespace {
out << "</superblock>\n"; out << "</superblock>\n";
} }
void begin_diff(indented_stream &out, uint64_t snap1, uint64_t snap2) { // FIXME: always show the blocknr?
void begin_diff(indented_stream &out,
boost::optional<uint64_t> snap1,
boost::optional<uint64_t> root1,
boost::optional<uint64_t> snap2,
boost::optional<uint64_t> root2) {
out.indent(); out.indent();
out << "<diff left=\"" << snap1 << "\" right=\"" << snap2 << "\">\n"; out << "<diff";
if (snap1)
out << " left=\"" << *snap1 << "\"";
else if (root1)
out << " left_root=\"" << *root1 << "\"";
if (snap2)
out << " right=\"" << *snap2 << "\"";
else if (root2)
out << " right_root=\"" << *root2 << "\"";
out << ">\n";
out.inc(); out.inc();
} }
@ -505,8 +524,12 @@ namespace {
metadata::ptr md(fs.use_metadata_snap ? new metadata(bm, fs.metadata_snap) : new metadata(bm)); metadata::ptr md(fs.use_metadata_snap ? new metadata(bm, fs.metadata_snap) : new metadata(bm));
sb = md->sb_; sb = md->sb_;
dev_tree::key k = {*fs.snap1}; boost::optional<uint64_t> snap1_root;
boost::optional<uint64_t> snap1_root = md->mappings_top_level_->lookup(k); if (fs.snap1) {
dev_tree::key k = {*fs.snap1};
snap1_root = md->mappings_top_level_->lookup(k);
} else if (fs.root1)
snap1_root = *fs.root1;
if (!snap1_root) { if (!snap1_root) {
ostringstream out; ostringstream out;
@ -517,8 +540,12 @@ namespace {
single_mapping_tree snap1(*md->tm_, *snap1_root, single_mapping_tree snap1(*md->tm_, *snap1_root,
mapping_tree_detail::block_traits::ref_counter(md->tm_->get_sm())); mapping_tree_detail::block_traits::ref_counter(md->tm_->get_sm()));
k[0] = *fs.snap2; boost::optional<uint64_t> snap2_root;
boost::optional<uint64_t> snap2_root = md->mappings_top_level_->lookup(k); if (fs.snap2) {
dev_tree::key k = {*fs.snap2};
snap2_root = md->mappings_top_level_->lookup(k);
} else if (fs.root2)
snap2_root = *fs.root2;
if (!snap2_root) { if (!snap2_root) {
ostringstream out; ostringstream out;
@ -546,7 +573,7 @@ namespace {
sb.metadata_snap_ ? sb.metadata_snap_ ?
boost::optional<block_address>(sb.metadata_snap_) : boost::optional<block_address>(sb.metadata_snap_) :
boost::optional<block_address>()); boost::optional<block_address>());
begin_diff(is, *fs.snap1, *fs.snap2); begin_diff(is, fs.snap1, fs.root1, fs.snap2, fs.root2);
if (fs.verbose) { if (fs.verbose) {
verbose_emitter e(is); verbose_emitter e(is);
@ -586,8 +613,8 @@ thin_delta_cmd::usage(std::ostream &out) const
{ {
out << "Usage: " << get_name() << " [options] <device or file>\n" out << "Usage: " << get_name() << " [options] <device or file>\n"
<< "Options:\n" << "Options:\n"
<< " {--thin1, --snap1}\n" << " {--thin1, --snap1, --root1}\n"
<< " {--thin2, --snap2}\n" << " {--thin2, --snap2, --root2}\n"
<< " {-m, --metadata-snap} [block#]\n" << " {-m, --metadata-snap} [block#]\n"
<< " {--verbose}\n" << " {--verbose}\n"
<< " {-h|--help}\n" << " {-h|--help}\n"
@ -610,6 +637,8 @@ thin_delta_cmd::run(int argc, char **argv)
{ "thin2", required_argument, NULL, 2 }, { "thin2", required_argument, NULL, 2 },
{ "snap2", required_argument, NULL, 2 }, { "snap2", required_argument, NULL, 2 },
{ "verbose", no_argument, NULL, 4 }, { "verbose", no_argument, NULL, 4 },
{ "root1", required_argument, NULL, 5 },
{ "root2", required_argument, NULL, 6 },
{ NULL, no_argument, NULL, 0 } { NULL, no_argument, NULL, 0 }
}; };
@ -641,6 +670,14 @@ thin_delta_cmd::run(int argc, char **argv)
fs.verbose = true; fs.verbose = true;
break; break;
case 5:
fs.root1 = parse_uint64(optarg, "thin root 1");
break;
case 6:
fs.root2 = parse_uint64(optarg, "thin root 2");
break;
default: default:
usage(cerr); usage(cerr);
return 1; return 1;
@ -652,11 +689,15 @@ thin_delta_cmd::run(int argc, char **argv)
else else
fs.dev = argv[optind]; fs.dev = argv[optind];
if (!fs.snap1) if (!fs.snap1 && !fs.root1)
die("--snap1 not specified."); die("--snap1 or --root1 not specified.");
if (!!fs.snap1 && !!fs.root1)
die("--snap1 and --root1 are not compatible.");
if (!fs.snap2) if (!fs.snap2 && !fs.root2)
die("--snap2 not specified."); die("--snap2 or --root2 not specified.");
if (!!fs.snap2 && !!fs.root2)
die("--snap2 and --root2 are not compatible.");
return delta(fs); return delta(fs);
} }