diff --git a/thin-provisioning/thin_delta.cc b/thin-provisioning/thin_delta.cc index b0c460d..196887d 100644 --- a/thin-provisioning/thin_delta.cc +++ b/thin-provisioning/thin_delta.cc @@ -6,9 +6,11 @@ #include "version.h" +#include "base/indented_stream.h" #include "persistent-data/data-structures/btree_damage_visitor.h" #include "persistent-data/run.h" #include "persistent-data/space-maps/core.h" +#include "persistent-data/space-maps/disk.h" #include "persistent-data/file_utils.h" #include "thin-provisioning/superblock.h" #include "thin-provisioning/mapping_tree.h" @@ -27,8 +29,11 @@ namespace local { } void usage(ostream &out) { - out << "Usage: " << cmd_ << " [options] --snap1 --snap2 \n" + out << "Usage: " << cmd_ << " [options] \n" << "Options:\n" + << " {--thin1, --snap1}\n" + << " {--thin2, --snap2}\n" + << " {-m, --metadata-snap}\n" << " {--verbose}\n" << " {-h|--help}\n" << " {-V|--version}" << endl; @@ -201,7 +206,7 @@ namespace local { class diff_emitter { public: - diff_emitter(ostream &out) + diff_emitter(indented_stream &out) : out_(out) { } @@ -212,18 +217,22 @@ namespace local { virtual void complete() = 0; protected: - ostream &out() { + void indent() { + out_.indent(); + } + + indented_stream &out() { return out_; } private: - ostream &out_; + indented_stream &out_; }; class simple_emitter : public diff_emitter { public: - simple_emitter(ostream &out) + simple_emitter(indented_stream &out) : diff_emitter(out) { } @@ -272,6 +281,7 @@ namespace local { if (!current_type_) return; + indent(); switch (*current_type_) { case LEFT_ONLY: out() << "\n"; } void right_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) { begin_block(RIGHT_ONLY); - out() << " \n"; } void blocks_differ(uint64_t vbegin, uint64_t left_dbegin, uint64_t right_dbegin, uint64_t len) { begin_block(DIFFER); - out() << " \n"; @@ -328,7 +341,8 @@ namespace local { void blocks_same(uint64_t vbegin, uint64_t dbegin, uint64_t len) { begin_block(SAME); - out() << " \n"; } @@ -359,6 +373,7 @@ namespace local { } void open(block_type t) { + indent(); switch (t) { case LEFT_ONLY: out() << "\n"; @@ -376,24 +391,27 @@ namespace local { out() << "\n"; break; } + out().inc(); } void close(block_type t) { + out().dec(); + indent(); switch (t) { case LEFT_ONLY: - out() << "\n\n"; + out() << "\n"; break; case RIGHT_ONLY: - out() << "\n\n"; + out() << "\n"; break; case DIFFER: - out() << "\n\n"; + out() << "\n"; break; case SAME: - out() << "\n\n"; + out() << "\n"; break; } @@ -466,16 +484,59 @@ namespace local { 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 metadata_snap) { + out.indent(); + out << "\n"; + out.inc(); + } + + void end_superblock(indented_stream &out) { + out.dec(); + out.indent(); + out << "\n"; + } + + void begin_diff(indented_stream &out, uint64_t snap1, uint64_t snap2) { + out.indent(); + out << "\n"; + out.inc(); + } + + void end_diff(indented_stream &out) { + out.dec(); + out.indent(); + out << "\n"; + } + void delta_(application &app, flags const &fs) { mapping_recorder mr1; mapping_recorder mr2; damage_visitor damage_v; + superblock_detail::superblock sb; + checked_space_map::ptr data_sm; { block_manager<>::ptr bm = open_bm(*fs.dev); 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(&sb.data_space_map_root_)); dev_tree dtree(*tm, sb.data_mapping_root_, mapping_tree_detail::mtree_traits::ref_counter(tm)); @@ -508,13 +569,26 @@ namespace local { 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(sb.metadata_snap_) : + boost::optional()); + begin_diff(is, *fs.snap1, *fs.snap2); + if (fs.verbose) { - verbose_emitter e(cout); + verbose_emitter e(is); dump_diff(mr1.get_mappings(), mr2.get_mappings(), e); } else { - simple_emitter e(cout); + simple_emitter e(is); dump_diff(mr1.get_mappings(), mr2.get_mappings(), e); } + + end_diff(is); + end_superblock(is); } int delta(application &app, flags const &fs) { @@ -541,13 +615,15 @@ int thin_delta_main(int argc, char **argv) flags fs; local::application app(basename(argv[0])); - char const shortopts[] = "hV"; + char const shortopts[] = "hVm"; option const longopts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, + { "thin1", required_argument, NULL, 1 }, { "snap1", required_argument, NULL, 1 }, + { "thin2", 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 } }; @@ -569,7 +645,7 @@ int thin_delta_main(int argc, char **argv) fs.snap2 = app.parse_snap(optarg); break; - case 3: + case 'm': abort(); break;