From patchwork Tue Mar 15 01:45:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Wheeler X-Patchwork-Id: 8584731 Return-Path: X-Original-To: patchwork-dm-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7EF70C0553 for ; Tue, 15 Mar 2016 01:49:44 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 819D42027D for ; Tue, 15 Mar 2016 01:49:37 +0000 (UTC) Received: from mx3-phx2.redhat.com (mx3-phx2.redhat.com [209.132.183.24]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 65D6A20270 for ; Tue, 15 Mar 2016 01:49:35 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx3-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id u2F1jsVa009280; Mon, 14 Mar 2016 21:45:55 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id u2F1jrak017954 for ; Mon, 14 Mar 2016 21:45:53 -0400 Received: from mx1.redhat.com (ext-mx02.extmail.prod.ext.rdu2.redhat.com [10.11.55.2]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u2F1jr9b015053 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 14 Mar 2016 21:45:53 -0400 Received: from mail.ewheeler.net (mx.ewheeler.net [71.19.153.34]) by mx1.redhat.com (Postfix) with ESMTP id 8F1772A6E8; Tue, 15 Mar 2016 01:45:42 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by mail.ewheeler.net (Postfix) with ESMTP id E7E6DA05B0; Tue, 15 Mar 2016 01:45:38 +0000 (UTC) X-Virus-Scanned: amavisd-new at ewheeler.net Received: from mail.ewheeler.net ([127.0.0.1]) by localhost (mail.ewheeler.net [127.0.0.1]) (amavisd-new, port 10024) with LMTP id KtztuaMmyQjB; Tue, 15 Mar 2016 01:45:24 +0000 (UTC) Received: from 23-95-35-21-host.colocrossing.com (unknown [23.95.35.21]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.ewheeler.net (Postfix) with ESMTPSA id 64C6AA042C; Tue, 15 Mar 2016 01:45:24 +0000 (UTC) Date: Tue, 15 Mar 2016 01:45:15 +0000 (UTC) From: Eric Wheeler X-X-Sender: lists@mail.ewheeler.net To: Joe Thornber Message-ID: User-Agent: Alpine 2.11 (LRH 23 2013-08-11) MIME-Version: 1.0 X-RedHat-Spam-Score: 0.799 (BAYES_50, RP_MATCHES_RCVD) 71.19.153.34 mx.ewheeler.net 71.19.153.34 mx.ewheeler.net X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Scanned-By: MIMEDefang 2.78 on 10.11.55.2 X-loop: dm-devel@redhat.com Cc: dm-devel@redhat.com Subject: [dm-devel] [PATCH] thin_dump: added --device-id, --skip-mappings, and new output --format's X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hi Joe, Please review the patch below when you have a moment. I am interested in your feedback, and also interested in having this functionality merged upstream. This was written against thin-provisioning-tools.git tag v0.5.6. We use thin_dump on live dm-thin metadata snapshots all the time. In our case, we want to dump the XML for new (snapshot) volumes instead of dumping the entire 16gb metadata device (37.8% used) which takes ~20-30 minutes instead of ~5 seconds for a single volume with --device-id. I started by adding --device-id to pass the `block_address dev_id` and skip the call to emit_mappings() within mapping_tree_emitter::visit() unless the dev_id matches --device-id as passed to thin_dump. It is sometimes nice to list all of the device supers without waiting for emit_mappings() so I added the --skip-mappings option. This allows you to get the dev_id without reading the mappings: thin_dump --skip-mappings -m /dev/mapper/vg-p_tmeta Like `bool repair`, I added skip_mappings and dev_id as arguments to thin_provisioning::metadata_dump() and passed them down to mapping_tree_emitter with new members set_skip_mappings() and set_dev_id() to set private attributes (default values are assigned in metadata_dumper.h in case of backward compatible calls). We work with the device metadata in a simplified format, and without superblock information: origin_offset:length:tdata_offset (hence, "o:L:d" or "old") Therefore, the output --format 'old' was added. I added the format 'null' as well for benchmarking purposes so the ostream needn't write large volumes of text to /dev/null. Benchmarks of the various formats on our sample metadata snapshot on an idle machine: for i in xml human_readable old null; do time thin_dump -m -f $i /dev/mapper/vg-p_tmeta -o /dev/null done real user sys xml 29:01.27 25:35.87 01:54.49 human 27:39.81 24:12.90 01:52.39 old 27:07.71 23:40.64 01:52.97 null 23:39.38 21:17.22 00:49.04 I have this as a branch in bitbucket if you prefer to see it online: https://bitbucket.org/ewheelerinc/thin-provisioning-tools/branch/v0.5.6-device-id or git pull https://bitbucket.org/ewheelerinc/thin-provisioning-tools.git v0.5.6-device-id --- Eric Wheeler -- dm-devel mailing list dm-devel@redhat.com https://www.redhat.com/mailman/listinfo/dm-devel diff --git a/thin-provisioning/thin_dump.cc b/thin-provisioning/thin_dump.cc index 191acb5..7df5d85 100644 --- a/thin-provisioning/thin_dump.cc +++ b/thin-provisioning/thin_dump.cc @@ -22,6 +22,8 @@ #include #include "human_readable_format.h" +#include "old_format.h" +#include "null_format.h" #include "metadata_dumper.h" #include "metadata.h" #include "xml_format.h" @@ -36,6 +38,8 @@ using namespace thin_provisioning; struct flags { bool find_metadata_snap; bool repair; + block_address dev_id; + bool skip_mappings; }; namespace { @@ -49,12 +53,16 @@ namespace { e = create_xml_emitter(out); else if (format == "human_readable") e = create_human_readable_emitter(out); + else if (format == "old") + e = create_old_emitter(out); + else if (format == "null") + e = create_null_emitter(out); else { cerr << "unknown format '" << format << "'" << endl; exit(1); } - metadata_dump(md, e, flags.repair); + metadata_dump(md, e, flags.repair, flags.skip_mappings, flags.dev_id); } catch (std::exception &e) { cerr << e.what() << endl; @@ -77,10 +85,12 @@ namespace { out << "Usage: " << cmd << " [options] {device|file}" << endl << "Options:" << endl << " {-h|--help}" << endl - << " {-f|--format} {xml|human_readable}" << endl + << " {-f|--format} {xml|human_readable|old|null}" << endl << " {-r|--repair}" << endl << " {-m|--metadata-snap} [block#]" << endl << " {-o }" << endl + << " {-d device_id}" << endl + << " {-s|--skip-mappings}" << endl << " {-V|--version}" << endl; } } @@ -89,17 +99,20 @@ int thin_dump_main(int argc, char **argv) { int c; char const *output = NULL; - const char shortopts[] = "hm::o:f:rV"; + const char shortopts[] = "hm::o:sd:f:rV"; char *end_ptr; string format = "xml"; block_address metadata_snap = 0; struct flags flags; - flags.find_metadata_snap = flags.repair = false; + flags.find_metadata_snap = flags.repair = flags.skip_mappings = false; + flags.dev_id = -1; const struct option longopts[] = { { "help", no_argument, NULL, 'h'}, { "metadata-snap", optional_argument, NULL, 'm' }, { "output", required_argument, NULL, 'o'}, + { "skip-mappings", no_argument, NULL, 's'}, + { "device-id", required_argument, NULL, 'd'}, { "format", required_argument, NULL, 'f' }, { "repair", no_argument, NULL, 'r'}, { "version", no_argument, NULL, 'V'}, @@ -120,6 +133,19 @@ int thin_dump_main(int argc, char **argv) flags.repair = true; break; + case 's': + flags.skip_mappings = true; + break; + + case 'd': + flags.dev_id = strtoull(optarg, &end_ptr, 10); + if (end_ptr == optarg) { + cerr << "couldn't parse " << endl; + usage(cerr, basename(argv[0])); + return 1; + } + break; + case 'm': if (optarg) { metadata_snap = strtoull(optarg, &end_ptr, 10); @@ -147,6 +173,12 @@ int thin_dump_main(int argc, char **argv) } } + if (format != "old" && flags.dev_id < 0) { + cerr << "Output format 'old' must specify --device-id" << endl; + return 1; + } + + if (argc == optind) { cerr << "No input file provided." << endl; usage(cerr, basename(argv[0])); diff --git a/thin-provisioning/metadata_dumper.h b/thin-provisioning/metadata_dumper.h index c96d22e..9d9814e 100644 --- a/thin-provisioning/metadata_dumper.h +++ b/thin-provisioning/metadata_dumper.h @@ -28,7 +28,7 @@ namespace thin_provisioning { // Set the @repair flag if your metadata is corrupt, and you'd like // the dumper to do it's best to recover info. If not set, any // corruption encountered will cause an exception to be thrown. - void metadata_dump(metadata::ptr md, emitter::ptr e, bool repair); + void metadata_dump(metadata::ptr md, emitter::ptr e, bool repair, bool skip_mappings = false, block_address dev_id = -1); } //---------------------------------------------------------------- diff --git a/thin-provisioning/metadata_dumper.cc b/thin-provisioning/metadata_dumper.cc index db656ee..55cbae8 100644 --- a/thin-provisioning/metadata_dumper.cc +++ b/thin-provisioning/metadata_dumper.cc @@ -171,23 +171,31 @@ namespace { dd_(dd), repair_(repair), damage_policy_(damage_policy) { + dev_id_ = -1; + skip_mappings_ = false; } + void set_dev_id(block_address dev_id) { dev_id_ = dev_id; } + void set_skip_mappings(bool skip) { skip_mappings_ = skip; } + void visit(btree_path const &path, block_address tree_root) { block_address dev_id = path[0]; dd_map::const_iterator it = dd_.find(path[0]); if (it != dd_.end()) { device_tree_detail::device_details const &d = it->second; - e_->begin_device(dev_id, - d.mapped_blocks_, - d.transaction_id_, - d.creation_time_, - d.snapshotted_time_); + if (dev_id_ == -1UL || dev_id == dev_id_) { + e_->begin_device(dev_id, + d.mapped_blocks_, + d.transaction_id_, + d.creation_time_, + d.snapshotted_time_); - emit_mappings(tree_root); + if (!skip_mappings_) + emit_mappings(tree_root); - e_->end_device(); + e_->end_device(); + } } else if (!repair_) { ostringstream msg; @@ -209,6 +217,8 @@ namespace { emitter::ptr e_; dd_map const &dd_; bool repair_; + block_address dev_id_; + bool skip_mappings_; mapping_tree_detail::damage_visitor::ptr damage_policy_; }; } @@ -216,7 +226,7 @@ namespace { //---------------------------------------------------------------- void -thin_provisioning::metadata_dump(metadata::ptr md, emitter::ptr e, bool repair) +thin_provisioning::metadata_dump(metadata::ptr md, emitter::ptr e, bool repair, bool skip_mappings, block_address dev_id) { details_extractor de; device_tree_detail::damage_visitor::ptr dd_policy(details_damage_policy(repair)); @@ -231,6 +241,11 @@ thin_provisioning::metadata_dump(metadata::ptr md, emitter::ptr e, bool repair) { mapping_tree_detail::damage_visitor::ptr md_policy(mapping_damage_policy(repair)); mapping_tree_emitter mte(md, e, de.get_details(), repair, mapping_damage_policy(repair)); + + mte.set_skip_mappings(skip_mappings); + + if (dev_id >= 0) + mte.set_dev_id(dev_id); walk_mapping_tree(*md->mappings_top_level_, mte, *md_policy); } diff --git a/man8/thin_dump.8 b/man8/thin_dump.8 index 7a9f785..9e0bf9e 100644 --- a/man8/thin_dump.8 +++ b/man8/thin_dump.8 @@ -26,9 +26,19 @@ in order to put it back onto a metadata This tool cannot be run on live metadata unless the \fB\-\-metadata\-snap\fP option is used. -.IP "\fB\-f, \-\-format\fP \fI{xml|human_readable}\fP". +.IP "\fB\-f, \-\-format\fP \fI{xml|human_readable|old|null}\fP". Print output in XML or human readable format. - +.sp +The +.B old +format requires the --device-id option and emits in the +following format, one record per line: +.B offset:length:tdata_offset +(hence, "o:L:d") with units in bytes. +.sp +The +.B null +format emits nothing and only walks the tree. .IP "\fB\-r, \-\-repair\fP". Repair the metadata whilst dumping it. @@ -39,6 +49,17 @@ the thin provisioning device-mapper target, else try the one at block#. See the thin provisioning target documentation on how to create or release a metadata snapshot and retrieve the block number from the kernel. +.IP "\fB\-d, \-\-skip\-mappings\fP". +Skip emission of the mappings. This outputs nothing if format is +either of +.B old +or +.B null +. + +.IP "\fB\-d, \-\-device\-id\fP". +Specify the device_id to be dumped. + .IP "\fB\-h, \-\-help\fP". Print help and exit. diff --git a/Makefile.in b/Makefile.in index e67b300..078bb53 100644 --- a/Makefile.in +++ b/Makefile.in @@ -73,6 +73,8 @@ SOURCE=\ persistent-data/validators.cc \ thin-provisioning/device_tree.cc \ thin-provisioning/human_readable_format.cc \ + thin-provisioning/old_format.cc \ + thin-provisioning/null_format.cc \ thin-provisioning/mapping_tree.cc \ thin-provisioning/metadata.cc \ thin-provisioning/metadata_checker.cc \ diff --git a/thin-provisioning/old_format.h b/thin-provisioning/old_format.h new file mode 100644 index 0000000..dba69e9 --- /dev/null +++ b/thin-provisioning/old_format.h @@ -0,0 +1,34 @@ +// Copyright (C) 2011 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#ifndef OLD_FORMAT_H +#define OLD_FORMAT_H + +#include "emitter.h" + +#include + +//---------------------------------------------------------------- + +namespace thin_provisioning { + emitter::ptr create_old_emitter(std::ostream &out); +} + +//---------------------------------------------------------------- + +#endif diff --git a/thin-provisioning/old_format.cc b/thin-provisioning/old_format.cc new file mode 100644 index 0000000..52056c8 --- /dev/null +++ b/thin-provisioning/old_format.cc @@ -0,0 +1,103 @@ +// Copyright (C) 2011 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#include "old_format.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; + } + + class old_emitter : public emitter { + public: + old_emitter(ostream &out) + : out_(out) { + } + + void begin_superblock(string const &uuid, + uint64_t time, + uint64_t trans_id, + uint32_t data_block_size, + uint64_t nr_data_blocks, + boost::optional metadata_snap) { + data_block_size_ = data_block_size; + } + + 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) { + } + + void end_device() { + } + + 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 data_begin, uint32_t time, uint64_t len) { + out_ << (data_block_size_ << 9)*origin_begin + << ":" << (data_block_size_ << 9)*len + << ":" << (data_block_size_ << 9)*data_begin + << endl; + } + + void single_map(uint64_t origin_block, uint64_t data_block, uint32_t time) { + out_ << (data_block_size_ << 9)*origin_block + << ":" << (data_block_size_ << 9) + << ":" << (data_block_size_ << 9)*data_block + << endl; + } + + private: + ostream &out_; + uint64_t data_block_size_; + }; +} + +//---------------------------------------------------------------- + +thin_provisioning::emitter::ptr +thin_provisioning::create_old_emitter(ostream &out) +{ + return emitter::ptr(new old_emitter(out)); +} + +//---------------------------------------------------------------- diff --git a/thin-provisioning/null_format.h b/thin-provisioning/null_format.h new file mode 100644 index 0000000..2688762 --- /dev/null +++ b/thin-provisioning/null_format.h @@ -0,0 +1,34 @@ +// Copyright (C) 2011 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#ifndef NULL_FORMAT_H +#define NULL_FORMAT_H + +#include "emitter.h" + +#include + +//---------------------------------------------------------------- + +namespace thin_provisioning { + emitter::ptr create_null_emitter(std::ostream &out); +} + +//---------------------------------------------------------------- + +#endif diff --git a/thin-provisioning/null_format.cc b/thin-provisioning/null_format.cc new file mode 100644 index 0000000..b1baa7d --- /dev/null +++ b/thin-provisioning/null_format.cc @@ -0,0 +1,92 @@ +// Copyright (C) 2011 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#include "null_format.h" + +#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; + } + + class null_emitter : public emitter { + public: + null_emitter(ostream &out) + : out_(out) { + } + + void begin_superblock(string const &uuid, + uint64_t time, + uint64_t trans_id, + 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) { + } + + void end_device() { + } + + 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 data_begin, uint32_t time, uint64_t len) { + } + + void single_map(uint64_t origin_block, uint64_t data_block, uint32_t time) { + } + + private: + ostream &out_; + }; +} + +//---------------------------------------------------------------- + +thin_provisioning::emitter::ptr +thin_provisioning::create_null_emitter(ostream &out) +{ + return emitter::ptr(new null_emitter(out)); +} + +//---------------------------------------------------------------- diff --git a/thin-provisioning/null_format.h b/thin-provisioning/null_format.h new file mode 100644 index 0000000..2688762 --- /dev/null +++ b/thin-provisioning/null_format.h @@ -0,0 +1,34 @@ +// Copyright (C) 2011 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#ifndef NULL_FORMAT_H +#define NULL_FORMAT_H + +#include "emitter.h" + +#include + +//---------------------------------------------------------------- + +namespace thin_provisioning { + emitter::ptr create_null_emitter(std::ostream &out); +} + +//---------------------------------------------------------------- + +#endif diff --git a/thin-provisioning/null_format.cc b/thin-provisioning/null_format.cc new file mode 100644 index 0000000..b1baa7d --- /dev/null +++ b/thin-provisioning/null_format.cc @@ -0,0 +1,92 @@ +// Copyright (C) 2011 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#include "null_format.h" + +#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; + } + + class null_emitter : public emitter { + public: + null_emitter(ostream &out) + : out_(out) { + } + + void begin_superblock(string const &uuid, + uint64_t time, + uint64_t trans_id, + 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) { + } + + void end_device() { + } + + 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 data_begin, uint32_t time, uint64_t len) { + } + + void single_map(uint64_t origin_block, uint64_t data_block, uint32_t time) { + } + + private: + ostream &out_; + }; +} + +//---------------------------------------------------------------- + +thin_provisioning::emitter::ptr +thin_provisioning::create_null_emitter(ostream &out) +{ + return emitter::ptr(new null_emitter(out)); +} + +//----------------------------------------------------------------