From 6c4f3ad2ff45567023dcdfd73b2c0cc66fa51fdb Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Thu, 24 Mar 2016 14:44:13 +0000 Subject: [PATCH] [contrib/ tmakatos_emitter for thin_dump --- contrib/Makefile.in | 12 ++- contrib/tmakatos_emitter.cc | 151 ++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 contrib/tmakatos_emitter.cc diff --git a/contrib/Makefile.in b/contrib/Makefile.in index a47c8e2..58cfefc 100644 --- a/contrib/Makefile.in +++ b/contrib/Makefile.in @@ -1,7 +1,15 @@ -contrib: contrib/thin_sexp_emitter.so +PLUGINS=\ + contrib/thin_sexp_emitter.so \ + contrib/tmakatos_emitter.so + +contrib: $(PLUGINS) contrib/thin_sexp_emitter.so: contrib/thin_sexp_emitter.o $(V)echo " [LD] $@" - $(V)$(CC) -shared -Wl,-soname,thin_sexp_emitter.so -o contrib/thin_sexp_emitter.so contrib/thin_sexp_emitter.o + $(V)$(CC) -shared -Wl,-soname,thin_sexp_emitter.so -o $@ $< + +contrib/tmakatos_emitter.so: contrib/tmakatos_emitter.o + $(V)echo " [LD] $@" + $(V)$(CC) -shared -Wl,-soname,tmakatos_emitter.so -o $@ $< diff --git a/contrib/tmakatos_emitter.cc b/contrib/tmakatos_emitter.cc new file mode 100644 index 0000000..4699077 --- /dev/null +++ b/contrib/tmakatos_emitter.cc @@ -0,0 +1,151 @@ +#include "thin-provisioning/emitter.h" + +#include +#include + +using namespace std; +using namespace thin_provisioning; + +//---------------------------------------------------------------- + +namespace { + template + std::ostream &operator << (ostream &out, boost::optional const &maybe) { + if (maybe) + out << *maybe; + + return out; + } + + //------------------------------------------------ + // binary generator + //------------------------------------------------ + class binary_emitter : public emitter { + public: + binary_emitter(ostream &out) + : out_(out) { + } + + void begin_superblock(string const &uuid, + uint64_t time, + uint64_t trans_id, + boost::optional flags, + boost::optional version, + uint32_t data_block_size, + uint64_t nr_data_blocks, + boost::optional metadata_snap) { + } + + void end_superblock() { + } + + void begin_device(uint32_t dev_id, + uint64_t mapped_blocks, + uint64_t trans_id, + uint64_t creation_time, + uint64_t snap_time) { + cur = 0; + bitmap = 0; + } + + void end_device() { + emit_bmp(true); + } + + void begin_named_mapping(string const &name) { } + + void end_named_mapping() { } + + void identifier(string const &name) { } + void range_map(uint64_t origin_begin, uint64_t, uint32_t, + uint64_t len) { + + uint64_t n = origin_begin / unit; + uint64_t i; + + assert(n >= cur); + assert(len > 0); + + /* + * Cover the gap between the last emitted unit and the current one. + */ + if (n > cur) + do { emit_bmp(); } while (cur < n); + + /* + * Emit partial unit. + */ + if (origin_begin & (unit - 1)) { + const uint64_t j = min(len, + (origin_begin & ~(unit - 1)) + unit - origin_begin); + for (i = origin_begin; i < origin_begin + j; i++) + bitmap |= 1ULL << (i & (unit - 1)); + if (j == len) + return; + + emit_bmp(); + + len -= j; + origin_begin = i; + } + + /* + * Emit full units until end. + */ + n = (origin_begin + len) / unit; + while (cur < n) { + bitmap = ~0; + emit_bmp(); + len -= unit; + } + origin_begin = cur * unit; + + /* + * Emit final unit. + */ + for (i = origin_begin; i < origin_begin + len; i++) + bitmap |= 1ULL << (i & (unit - 1)); + } + + void single_map(uint64_t origin_block, uint64_t, uint32_t) { + range_map(origin_block, 0, 0, 1); + } + + private: + ostream &out_; + + /** + * The entire virtual block allocation bitmap is segmented into 64-bit + * sub-bitmaps (units). + */ + uint64_t bitmap; + + /* + * Pointer to the current sub-bitmap (unit) that has not yet been + * emitted. + */ + uint64_t cur; + + /** + * Unit (sub-bitmap) size. Must be a power of 2. + */ + static const size_t unit = sizeof bitmap * CHAR_BIT; + + void emit_bmp(bool omit_if_zero = false) { + if (!bitmap && omit_if_zero) + out_.write((const char*)&bitmap, sizeof bitmap); + bitmap = 0; + cur++; + } + }; +} + +//---------------------------------------------------------------- + +extern "C" { + emitter::ptr create_emitter(ostream &out) { + return emitter::ptr(new binary_emitter(out)); + } +} + +//----------------------------------------------------------------