thin_restore now parses xml and hands to an emitter
This commit is contained in:
parent
13e26684f7
commit
28ab23fe6c
2
Makefile
2
Makefile
@ -19,7 +19,7 @@ OBJECTS=$(subst .cc,.o,$(SOURCE))
|
||||
TOP_DIR:=$(PWD)
|
||||
CPPFLAGS=-Wall -g -I$(TOP_DIR) -O8
|
||||
#CPPFLAGS=-Wall -std=c++0x -g -I$(TOP_DIR)
|
||||
LIBS=-lstdc++ -lboost_program_options
|
||||
LIBS=-lstdc++ -lboost_program_options -lexpat
|
||||
|
||||
.PHONEY: test-programs
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace thin_provisioning {
|
||||
|
||||
virtual void identifier(std::string const &name) = 0;
|
||||
virtual void range_map(uint64_t origin_begin, uint64_t data_begin, uint64_t len) = 0;
|
||||
virtual void single_map(uint64_t origin_block, uint64_t ddata_block) = 0;
|
||||
virtual void single_map(uint64_t origin_block, uint64_t data_block) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ namespace {
|
||||
uint64_t time,
|
||||
uint64_t trans_id,
|
||||
uint32_t data_block_size) {
|
||||
out_ << "begin superblock: " << uuid
|
||||
out_ << "begin superblock: \"" << uuid << "\""
|
||||
<< ", " << time
|
||||
<< ", " << trans_id
|
||||
<< ", " << data_block_size
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "emitter.h"
|
||||
#include "human_readable_format.h"
|
||||
#include "metadata.h"
|
||||
#include "xml_format.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
using namespace persistent_data;
|
||||
@ -14,7 +17,10 @@ namespace po = boost::program_options;
|
||||
|
||||
namespace {
|
||||
void restore(string const &backup_file, string const &dev) {
|
||||
cerr << "not implemented" << endl;
|
||||
emitter::ptr hr = create_human_readable_emitter(cout);
|
||||
ifstream in(backup_file.c_str(), ifstream::in);
|
||||
parse_xml(in, hr);
|
||||
in.close();
|
||||
}
|
||||
|
||||
void usage(po::options_description const &desc) {
|
||||
|
140
xml_format.cc
140
xml_format.cc
@ -1,8 +1,14 @@
|
||||
#include "xml_format.h"
|
||||
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <expat.h>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string.h>
|
||||
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
using namespace thin_provisioning;
|
||||
|
||||
@ -11,6 +17,9 @@ namespace tp = thin_provisioning;
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
//------------------------------------------------
|
||||
// XML generator
|
||||
//------------------------------------------------
|
||||
class xml_emitter : public emitter {
|
||||
public:
|
||||
xml_emitter(ostream &out)
|
||||
@ -107,6 +116,107 @@ namespace {
|
||||
ostream &out_;
|
||||
unsigned indent_;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
// XML parser
|
||||
//------------------------------------------------
|
||||
typedef std::map<string, string> attributes;
|
||||
|
||||
void build_attributes(attributes &a, char const **attr) {
|
||||
while (*attr) {
|
||||
char const *key = *attr;
|
||||
|
||||
attr++;
|
||||
if (!*attr) {
|
||||
ostringstream out;
|
||||
out << "No value given for xml attribute: " << key;
|
||||
throw runtime_error(out.str());
|
||||
}
|
||||
|
||||
char const *value = *attr;
|
||||
a.insert(make_pair(string(key), string(value)));
|
||||
attr++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get_attr(attributes const &attr, string const &key) {
|
||||
attributes::const_iterator it = attr.find(key);
|
||||
if (it == attr.end()) {
|
||||
ostringstream out;
|
||||
out << "could not find attribute: " << key;
|
||||
throw runtime_error(out.str());
|
||||
}
|
||||
|
||||
return lexical_cast<T>(it->second);
|
||||
}
|
||||
|
||||
void parse_superblock(emitter *e, attributes const &attr) {
|
||||
e->begin_superblock(get_attr<string>(attr, "uuid"),
|
||||
get_attr<uint64_t>(attr, "time"),
|
||||
get_attr<uint64_t>(attr, "transaction"),
|
||||
get_attr<uint32_t>(attr, "data_block_size"));
|
||||
}
|
||||
|
||||
void parse_device(emitter *e, attributes const &attr) {
|
||||
e->begin_device(get_attr<uint32_t>(attr, "dev_id"),
|
||||
get_attr<uint64_t>(attr, "mapped_blocks"),
|
||||
get_attr<uint64_t>(attr, "transaction"),
|
||||
get_attr<uint64_t>(attr, "creation_time"),
|
||||
get_attr<uint64_t>(attr, "snap_time"));
|
||||
}
|
||||
|
||||
void parse_range_mapping(emitter *e, attributes const &attr) {
|
||||
e->range_map(get_attr<uint64_t>(attr, "origin_begin"),
|
||||
get_attr<uint64_t>(attr, "data_begin"),
|
||||
get_attr<uint64_t>(attr, "length"));
|
||||
}
|
||||
|
||||
void parse_single_mapping(emitter *e, attributes const &attr) {
|
||||
e->single_map(get_attr<uint64_t>(attr, "origin_block"),
|
||||
get_attr<uint64_t>(attr, "data_block"));
|
||||
}
|
||||
|
||||
void start_tag(void *data, char const *el, char const **attr) {
|
||||
emitter *e = static_cast<emitter *>(data);
|
||||
attributes a;
|
||||
|
||||
build_attributes(a, attr);
|
||||
|
||||
if (!strcmp(el, "superblock"))
|
||||
parse_superblock(e, a);
|
||||
|
||||
else if (!strcmp(el, "device"))
|
||||
parse_device(e, a);
|
||||
|
||||
else if (!strcmp(el, "range_mapping"))
|
||||
parse_range_mapping(e, a);
|
||||
|
||||
else if (!strcmp(el, "single_mapping"))
|
||||
parse_single_mapping(e, a);
|
||||
|
||||
else
|
||||
throw runtime_error("unknown tag type");
|
||||
}
|
||||
|
||||
void end_tag(void *data, const char *el) {
|
||||
emitter *e = static_cast<emitter *>(data);
|
||||
|
||||
if (!strcmp(el, "superblock"))
|
||||
e->end_superblock();
|
||||
|
||||
else if (!strcmp(el, "device"))
|
||||
e->end_device();
|
||||
|
||||
else if (!strcmp(el, "range_mapping")) {
|
||||
// do nothing
|
||||
|
||||
} else if (!strcmp(el, "single_mapping")) {
|
||||
// do nothing
|
||||
|
||||
} else
|
||||
throw runtime_error("unknown tag close");
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
@ -117,4 +227,32 @@ tp::create_xml_emitter(ostream &out)
|
||||
return emitter::ptr(new xml_emitter(out));
|
||||
}
|
||||
|
||||
void
|
||||
tp::parse_xml(std::istream &in, emitter::ptr e)
|
||||
{
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
if (!parser)
|
||||
throw runtime_error("couldn't create xml parser");
|
||||
|
||||
XML_SetUserData(parser, e.get());
|
||||
XML_SetElementHandler(parser, start_tag, end_tag);
|
||||
|
||||
while (!in.eof()) {
|
||||
char buffer[4096];
|
||||
in.read(buffer, sizeof(buffer));
|
||||
size_t len = in.gcount();
|
||||
int done = in.eof();
|
||||
|
||||
if (!XML_Parse(parser, buffer, len, done)) {
|
||||
ostringstream out;
|
||||
out << "Parse error at line "
|
||||
<< XML_GetCurrentLineNumber(parser)
|
||||
<< ":\n"
|
||||
<< XML_ErrorString(XML_GetErrorCode(parser))
|
||||
<< endl;
|
||||
throw runtime_error(out.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
namespace thin_provisioning {
|
||||
emitter::ptr create_xml_emitter(std::ostream &out);
|
||||
void parse_xml(std::istream &in, emitter::ptr e);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user