// 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 "xml_format.h" #include "base/indented_stream.h" #include "base/xml_utils.h" #include #include #include #include #include #include #include using namespace std; using namespace thin_provisioning; using namespace xml_utils; namespace tp = thin_provisioning; //---------------------------------------------------------------- namespace { //------------------------------------------------ // XML generator //------------------------------------------------ class xml_emitter : public emitter { public: xml_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) { out_.indent(); out_ << "" << endl; out_.inc(); } void end_superblock() { out_.dec(); out_.indent(); out_ << "" << endl; } void begin_device(uint32_t dev_id, uint64_t mapped_blocks, uint64_t trans_id, uint64_t creation_time, uint64_t snap_time) { out_.indent(); out_ << "" << endl; out_.inc(); } void end_device() { out_.dec(); out_.indent(); out_ << "" << endl; } void begin_named_mapping(string const &name) { out_.indent(); out_ << "" << endl; out_.inc(); } void end_named_mapping() { out_.dec(); out_.indent(); out_ << "" << endl; } void identifier(string const &name) { out_.indent(); out_ << "" << endl; } void range_map(uint64_t origin_begin, uint64_t data_begin, uint32_t time, uint64_t len) { out_.indent(); out_ << "" << endl; } void single_map(uint64_t origin_block, uint64_t data_block, uint32_t time) { out_.indent(); out_ << "" << endl; } private: indented_stream out_; }; //------------------------------------------------ // XML parser //------------------------------------------------ void parse_superblock(emitter *e, attributes const &attr) { e->begin_superblock(get_attr(attr, "uuid"), get_attr(attr, "time"), get_attr(attr, "transaction"), get_opt_attr(attr, "flags"), get_opt_attr(attr, "version"), get_attr(attr, "data_block_size"), get_attr(attr, "nr_data_blocks"), get_opt_attr(attr, "metadata_snap")); } void parse_device(emitter *e, attributes const &attr) { e->begin_device(get_attr(attr, "dev_id"), get_attr(attr, "mapped_blocks"), get_attr(attr, "transaction"), get_attr(attr, "creation_time"), get_attr(attr, "snap_time")); } void parse_range_mapping(emitter *e, attributes const &attr) { e->range_map(get_attr(attr, "origin_begin"), get_attr(attr, "data_begin"), get_attr(attr, "time"), get_attr(attr, "length")); } void parse_single_mapping(emitter *e, attributes const &attr) { e->single_map(get_attr(attr, "origin_block"), get_attr(attr, "data_block"), get_attr(attr, "time")); } void start_tag(void *data, char const *el, char const **attr) { emitter *e = static_cast(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(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"); } } //---------------------------------------------------------------- tp::emitter::ptr tp::create_xml_emitter(ostream &out) { return emitter::ptr(new xml_emitter(out)); } void tp::parse_xml(std::string const &backup_file, emitter::ptr e, bool quiet) { xml_parser p; XML_SetUserData(p.get_parser(), e.get()); XML_SetElementHandler(p.get_parser(), start_tag, end_tag); p.parse(backup_file, quiet); } //----------------------------------------------------------------