diff --git a/Makefile.in b/Makefile.in index f240904..5fc8c84 100644 --- a/Makefile.in +++ b/Makefile.in @@ -40,6 +40,7 @@ SOURCE=\ caching/superblock.cc \ caching/mapping_array.cc \ caching/metadata.cc \ + caching/metadata_dump.cc \ caching/restore_emitter.cc \ caching/xml_format.cc \ \ @@ -243,6 +244,7 @@ CACHE_CHECK_SOURCE=\ caching/superblock.cc \ caching/mapping_array.cc \ caching/metadata.cc \ + caching/metadata_dump.cc \ caching/restore_emitter.cc \ caching/xml_format.cc diff --git a/caching/cache_dump.cc b/caching/cache_dump.cc index 18d36c6..ea13c55 100644 --- a/caching/cache_dump.cc +++ b/caching/cache_dump.cc @@ -6,6 +6,7 @@ #include "version.h" #include "caching/mapping_array.h" #include "caching/metadata.h" +#include "caching/metadata_dump.h" #include "caching/xml_format.h" #include "persistent-data/file_utils.h" @@ -23,75 +24,6 @@ namespace { bool repair_; }; - string to_string(unsigned char const *data) { - // FIXME: we're assuming the data is zero terminated here - return std::string(reinterpret_cast(data)); - } - - void raise_metadata_damage() { - throw std::runtime_error("metadata contains errors (run cache_check for details).\n" - "perhaps you wanted to run with --repair"); - } - - //-------------------------------- - - class mapping_emitter : public mapping_visitor { - public: - mapping_emitter(emitter::ptr e) - : e_(e) { - } - - void visit(block_address cblock, mapping const &m) { - if (m.flags_ & M_VALID) - e_->mapping(cblock, m.oblock_, m.flags_ & M_DIRTY); - } - - private: - emitter::ptr e_; - }; - - struct ignore_mapping_damage : public mapping_array_damage::damage_visitor { - virtual void visit(mapping_array_damage::missing_mappings const &d) {} - virtual void visit(mapping_array_damage::invalid_mapping const &d) {} - }; - - class fatal_mapping_damage : public mapping_array_damage::damage_visitor { - public: - virtual void visit(mapping_array_damage::missing_mappings const &d) { - raise_metadata_damage(); - } - - virtual void visit(mapping_array_damage::invalid_mapping const &d) { - raise_metadata_damage(); - } - }; - - //-------------------------------- - - class hint_emitter : public hint_visitor { - public: - hint_emitter(emitter::ptr e) - : e_(e) { - } - - virtual void visit(block_address cblock, std::vector const &data) { - e_->hint(cblock, data); - } - - private: - emitter::ptr e_; - }; - - struct ignore_hint_damage : public hint_array_damage::damage_visitor { - virtual void visit(hint_array_damage::missing_hints const &d) {} - }; - - class fatal_hint_damage : public hint_array_damage::damage_visitor { - virtual void visit(hint_array_damage::missing_hints const &d) { - raise_metadata_damage(); - } - }; - //-------------------------------- string const STDOUT_PATH("-"); @@ -100,65 +32,26 @@ namespace { return output == STDOUT_PATH; } - int dump_(string const &dev, ostream &out, flags const &fs) { - block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY); - metadata::ptr md(new metadata(bm, metadata::OPEN)); - emitter::ptr e = create_xml_emitter(out); - - superblock const &sb = md->sb_; - e->begin_superblock(to_string(sb.uuid), sb.data_block_size, - sb.cache_blocks, to_string(sb.policy_name), - sb.policy_hint_size); - - e->begin_mappings(); - { - namespace mad = mapping_array_damage; - - mapping_emitter me(e); - ignore_mapping_damage ignore; - fatal_mapping_damage fatal; - mad::damage_visitor &dv = fs.repair_ ? - static_cast(ignore) : - static_cast(fatal); - walk_mapping_array(*md->mappings_, me, dv); - } - e->end_mappings(); - - // walk hints - e->begin_hints(); - { - using namespace hint_array_damage; - - hint_emitter he(e); - ignore_hint_damage ignore; - fatal_hint_damage fatal; - damage_visitor &dv = fs.repair_ ? - static_cast(ignore) : - static_cast(fatal); - md->hints_->walk(he, dv); - } - e->end_hints(); - - // FIXME: walk discards - - e->end_superblock(); - - return 0; - } - int dump(string const &dev, string const &output, flags const &fs) { try { - if (want_stdout(output)) - return dump_(dev, cout, fs); - else { + block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY); + metadata::ptr md(new metadata(bm, metadata::OPEN)); + + if (want_stdout(output)) { + emitter::ptr e = create_xml_emitter(cout); + metadata_dump(md, e, fs.repair_); + } else { ofstream out(output.c_str()); - return dump_(dev, out, fs); + emitter::ptr e = create_xml_emitter(out); + metadata_dump(md, e, fs.repair_); } } catch (std::exception &e) { cerr << e.what() << endl; return 1; } + + return 0; } void usage(ostream &out, string const &cmd) { diff --git a/caching/metadata_dump.cc b/caching/metadata_dump.cc new file mode 100644 index 0000000..7521809 --- /dev/null +++ b/caching/metadata_dump.cc @@ -0,0 +1,124 @@ +#include "caching/metadata_dump.h" + +using namespace std; +using namespace caching; + +//---------------------------------------------------------------- + +namespace { + string to_string(unsigned char const *data) { + // FIXME: we're assuming the data is zero terminated here + return std::string(reinterpret_cast(data)); + } + + void raise_metadata_damage() { + throw std::runtime_error("metadata contains errors (run cache_check for details).\n" + "perhaps you wanted to run with --repair"); + } + + //-------------------------------- + + class mapping_emitter : public mapping_visitor { + public: + mapping_emitter(emitter::ptr e) + : e_(e) { + } + + void visit(block_address cblock, mapping const &m) { + if (m.flags_ & M_VALID) + e_->mapping(cblock, m.oblock_, m.flags_ & M_DIRTY); + } + + private: + emitter::ptr e_; + }; + + struct ignore_mapping_damage : public mapping_array_damage::damage_visitor { + virtual void visit(mapping_array_damage::missing_mappings const &d) {} + virtual void visit(mapping_array_damage::invalid_mapping const &d) {} + }; + + class fatal_mapping_damage : public mapping_array_damage::damage_visitor { + public: + virtual void visit(mapping_array_damage::missing_mappings const &d) { + raise_metadata_damage(); + } + + virtual void visit(mapping_array_damage::invalid_mapping const &d) { + raise_metadata_damage(); + } + }; + + //-------------------------------- + + class hint_emitter : public hint_visitor { + public: + hint_emitter(emitter::ptr e) + : e_(e) { + } + + virtual void visit(block_address cblock, std::vector const &data) { + e_->hint(cblock, data); + } + + private: + emitter::ptr e_; + }; + + struct ignore_hint_damage : public hint_array_damage::damage_visitor { + virtual void visit(hint_array_damage::missing_hints const &d) {} + }; + + class fatal_hint_damage : public hint_array_damage::damage_visitor { + virtual void visit(hint_array_damage::missing_hints const &d) { + raise_metadata_damage(); + } + }; +} + +//---------------------------------------------------------------- + +void +caching::metadata_dump(metadata::ptr md, emitter::ptr e, bool repair) +{ + superblock const &sb = md->sb_; + e->begin_superblock(to_string(sb.uuid), sb.data_block_size, + sb.cache_blocks, to_string(sb.policy_name), + sb.policy_hint_size); + + e->begin_mappings(); + { + namespace mad = mapping_array_damage; + + mapping_emitter me(e); + ignore_mapping_damage ignore; + fatal_mapping_damage fatal; + mad::damage_visitor &dv = repair ? + static_cast(ignore) : + static_cast(fatal); + walk_mapping_array(*md->mappings_, me, dv); + } + e->end_mappings(); + + // walk hints + e->begin_hints(); + { + using namespace hint_array_damage; + + hint_emitter he(e); + ignore_hint_damage ignore; + fatal_hint_damage fatal; + damage_visitor &dv = repair ? + static_cast(ignore) : + static_cast(fatal); + md->hints_->walk(he, dv); + } + e->end_hints(); + + // FIXME: walk discards + + e->end_superblock(); +} + +//---------------------------------------------------------------- + diff --git a/caching/metadata_dump.h b/caching/metadata_dump.h new file mode 100644 index 0000000..7dc1d38 --- /dev/null +++ b/caching/metadata_dump.h @@ -0,0 +1,17 @@ +#ifndef CACHING_METADATA_DUMP_H +#define CACHING_METADATA_DUMP_H + +#include "caching/metadata.h" +#include "caching/emitter.h" + +//---------------------------------------------------------------- + +namespace caching { + // If 'repair' is set then any metadata damage will be stepped + // around. Otherwise an exception will be thrown. + void metadata_dump(metadata::ptr md, emitter::ptr out, bool repair); +} + +//---------------------------------------------------------------- + +#endif