From bb571045424d9eb1f62616c202c10c354b62b22e Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Tue, 17 Jun 2014 14:20:33 +0100 Subject: [PATCH] [thin_delta] By default output a simpler format that ignores the data locations. Most people will access the data via the thin device itself, so there's really no need to output the locations of the data on pool device. Doing this allows us to run together adjacent thin blocks (even if they are not adjacent on the pool dev). Simple format: The old format is available using the --verbose switch: --- thin-provisioning/thin_delta.cc | 173 +++++++++++++++++++++++++++----- 1 file changed, 146 insertions(+), 27 deletions(-) diff --git a/thin-provisioning/thin_delta.cc b/thin-provisioning/thin_delta.cc index d0d5fee..186a38c 100644 --- a/thin-provisioning/thin_delta.cc +++ b/thin-provisioning/thin_delta.cc @@ -56,9 +56,14 @@ namespace { }; struct flags { + flags() + : verbose(false) { + } + boost::optional dev; boost::optional snap1; boost::optional snap2; + bool verbose; }; //-------------------------------- @@ -171,39 +176,140 @@ namespace { } }; + //-------------------------------- + class diff_emitter { public: diff_emitter(ostream &out) : out_(out) { } + virtual void left_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) = 0; + virtual void right_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) = 0; + virtual void blocks_differ(uint64_t vbegin, uint64_t left_dbegin, uint64_t right_dbegin, uint64_t len) = 0; + virtual void blocks_same(uint64_t vbegin, uint64_t dbegin, uint64_t len) = 0; + virtual void complete() = 0; + + protected: + ostream &out() { + return out_; + } + + private: + ostream &out_; + }; + + + class simple_emitter : public diff_emitter { + public: + simple_emitter(ostream &out) + : diff_emitter(out) { + } + + void left_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) { + add_range(LEFT_ONLY, vbegin, len); + } + + void right_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) { + add_range(RIGHT_ONLY, vbegin, len); + } + + void blocks_differ(uint64_t vbegin, uint64_t left_dbegin, uint64_t right_dbegin, uint64_t len) { + add_range(DIFFER, vbegin, len); + } + + void blocks_same(uint64_t vbegin, uint64_t dbegin, uint64_t len) { + add_range(SAME, vbegin, len); + } + + void complete() { + if (current_type_) + emit_range(); + } + + private: + enum block_type { + LEFT_ONLY, + RIGHT_ONLY, + DIFFER, + SAME + }; + + void add_range(block_type t, uint64_t vbegin, uint64_t len) { + if (current_type_ && *current_type_ == t && vbegin == vend_) { + vend_ += len; + return; + } + + emit_range(); + current_type_ = t; + vbegin_ = vbegin; + vend_ = vbegin_ + len; + } + + void emit_range() { + if (!current_type_) + return; + + switch (*current_type_) { + case LEFT_ONLY: + out() << "\n"; + } + + boost::optional current_type_; + uint64_t vbegin_, vend_; + }; + + class verbose_emitter : public diff_emitter { + public: + verbose_emitter(ostream &out) + : diff_emitter(out) { + } + void left_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) { begin_block(LEFT_ONLY); - out_ << " \n"; + out() << " \n"; } void right_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) { begin_block(RIGHT_ONLY); - out_ << " \n"; + out() << " \n"; } void blocks_differ(uint64_t vbegin, uint64_t left_dbegin, uint64_t right_dbegin, uint64_t len) { begin_block(DIFFER); - out_ << " \n"; + out() << " \n"; } void blocks_same(uint64_t vbegin, uint64_t dbegin, uint64_t len) { begin_block(SAME); - out_ << " \n"; + out() << " \n"; } void complete() { @@ -234,19 +340,19 @@ namespace { void open(block_type t) { switch (t) { case LEFT_ONLY: - out_ << "\n"; + out() << "\n"; break; case RIGHT_ONLY: - out_ << "\n"; + out() << "\n"; break; case DIFFER: - out_ << "\n"; + out() << "\n"; break; case SAME: - out_ << "\n"; + out() << "\n"; break; } } @@ -254,34 +360,32 @@ namespace { void close(block_type t) { switch (t) { case LEFT_ONLY: - out_ << "\n\n"; + out() << "\n\n"; break; case RIGHT_ONLY: - out_ << "\n\n"; + out() << "\n\n"; break; case DIFFER: - out_ << "\n\n"; + out() << "\n\n"; break; case SAME: - out_ << "\n\n"; + out() << "\n\n"; break; } } boost::optional current_type_; - ostream &out_; }; //---------------------------------------------------------------- void dump_diff(mapping_deque const &left, - mapping_deque const &right) { - - diff_emitter e(cout); + mapping_deque const &right, + diff_emitter &e) { // We iterate through both sets of mappings in parallel // noting any differences. @@ -366,7 +470,13 @@ namespace { btree_visit_values(snap2, mr2, damage_v); } - dump_diff(mr1.get_mappings(), mr2.get_mappings()); + if (fs.verbose) { + verbose_emitter e(cout); + dump_diff(mr1.get_mappings(), mr2.get_mappings(), e); + } else { + simple_emitter e(cout); + dump_diff(mr1.get_mappings(), mr2.get_mappings(), e); + } } int delta(application &app, flags const &fs) { @@ -397,7 +507,8 @@ int main(int argc, char **argv) { "version", no_argument, NULL, 'V' }, { "snap1", required_argument, NULL, 1 }, { "snap2", required_argument, NULL, 2 }, - { "metadata-snap", optional_argument, NULL, 3 }, + { "metadata-snap", no_argument, NULL, 3 }, + { "verbose", no_argument, NULL, 4 } }; while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { @@ -418,6 +529,14 @@ int main(int argc, char **argv) fs.snap2 = app.parse_snap(optarg); break; + case 3: + abort(); + break; + + case 4: + fs.verbose = true; + break; + default: app.usage(cerr); return 1;