[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:

  <same begin="0" length="1"/>
  <different begin="1" length="4"/>
  <same begin="5" length="1"/>
  <different begin="6" length="6"/>
  <same begin="12" length="1"/>
  <different begin="13" length="9"/>
  <same begin="22" length="1"/>
  <different begin="23" length="4"/>
  <same begin="27" length="1"/>
  <different begin="28" length="3"/>
  <same begin="31" length="1"/>
  <different begin="32" length="1"/>

The old format is available using the --verbose switch:

  <same>
    <range begin="0" data_begin="0" length="1"/>
  </same>

  <different>
    <range begin="1" left_data_begin="24576" right_data_begin="16384" length="1"/>
    <range begin="2" left_data_begin="24577" right_data_begin="2" length="1"/>
    <range begin="3" left_data_begin="24578" right_data_begin="16385" length="1"/>
    <range begin="4" left_data_begin="24579" right_data_begin="4" length="1"/>
  </different>

  <same>
    <range begin="5" data_begin="5" length="1"/>
  </same>

  <different>
    <range begin="6" left_data_begin="24580" right_data_begin="16386" length="1"/>
    <range begin="7" left_data_begin="7" right_data_begin="16387" length="1"/>
    <range begin="8" left_data_begin="24581" right_data_begin="8" length="1"/>
    <range begin="9" left_data_begin="24582" right_data_begin="16388" length="1"/>
    <range begin="10" left_data_begin="10" right_data_begin="16389" length="1"/>
    <range begin="11" left_data_begin="24583" right_data_begin="11" length="1"/>
  </different>

  <same>
    <range begin="12" data_begin="12" length="1"/>
  </same>

  <different>
    <range begin="13" left_data_begin="24584" right_data_begin="13" length="1"/>
    <range begin="14" left_data_begin="24585" right_data_begin="16390" length="1"/>
    <range begin="15" left_data_begin="24586" right_data_begin="15" length="1"/>
    <range begin="16" left_data_begin="16" right_data_begin="16391" length="1"/>
    <range begin="17" left_data_begin="24587" right_data_begin="16392" length="1"/>
    <range begin="18" left_data_begin="18" right_data_begin="16393" length="3"/>
    <range begin="21" left_data_begin="24588" right_data_begin="21" length="1"/>
  </different>

  <same>
    <range begin="22" data_begin="22" length="1"/>
  </same>

  <different>
    <range begin="23" left_data_begin="24589" right_data_begin="23" length="1"/>
    <range begin="24" left_data_begin="24590" right_data_begin="16396" length="1"/>
    <range begin="25" left_data_begin="24591" right_data_begin="25" length="1"/>
    <range begin="26" left_data_begin="26" right_data_begin="16397" length="1"/>
  </different>

  <same>
    <range begin="27" data_begin="27" length="1"/>
  </same>

  <different>
    <range begin="28" left_data_begin="24592" right_data_begin="28" length="2"/>
    <range begin="30" left_data_begin="30" right_data_begin="16398" length="1"/>
  </different>

  <same>
    <range begin="31" data_begin="31" length="1"/>
  </same>

  <different>
    <range begin="32" left_data_begin="24594" right_data_begin="32" length="1"/>
  </different>
This commit is contained in:
Joe Thornber 2014-06-17 14:20:33 +01:00
parent 0e62a1c4de
commit bb57104542

View File

@ -56,9 +56,14 @@ namespace {
};
struct flags {
flags()
: verbose(false) {
}
boost::optional<string> dev;
boost::optional<uint64_t> snap1;
boost::optional<uint64_t> 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() << "<left_only";
break;
case RIGHT_ONLY:
out() << "<right_only";
break;
case DIFFER:
out() << "<different";
break;
case SAME:
out() << "<same";
break;
}
out() << " begin=\"" << vbegin_ << "\""
<< " length=\"" << vend_ - vbegin_ << "\"/>\n";
}
boost::optional<block_type> 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_ << " <rang begin=\"" << vbegin << "\""
<< " data_begin=\"" << dbegin << "\""
<< " length=\"" << len << "\"/>\n";
out() << " <range begin=\"" << vbegin << "\""
<< " data_begin=\"" << dbegin << "\""
<< " length=\"" << len << "\"/>\n";
}
void right_only(uint64_t vbegin, uint64_t dbegin, uint64_t len) {
begin_block(RIGHT_ONLY);
out_ << " <range begin=\"" << vbegin << "\""
<< " data_begin=\"" << dbegin << "\""
<< " length=\"" << len << "\"/>\n";
out() << " <range begin=\"" << vbegin << "\""
<< " data_begin=\"" << dbegin << "\""
<< " length=\"" << len << "\"/>\n";
}
void blocks_differ(uint64_t vbegin, uint64_t left_dbegin, uint64_t right_dbegin, uint64_t len) {
begin_block(DIFFER);
out_ << " <range begin=\"" << vbegin << "\""
<< " left_data_begin=\"" << left_dbegin << "\""
<< " right_data_begin=\"" << right_dbegin << "\""
<< " length=\"" << len << "\"/>\n";
out() << " <range begin=\"" << vbegin << "\""
<< " left_data_begin=\"" << left_dbegin << "\""
<< " right_data_begin=\"" << right_dbegin << "\""
<< " length=\"" << len << "\"/>\n";
}
void blocks_same(uint64_t vbegin, uint64_t dbegin, uint64_t len) {
begin_block(SAME);
out_ << " <range begin=\"" << vbegin << "\""
<< " data_begin=\"" << dbegin << "\""
<< " length=\"" << len << "\"/>\n";
out() << " <range begin=\"" << vbegin << "\""
<< " data_begin=\"" << dbegin << "\""
<< " length=\"" << len << "\"/>\n";
}
void complete() {
@ -234,19 +340,19 @@ namespace {
void open(block_type t) {
switch (t) {
case LEFT_ONLY:
out_ << "<left_only>\n";
out() << "<left_only>\n";
break;
case RIGHT_ONLY:
out_ << "<right_only>\n";
out() << "<right_only>\n";
break;
case DIFFER:
out_ << "<different>\n";
out() << "<different>\n";
break;
case SAME:
out_ << "<same>\n";
out() << "<same>\n";
break;
}
}
@ -254,34 +360,32 @@ namespace {
void close(block_type t) {
switch (t) {
case LEFT_ONLY:
out_ << "</left_only>\n\n";
out() << "</left_only>\n\n";
break;
case RIGHT_ONLY:
out_ << "</right_only>\n\n";
out() << "</right_only>\n\n";
break;
case DIFFER:
out_ << "</different>\n\n";
out() << "</different>\n\n";
break;
case SAME:
out_ << "</same>\n\n";
out() << "</same>\n\n";
break;
}
}
boost::optional<block_type> 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;