[thin_dump] --format custom=<shared lib>
Allow people to use their own emitters held in a shared library. Put a trivial emitter in contrib/ as an example.
This commit is contained in:
parent
872a933072
commit
c7813e07e4
@ -91,6 +91,7 @@ SOURCE=\
|
||||
thin-provisioning/restore_emitter.cc \
|
||||
thin-provisioning/rmap_visitor.cc \
|
||||
thin-provisioning/superblock.cc \
|
||||
thin-provisioning/shared_library_emitter.cc \
|
||||
thin-provisioning/thin_check.cc \
|
||||
thin-provisioning/thin_delta.cc \
|
||||
thin-provisioning/thin_dump.cc \
|
||||
@ -123,9 +124,9 @@ STRIP:=@STRIP@
|
||||
OBJECTS:=$(subst .cc,.o,$(SOURCE))
|
||||
TOP_DIR:=@top_srcdir@
|
||||
TOP_BUILDDIR:=@top_builddir@
|
||||
CFLAGS+=-g -Wall -O3
|
||||
CFLAGS+=-g -Wall -O3 -fPIC
|
||||
CFLAGS+=@LFS_FLAGS@
|
||||
CXXFLAGS+=-g -Wall -fno-strict-aliasing -std=c++11
|
||||
CXXFLAGS+=-g -Wall -fPIC -fno-strict-aliasing -std=c++11
|
||||
|
||||
ifeq ("@DEVTOOLS@", "yes")
|
||||
CXXFLAGS+=-DDEV_TOOLS
|
||||
@ -260,6 +261,7 @@ endif
|
||||
|
||||
ifeq ("@TESTING@", "yes")
|
||||
include unit-tests/Makefile
|
||||
include contrib/Makefile
|
||||
|
||||
.PHONEY: features
|
||||
|
||||
|
@ -188,6 +188,7 @@ dnl -- First and last lines should not contain files to generate in order to
|
||||
dnl -- keep utility scripts running properly
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
contrib/Makefile
|
||||
unit-tests/Makefile
|
||||
version.h
|
||||
])
|
||||
|
7
contrib/Makefile.in
Normal file
7
contrib/Makefile.in
Normal file
@ -0,0 +1,7 @@
|
||||
contrib: contrib/thin_sexp_emitter.so
|
||||
|
||||
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
|
||||
|
||||
|
120
contrib/thin_sexp_emitter.cc
Normal file
120
contrib/thin_sexp_emitter.cc
Normal file
@ -0,0 +1,120 @@
|
||||
#include "base/indented_stream.h"
|
||||
#include "thin-provisioning/emitter.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace thin_provisioning;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
class sexp_emitter : public emitter {
|
||||
public:
|
||||
sexp_emitter(ostream &out)
|
||||
: out_(out) {
|
||||
}
|
||||
|
||||
virtual void begin_superblock(std::string const &uuid,
|
||||
uint64_t time,
|
||||
uint64_t trans_id,
|
||||
boost::optional<uint32_t> flags,
|
||||
boost::optional<uint32_t> version,
|
||||
uint32_t data_block_size,
|
||||
uint64_t nr_data_blocks,
|
||||
boost::optional<uint64_t> metadata_snap) {
|
||||
open("superblock");
|
||||
out_.indent();
|
||||
out_ << "((uuid \"" << uuid << "\")\n";
|
||||
kv("time", time);
|
||||
kv("trans_id", trans_id);
|
||||
kv("flags", flags);
|
||||
kv("version", version);
|
||||
kv("data_block_size", data_block_size);
|
||||
kv("nr_data_blocks", nr_data_blocks);
|
||||
kv("metadata_snap", metadata_snap);
|
||||
out_.indent();
|
||||
out_ << ")\n";
|
||||
}
|
||||
|
||||
virtual void end_superblock() {
|
||||
close();
|
||||
}
|
||||
|
||||
virtual void begin_device(uint32_t dev_id,
|
||||
uint64_t mapped_blocks,
|
||||
uint64_t trans_id,
|
||||
uint64_t creation_time,
|
||||
uint64_t snap_time) {
|
||||
open("device");
|
||||
out_.indent();
|
||||
out_ << "((dev_id " << dev_id << ")\n";
|
||||
kv("mapped_blocks", mapped_blocks);
|
||||
kv("trans_id", trans_id);
|
||||
kv("creation_time", creation_time);
|
||||
kv("snap_time", snap_time);
|
||||
out_.indent();
|
||||
out_ << ")\n";
|
||||
}
|
||||
|
||||
virtual void end_device() {
|
||||
close();
|
||||
}
|
||||
|
||||
virtual void begin_named_mapping(std::string const &name) {
|
||||
|
||||
}
|
||||
|
||||
virtual void end_named_mapping() {
|
||||
|
||||
}
|
||||
|
||||
virtual void identifier(std::string const &name) {
|
||||
|
||||
}
|
||||
|
||||
virtual void range_map(uint64_t origin_begin, uint64_t data_begin, uint32_t time, uint64_t len) {
|
||||
out_.indent();
|
||||
out_ << "(range (origin_begin " << origin_begin
|
||||
<< ") (data_begin " << data_begin
|
||||
<< ") (time " << time
|
||||
<< ") (len " << len << "))\n";
|
||||
}
|
||||
|
||||
virtual void single_map(uint64_t origin_block, uint64_t data_block, uint32_t time) {
|
||||
out_.indent();
|
||||
out_ << "(single (origin_block " << origin_block
|
||||
<< ") (data_block " << data_block
|
||||
<< ") (time " << time << "))\n";
|
||||
}
|
||||
|
||||
private:
|
||||
void open(char const *tag) {
|
||||
out_.indent();
|
||||
out_ << "(" << tag << "\n";
|
||||
out_.inc();
|
||||
}
|
||||
|
||||
void close() {
|
||||
out_.dec();
|
||||
out_.indent();
|
||||
out_ << ")\n";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void kv(char const *k, T const &v) {
|
||||
out_.indent();
|
||||
out_ << " (" << k << " " << v << ")\n";
|
||||
}
|
||||
|
||||
indented_stream out_;
|
||||
};
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
extern "C" {
|
||||
emitter::ptr create_emitter(ostream &out) {
|
||||
return emitter::ptr(new sexp_emitter(out));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
@ -26,8 +26,13 @@ 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".
|
||||
Print output in XML or human readable format.
|
||||
.IP "\fB\-f, \-\-format\fP \fI{xml|human_readable|custom}\fP".
|
||||
|
||||
Print output in XML or human readable format. Custom formats are
|
||||
supported via shared library plugins. They should be specified as in
|
||||
this example:
|
||||
.sp
|
||||
.B thin_dump --format custom=mylib.so /dev/sda
|
||||
|
||||
.IP "\fB\-r, \-\-repair\fP".
|
||||
Repair the metadata whilst dumping it.
|
||||
|
29
thin-provisioning/shared_library_emitter.cc
Normal file
29
thin-provisioning/shared_library_emitter.cc
Normal file
@ -0,0 +1,29 @@
|
||||
#include "thin-provisioning/shared_library_emitter.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace std;
|
||||
using namespace thin_provisioning;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
emitter::ptr
|
||||
thin_provisioning::create_custom_emitter(string const &shared_lib, ostream &out)
|
||||
{
|
||||
emitter::ptr (*create_fn)(ostream &out);
|
||||
void *handle = dlopen(shared_lib.c_str(), RTLD_LAZY);
|
||||
if (!handle)
|
||||
throw runtime_error(dlerror());
|
||||
|
||||
dlerror(); // Clear any existing error
|
||||
create_fn = reinterpret_cast<emitter::ptr (*)(ostream &)>(dlsym(handle, "create_emitter"));
|
||||
|
||||
char *error = dlerror();
|
||||
if (error)
|
||||
throw runtime_error(error);
|
||||
|
||||
return create_fn(out);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
14
thin-provisioning/shared_library_emitter.h
Normal file
14
thin-provisioning/shared_library_emitter.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef THIN_PROVISIONING_SHARED_LIBRARY_EMITTER_H
|
||||
#define THIN_PROVISIONING_SHARED_LIBRARY_EMITTER_H
|
||||
|
||||
#include "thin-provisioning/emitter.h"
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace thin_provisioning {
|
||||
emitter::ptr create_custom_emitter(std::string const &shared_lib, std::ostream &out);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#endif
|
@ -21,13 +21,14 @@
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "human_readable_format.h"
|
||||
#include "metadata_dumper.h"
|
||||
#include "metadata.h"
|
||||
#include "xml_format.h"
|
||||
#include "version.h"
|
||||
#include "thin-provisioning/commands.h"
|
||||
#include "persistent-data/file_utils.h"
|
||||
#include "thin-provisioning/commands.h"
|
||||
#include "thin-provisioning/human_readable_format.h"
|
||||
#include "thin-provisioning/metadata.h"
|
||||
#include "thin-provisioning/metadata_dumper.h"
|
||||
#include "thin-provisioning/shared_library_emitter.h"
|
||||
#include "thin-provisioning/xml_format.h"
|
||||
#include "version.h"
|
||||
|
||||
using namespace boost;
|
||||
using namespace persistent_data;
|
||||
@ -56,6 +57,10 @@ namespace {
|
||||
return md;
|
||||
}
|
||||
|
||||
bool begins_with(string const &str, string const &prefix) {
|
||||
return str.substr(0, prefix.length()) == prefix;
|
||||
}
|
||||
|
||||
emitter::ptr create_emitter(string const &format, ostream &out) {
|
||||
emitter::ptr e;
|
||||
|
||||
@ -65,9 +70,13 @@ namespace {
|
||||
else if (format == "human_readable")
|
||||
e = create_human_readable_emitter(out);
|
||||
|
||||
else if (begins_with(format, "custom="))
|
||||
e = create_custom_emitter(format.substr(7), out);
|
||||
|
||||
else {
|
||||
cerr << "unknown format '" << format << "'" << endl;
|
||||
exit(1);
|
||||
ostringstream msg;
|
||||
msg << "unknown format '" << format << "'";
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
return e;
|
||||
|
Loading…
Reference in New Issue
Block a user