From 9e0540e1b60fdb6c511ede0fae552fab18c047d4 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Thu, 23 Jan 2014 00:46:03 +0000 Subject: [PATCH] era_check, era_dump --- Makefile.in | 41 +++++- caching/metadata_dump.cc | 2 +- era/bloom_tree.cc | 13 +- era/bloom_tree.h | 6 +- era/emitter.h | 35 +++++ era/era_array.cc | 87 +++++++++++ era/era_array.h | 78 ++++++++++ era/era_check.cc | 53 ++++++- era/era_detail.h | 11 +- era/era_dump.cc | 118 +++++++++++++++ era/metadata.cc | 60 ++++++++ era/metadata.h | 47 ++++++ era/metadata_dump.cc | 135 ++++++++++++++++++ era/metadata_dump.h | 15 ++ era/xml_format.cc | 103 +++++++++++++ era/xml_format.h | 17 +++ persistent-data/data-structures/bitset.cc | 4 +- persistent-data/data-structures/btree.h | 16 --- .../data-structures/simple_traits.h | 38 +++++ 19 files changed, 849 insertions(+), 30 deletions(-) create mode 100644 era/emitter.h create mode 100644 era/era_array.cc create mode 100644 era/era_array.h create mode 100644 era/era_dump.cc create mode 100644 era/metadata.cc create mode 100644 era/metadata.h create mode 100644 era/metadata_dump.cc create mode 100644 era/metadata_dump.h create mode 100644 era/xml_format.cc create mode 100644 era/xml_format.h create mode 100644 persistent-data/data-structures/simple_traits.h diff --git a/Makefile.in b/Makefile.in index 6d086a1..f199a80 100644 --- a/Makefile.in +++ b/Makefile.in @@ -26,6 +26,7 @@ PROGRAMS=\ cache_repair \ \ era_check \ + era_dump \ \ thin_check \ thin_dump \ @@ -49,9 +50,13 @@ SOURCE=\ caching/restore_emitter.cc \ caching/xml_format.cc \ \ + era/era_array.cc \ era/era_detail.cc \ era/superblock.cc \ era/bloom_tree.cc \ + era/metadata.cc \ + era/metadata_dump.cc \ + era/xml_format.cc \ \ persistent-data/checksum.cc \ persistent-data/error_set.cc \ @@ -301,8 +306,10 @@ ERA_CHECK_SOURCE=\ base/endian_utils.cc \ \ era/bloom_tree.cc \ - era/superblock.cc \ era/era_detail.cc \ + era/era_array.cc \ + era/metadata.cc \ + era/superblock.cc \ \ persistent-data/checksum.cc \ persistent-data/error_set.cc \ @@ -323,6 +330,38 @@ era_check: $(ERA_CHECK_OBJECTS) era/era_check.o @echo " [LD] $@" $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) +ERA_DUMP_SOURCE=\ + base/base64.cc \ + base/error_state.cc \ + base/endian_utils.cc \ + \ + era/bloom_tree.cc \ + era/era_detail.cc \ + era/era_array.cc \ + era/metadata.cc \ + era/metadata_dump.cc \ + era/superblock.cc \ + era/xml_format.cc \ + \ + persistent-data/checksum.cc \ + persistent-data/error_set.cc \ + persistent-data/file_utils.cc \ + persistent-data/hex_dump.cc \ + persistent-data/lock_tracker.cc \ + persistent-data/data-structures/btree.cc \ + persistent-data/data-structures/bitset.cc \ + persistent-data/space_map.cc \ + persistent-data/space-maps/disk.cc \ + persistent-data/space-maps/recursive.cc \ + persistent-data/space-maps/careful_alloc.cc \ + persistent-data/transaction_manager.cc \ + +ERA_DUMP_OBJECTS=$(subst .cc,.o,$(ERA_DUMP_SOURCE)) + +era_dump: $(ERA_DUMP_OBJECTS) era/era_dump.o + @echo " [LD] $@" + $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) + #---------------------------------------------------------------- DEPEND_FILES=\ diff --git a/caching/metadata_dump.cc b/caching/metadata_dump.cc index 2f66766..0b50145 100644 --- a/caching/metadata_dump.cc +++ b/caching/metadata_dump.cc @@ -15,7 +15,7 @@ namespace { void raise_metadata_damage() { throw std::runtime_error("metadata contains errors (run cache_check for details).\n" - "perhaps you wanted to run with --repair"); + "perhaps you wanted to run with --repair ?"); } //-------------------------------- diff --git a/era/bloom_tree.cc b/era/bloom_tree.cc index 022d447..b49e533 100644 --- a/era/bloom_tree.cc +++ b/era/bloom_tree.cc @@ -55,11 +55,13 @@ namespace { void visit(btree_path const &path, era_detail const &era) { era_ = path[0]; bitset bs(tm_, era.bloom_root, era.nr_bits); + bloom_v_.bloom_begin(era_, era.nr_blocks, era.nr_bits, era.nr_set); bs.walk_bitset(*this); + bloom_v_.bloom_end(); } void visit(uint32_t index, bool value) { - bloom_v_.visit(index, value); + bloom_v_.bit(index, value); } void visit(bitset_detail::missing_bits const &d) { @@ -109,7 +111,14 @@ era::walk_bloom_tree(persistent_data::transaction_manager::ptr tm, namespace { class noop_bloom_visitor : public bloom_tree_detail::bloom_visitor { public: - void visit(uint32_t index, bool value) { + void bloom_begin(uint32_t era, uint32_t nr_blocks, + uint32_t nr_bits, uint32_t nr_set) { + } + + void bit(uint32_t index, bool value) { + } + + void bloom_end() { } }; }; diff --git a/era/bloom_tree.h b/era/bloom_tree.h index 8d89a96..ad4bbd6 100644 --- a/era/bloom_tree.h +++ b/era/bloom_tree.h @@ -63,7 +63,11 @@ namespace era { typedef boost::shared_ptr ptr; virtual ~bloom_visitor() {} - virtual void visit(uint32_t index, bool value) = 0; + + virtual void bloom_begin(uint32_t era, uint32_t nr_blocks, + uint32_t nr_bits, uint32_t nr_set) = 0; + virtual void bit(uint32_t index, bool value) = 0; + virtual void bloom_end() = 0; }; } diff --git a/era/emitter.h b/era/emitter.h new file mode 100644 index 0000000..0fb7520 --- /dev/null +++ b/era/emitter.h @@ -0,0 +1,35 @@ +#ifndef ERA_EMITTER_H +#define ERA_EMITTER_H + +#include "persistent-data/block.h" + +//---------------------------------------------------------------- + +namespace era { + namespace pd = persistent_data; + + class emitter { + public: + typedef boost::shared_ptr ptr; + + virtual ~emitter() {} + + virtual void begin_superblock(std::string const &uuid, + uint32_t data_block_size, + pd::block_address nr_blocks, + uint32_t current_era) = 0; + virtual void end_superblock() = 0; + + virtual void begin_bloom(uint32_t era, uint32_t nr_bits, pd::block_address nr_blocks) = 0; + virtual void bloom_bit(uint32_t bit, bool value) = 0; + virtual void end_bloom() = 0; + + virtual void begin_era_array() = 0; + virtual void era(pd::block_address block, uint32_t era) = 0; + virtual void end_era_array() = 0; + }; +} + +//---------------------------------------------------------------- + +#endif diff --git a/era/era_array.cc b/era/era_array.cc new file mode 100644 index 0000000..72ef82c --- /dev/null +++ b/era/era_array.cc @@ -0,0 +1,87 @@ +#include "era/era_array.h" + +using namespace era; +using namespace era_array_detail; +using namespace std; + +//---------------------------------------------------------------- + +missing_eras::missing_eras(string const &desc, run const &eras) + : damage(desc), + eras_(eras) +{ +} + +void +missing_eras::visit(damage_visitor &v) const +{ + v.visit(*this); +} + +invalid_era::invalid_era(string const &desc, block_address block, uint32_t era) + : damage(desc), + block_(block), + era_(era) +{ +} + +void +invalid_era::visit(damage_visitor &v) const +{ + v.visit(*this); +} + +//---------------------------------------------------------------- + +namespace { + class check_era_visitor : public era_array_visitor { + public: + check_era_visitor(damage_visitor &visitor, uint32_t current_era) + : visitor_(visitor), + current_era_(current_era) { + } + + virtual void visit(uint32_t cblock, uint32_t era) { + if (era > current_era_) + visitor_.visit(invalid_era("era too great", cblock, era)); + } + + private: + damage_visitor &visitor_; + uint32_t current_era_; + }; + + class ll_damage_visitor { + public: + ll_damage_visitor(damage_visitor &v) + : v_(v) { + } + + virtual void visit(array_detail::damage const &d) { + v_.visit(missing_eras(d.desc_, d.lost_keys_)); + } + + private: + damage_visitor &v_; + }; +} + +void +era::walk_era_array(era_array const &array, + era_array_visitor &ev, + era_array_detail::damage_visitor &dv) +{ + ll_damage_visitor ll(dv); + array.visit_values(ev, ll); +} + +void +era::check_era_array(era_array const &array, + uint32_t current_era, + era_array_detail::damage_visitor &dv) +{ + check_era_visitor cv(dv, current_era); + walk_era_array(array, cv, dv); +} + +//---------------------------------------------------------------- diff --git a/era/era_array.h b/era/era_array.h new file mode 100644 index 0000000..49d7aca --- /dev/null +++ b/era/era_array.h @@ -0,0 +1,78 @@ +#ifndef ERA_ARRAY_H +#define ERA_ARRAY_H + +#include "persistent-data/data-structures/array.h" +#include "persistent-data/data-structures/simple_traits.h" + +//---------------------------------------------------------------- + +namespace era { + namespace era_array_detail { + class damage_visitor; + + class damage { + public: + damage(std::string const &desc) + : desc_(desc) { + } + + virtual ~damage() {} + virtual void visit(damage_visitor &v) const = 0; + + std::string get_desc() const { + return desc_; + } + + private: + std::string desc_; + }; + + struct missing_eras : public damage { + missing_eras(std::string const &desc, run const &eras); + virtual void visit(damage_visitor &v) const; + + run eras_; + }; + + struct invalid_era : public damage { + invalid_era(std::string const &desc, block_address block, uint32_t era); + virtual void visit(damage_visitor &v) const; + + block_address block_; + uint32_t era_; + }; + + class damage_visitor { + public: + virtual ~damage_visitor() {} + + void visit(era_array_detail::damage const &d) { + d.visit(*this); + } + + virtual void visit(missing_eras const &d) = 0; + virtual void visit(invalid_era const &d) = 0; + }; + } + + typedef persistent_data::array era_array; + + class era_array_visitor { + public: + virtual ~era_array_visitor() {} + + virtual void visit(uint32_t index, uint32_t era) = 0; + }; + + void walk_era_array(era_array const &array, + era_array_visitor &ev, + era_array_detail::damage_visitor &dv); + + void check_era_array(era_array const &array, + uint32_t current_era, + era_array_detail::damage_visitor &dv); +} + +//---------------------------------------------------------------- + +#endif diff --git a/era/era_check.cc b/era/era_check.cc index 991da05..de65106 100644 --- a/era/era_check.cc +++ b/era/era_check.cc @@ -15,6 +15,7 @@ #include "base/error_state.h" #include "base/nested_output.h" #include "era/bloom_tree.h" +#include "era/era_array.h" #include "era/superblock.h" #include "persistent-data/block.h" #include "persistent-data/file_utils.h" @@ -98,7 +99,7 @@ namespace { } void visit(bloom_tree_detail::missing_eras const &d) { - out() << "missing eras" << end_message(); + out() << "missing eras from bloom tree" << end_message(); { nested_output::nest _ = push(); out() << d.get_desc() << end_message(); @@ -125,6 +126,38 @@ namespace { using reporter_base::get_error; }; + class era_array_reporter : public era_array_detail::damage_visitor, reporter_base { + public: + era_array_reporter(nested_output &o) + : reporter_base(o) { + } + + void visit(era_array_detail::missing_eras const &d) { + out() << "missing eras from era array" << end_message(); + { + nested_output::nest _ = push(); + out() << d.get_desc() << end_message(); + out() << "Effected eras: [" << d.eras_.begin_.get() + << ", " << d.eras_.end_.get() << ")" << end_message(); + } + + mplus_error(FATAL); + } + + void visit(era_array_detail::invalid_era const &d) { + out() << "invalid era in era array" << end_message(); + { + nested_output::nest _ = push(); + out() << d.get_desc() << end_message(); + out() << "block: " << d.block_ << ", era: " << d.era_ << end_message(); + } + + mplus_error(FATAL); + } + + using reporter_base::get_error; + }; + //-------------------------------- transaction_manager::ptr open_tm(block_manager<>::ptr bm) { @@ -184,12 +217,22 @@ namespace { transaction_manager::ptr tm = open_tm(bm); bloom_tree_reporter bt_rep(out); - era_detail_traits::ref_counter rc(tm); - bloom_tree bt(tm, rc); - check_bloom_tree(tm, bt, bt_rep); + { + era_detail_traits::ref_counter rc(tm); + bloom_tree bt(tm, sb.bloom_tree_root, rc); + check_bloom_tree(tm, bt, bt_rep); + } + + era_array_reporter ea_rep(out); + { + uint32_traits::ref_counter rc; + era_array ea(tm, rc, sb.era_array_root, sb.nr_blocks); + check_era_array(ea, ea_rep); + } return combine_errors(sb_rep.get_error(), - bt_rep.get_error()); + combine_errors(bt_rep.get_error(), + ea_rep.get_error())); } int check(string const &path, flags const &fs) { diff --git a/era/era_detail.h b/era/era_detail.h index 7afaaaf..6cacc09 100644 --- a/era/era_detail.h +++ b/era/era_detail.h @@ -26,11 +26,16 @@ namespace era { uint64_t bloom_root; }; + // FIXME: implement struct era_detail_ref_counter { - era_detail_ref_counter(persistent_data::transaction_manager::ptr tm); + era_detail_ref_counter(persistent_data::transaction_manager::ptr tm) { + } - void inc(persistent_data::block_address b); - void dec(persistent_data::block_address b); + void inc(persistent_data::block_address b) { + } + + void dec(persistent_data::block_address b) { + } }; struct era_detail_traits { diff --git a/era/era_dump.cc b/era/era_dump.cc new file mode 100644 index 0000000..1f13abd --- /dev/null +++ b/era/era_dump.cc @@ -0,0 +1,118 @@ +#include +#include +#include +#include + +#include "version.h" +#include "era/era_array.h" +#include "era/bloom_tree.h" +#include "era/metadata.h" +#include "era/metadata_dump.h" +#include "era/xml_format.h" +#include "persistent-data/file_utils.h" + +using namespace era; +using namespace std; + +//---------------------------------------------------------------- + +namespace { + struct flags { + flags() + : repair_(false) { + } + + bool repair_; + }; + + //-------------------------------- + + string const STDOUT_PATH("-"); + + bool want_stdout(string const &output) { + return output == STDOUT_PATH; + } + + int dump(string const &dev, string const &output, flags const &fs) { + try { + 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()); + 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) { + out << "Usage: " << cmd << " [options] {device|file}" << endl + << "Options:" << endl + << " {-h|--help}" << endl + << " {-o }" << endl + << " {-V|--version}" << endl + << " {--repair}" << endl; + } +} + +//---------------------------------------------------------------- + +int main(int argc, char **argv) +{ + int c; + flags fs; + string output("-"); + char const shortopts[] = "ho:V"; + + option const longopts[] = { + { "help", no_argument, NULL, 'h' }, + { "output", required_argument, NULL, 'o' }, + { "version", no_argument, NULL, 'V' }, + { "repair", no_argument, NULL, 1 }, + { NULL, no_argument, NULL, 0 } + }; + + while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { + switch(c) { + case 1: + fs.repair_ = true; + break; + + case 'h': + usage(cout, basename(argv[0])); + return 0; + + case 'o': + output = optarg; + break; + + case 'V': + cout << THIN_PROVISIONING_TOOLS_VERSION << endl; + return 0; + + default: + usage(cerr, basename(argv[0])); + return 1; + } + } + + if (argc == optind) { + cerr << "No input file provided." << endl; + usage(cerr, basename(argv[0])); + return 1; + } + + return dump(argv[optind], output, fs); +} + +//---------------------------------------------------------------- diff --git a/era/metadata.cc b/era/metadata.cc new file mode 100644 index 0000000..270bd15 --- /dev/null +++ b/era/metadata.cc @@ -0,0 +1,60 @@ +#include "era/metadata.h" +#include "persistent-data/space-maps/core.h" + +using namespace era; + +//---------------------------------------------------------------- + +namespace { + unsigned const METADATA_CACHE_SIZ = 1024; + + // FIXME: duplication + transaction_manager::ptr + open_tm(block_manager<>::ptr bm) { + space_map::ptr sm(new core_map(bm->get_nr_blocks())); + sm->inc(SUPERBLOCK_LOCATION); + transaction_manager::ptr tm(new transaction_manager(bm, sm)); + return tm; + } + + void + copy_space_maps(space_map::ptr lhs, space_map::ptr rhs) { + for (block_address b = 0; b < rhs->get_nr_blocks(); b++) { + uint32_t count = rhs->get_count(b); + if (count > 0) + lhs->set_count(b, rhs->get_count(b)); + } + } +} + +metadata::metadata(block_manager<>::ptr bm, open_type ot) +{ + switch (ot) { + case CREATE: + // finish + throw runtime_error("not imlemented"); + break; + + case OPEN: + open_metadata(bm); + break; + } +} + +void +metadata::open_metadata(block_manager<>::ptr bm) +{ + tm_ = open_tm(bm); + sb_ = read_superblock(tm_->get_bm()); + + bloom_tree_ = bloom_tree::ptr(new bloom_tree(tm_, + sb_.bloom_tree_root, + era_detail_traits::ref_counter(tm_))); + + era_array_ = era_array::ptr(new era_array(tm_, + uint32_traits::ref_counter(), + sb_.era_array_root, + sb_.nr_blocks)); +} + +//---------------------------------------------------------------- diff --git a/era/metadata.h b/era/metadata.h new file mode 100644 index 0000000..0d8a23b --- /dev/null +++ b/era/metadata.h @@ -0,0 +1,47 @@ +#ifndef ERA_METADATA_H +#define ERA_METADATA_H + +#include "base/endian_utils.h" + +#include "persistent-data/block.h" +#include "persistent-data/data-structures/array.h" +#include "persistent-data/data-structures/bitset.h" +#include "persistent-data/space-maps/disk.h" +#include "persistent-data/transaction_manager.h" + +#include "era/superblock.h" +#include "era/bloom_tree.h" +#include "era/era_array.h" + +//---------------------------------------------------------------- + +namespace era { + class metadata { + public: + enum open_type { + CREATE, + OPEN + }; + + typedef block_manager<>::read_ref read_ref; + typedef block_manager<>::write_ref write_ref; + typedef boost::shared_ptr ptr; + + metadata(block_manager<>::ptr bm, open_type ot); + void commit(bool clean_shutdown = true); + + typedef persistent_data::transaction_manager tm; + tm::ptr tm_; + superblock sb_; + checked_space_map::ptr metadata_sm_; + bloom_tree::ptr bloom_tree_; + era_array::ptr era_array_; + + private: + void open_metadata(block_manager<>::ptr bm); + }; +}; + +//---------------------------------------------------------------- + +#endif diff --git a/era/metadata_dump.cc b/era/metadata_dump.cc new file mode 100644 index 0000000..edf4a1d --- /dev/null +++ b/era/metadata_dump.cc @@ -0,0 +1,135 @@ +#include "era/metadata_dump.h" +#include "era/era_array.h" + +using namespace era; +using namespace std; + +//---------------------------------------------------------------- + +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 era_check for details).\n" + "perhaps you wanted to run with --repair ?"); + } + + class bloom_tree_emitter : public bloom_tree_detail::bloom_visitor { + public: + bloom_tree_emitter(emitter::ptr e) + : e_(e) { + } + + virtual void bloom_begin(uint32_t era, uint32_t nr_blocks, uint32_t nr_bits, uint32_t nr_set) { + e_->begin_bloom(era, nr_bits, nr_blocks); + } + + virtual void bit(uint32_t bit, bool value) { + e_->bloom_bit(bit, value); + } + + virtual void bloom_end() { + e_->end_bloom(); + } + + private: + emitter::ptr e_; + }; + + struct ignore_bloom_tree_damage : public bloom_tree_detail::damage_visitor { + void visit(bloom_tree_detail::missing_eras const &d) { + } + + void visit(bloom_tree_detail::damaged_bloom_filter const &d) { + } + }; + + struct fatal_bloom_tree_damage : public bloom_tree_detail::damage_visitor { + void visit(bloom_tree_detail::missing_eras const &d) { + raise_metadata_damage(); + } + + void visit(bloom_tree_detail::damaged_bloom_filter const &d) { + raise_metadata_damage(); + } + }; + + //-------------------------------- + + class era_array_emitter : public era_array_visitor { + public: + era_array_emitter(emitter::ptr e) + : e_(e) { + } + + virtual void visit(uint32_t index, uint32_t era) { + e_->era(index, era); + } + + private: + emitter::ptr e_; + }; + + struct ignore_era_array_damage : public era_array_detail::damage_visitor { + void visit(era_array_detail::missing_eras const &d) { + } + + void visit(era_array_detail::invalid_era const &d) { + } + }; + + class fatal_era_array_damage : public era_array_detail::damage_visitor { + void visit(era_array_detail::missing_eras const &d) { + raise_metadata_damage(); + } + + void visit(era_array_detail::invalid_era const &d) { + raise_metadata_damage(); + } + }; +} + +//---------------------------------------------------------------- + +void +era::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.nr_blocks, + sb.current_era); + { + { + bloom_tree_emitter visitor(e); + + ignore_bloom_tree_damage ignore; + fatal_bloom_tree_damage fatal; + bloom_tree_detail::damage_visitor &dv = repair ? + static_cast(ignore) : + static_cast(fatal); + + walk_bloom_tree(md->tm_, *md->bloom_tree_, visitor, dv); + } + + e->begin_era_array(); + { + era_array_emitter visitor(e); + + ignore_era_array_damage ignore; + fatal_era_array_damage fatal; + era_array_detail::damage_visitor &dv = repair ? + static_cast(ignore) : + static_cast(fatal); + + walk_era_array(*md->era_array_, visitor, dv); + } + e->end_era_array(); + } + e->end_superblock(); +} + +//---------------------------------------------------------------- diff --git a/era/metadata_dump.h b/era/metadata_dump.h new file mode 100644 index 0000000..59d9d67 --- /dev/null +++ b/era/metadata_dump.h @@ -0,0 +1,15 @@ +#ifndef ERA_METADATA_DUMP_H +#define ERA_METADATA_DUMP_H + +#include "era/metadata.h" +#include "era/emitter.h" + +//---------------------------------------------------------------- + +namespace era { + void metadata_dump(metadata::ptr md, emitter::ptr out, bool repair); +} + +//---------------------------------------------------------------- + +#endif diff --git a/era/xml_format.cc b/era/xml_format.cc new file mode 100644 index 0000000..9a63b8a --- /dev/null +++ b/era/xml_format.cc @@ -0,0 +1,103 @@ +#include "era/xml_format.h" + +using namespace boost; +using namespace era; +using namespace persistent_data; +using namespace std; + +//---------------------------------------------------------------- + +namespace { + class xml_emitter : public emitter { + public: + xml_emitter(ostream &out) + : out_(out), + indent_(0) { + } + + void begin_superblock(std::string const &uuid, + uint32_t block_size, + pd::block_address nr_blocks, + uint32_t current_era) { + indent(); + out_ << "" << endl; + inc(); + } + + void end_superblock() { + dec(); + indent(); + out_ << "" << endl; + } + + void begin_bloom(uint32_t era, uint32_t nr_bits, + pd::block_address nr_blocks) { + indent(); + out_ << "" << endl; + inc(); + } + + void bloom_bit(uint32_t bit, bool value) { + indent(); + // FIXME: collect all the bits, then uuencode + out_ << "" << endl; + } + + void end_bloom() { + dec(); + indent(); + out_ << "" << endl; + } + + void begin_era_array() { + indent(); + out_ << "" << endl; + inc(); + } + + void era(pd::block_address block, uint32_t era) { + indent(); + out_ << "" << endl; + } + + void end_era_array() { + dec(); + indent(); + out_ << "" << endl; + } + + private: + // FIXME: factor out a common class with the thin_provisioning emitter + void indent() { + for (unsigned i = 0; i < indent_ * 2; i++) + out_ << ' '; + } + + void inc() { + indent_++; + } + + void dec() { + indent_--; + } + + ostream &out_; + unsigned indent_; + }; +} + +//---------------------------------------------------------------- + +emitter::ptr +era::create_xml_emitter(std::ostream &out) +{ + return emitter::ptr(new xml_emitter(out)); +} + +//---------------------------------------------------------------- diff --git a/era/xml_format.h b/era/xml_format.h new file mode 100644 index 0000000..30b7174 --- /dev/null +++ b/era/xml_format.h @@ -0,0 +1,17 @@ +#ifndef ERA_XML_FORMAT_H +#define ERA_XML_FORMAT_H + +#include "emitter.h" + +#include + +//---------------------------------------------------------------- + +namespace era { + emitter::ptr create_xml_emitter(std::ostream &out); + void parse_xml(std::istream &in, emitter::ptr e); +} + +//---------------------------------------------------------------- + +#endif diff --git a/persistent-data/data-structures/bitset.cc b/persistent-data/data-structures/bitset.cc index 6bab965..47a47bf 100644 --- a/persistent-data/data-structures/bitset.cc +++ b/persistent-data/data-structures/bitset.cc @@ -27,6 +27,8 @@ namespace { namespace persistent_data { namespace bitset_detail { + size_t BITS_PER_ULL = 64; + class bitset_impl { public: typedef boost::shared_ptr ptr; @@ -39,7 +41,7 @@ namespace persistent_data { bitset_impl(tm_ptr tm, block_address root, unsigned nr_bits) : nr_bits_(nr_bits), - array_(tm, rc_, root, nr_bits) { + array_(tm, rc_, root, nr_bits / BITS_PER_ULL) { } block_address get_root() const { diff --git a/persistent-data/data-structures/btree.h b/persistent-data/data-structures/btree.h index 93c3284..f060279 100644 --- a/persistent-data/data-structures/btree.h +++ b/persistent-data/data-structures/btree.h @@ -43,22 +43,6 @@ namespace persistent_data { space_map::ptr sm_; }; - // FIXME: move to sep file. I don't think it's directly used by - // the btree code. - struct uint64_traits { - typedef base::le64 disk_type; - typedef uint64_t value_type; - typedef no_op_ref_counter ref_counter; - - static void unpack(disk_type const &disk, value_type &value) { - value = base::to_cpu(disk); - } - - static void pack(value_type const &value, disk_type &disk) { - disk = base::to_disk(value); - } - }; - struct block_traits { typedef base::le64 disk_type; typedef block_address value_type; diff --git a/persistent-data/data-structures/simple_traits.h b/persistent-data/data-structures/simple_traits.h new file mode 100644 index 0000000..fa01737 --- /dev/null +++ b/persistent-data/data-structures/simple_traits.h @@ -0,0 +1,38 @@ +#ifndef PERSISTENT_DATA_DATA_STRUCTURES_SIMPLE_TRAITS_H +#define PERSISTENT_DATA_DATA_STRUCTURES_SIMPLE_TRAITS_H + +//---------------------------------------------------------------- + +namespace persistent_data { + struct uint64_traits { + typedef base::le64 disk_type; + typedef uint64_t value_type; + typedef no_op_ref_counter ref_counter; + + static void unpack(disk_type const &disk, value_type &value) { + value = base::to_cpu(disk); + } + + static void pack(value_type const &value, disk_type &disk) { + disk = base::to_disk(value); + } + }; + + struct uint32_traits { + typedef base::le32 disk_type; + typedef uint32_t value_type; + typedef no_op_ref_counter ref_counter; + + static void unpack(disk_type const &disk, value_type &value) { + value = base::to_cpu(disk); + } + + static void pack(value_type const &value, disk_type &disk) { + disk = base::to_disk(value); + } + }; +} + +//---------------------------------------------------------------- + +#endif