From e7223037d4be680cecf7f1d3569b0a0b9ec9521e Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 2 Oct 2013 10:50:42 +0100 Subject: [PATCH] [cache_check] wip --- Makefile.in | 2 + caching/cache_check.cc | 173 ++++++++++++++++++++++++++++++++++------- 2 files changed, 148 insertions(+), 27 deletions(-) diff --git a/Makefile.in b/Makefile.in index ddabacb..1781abf 100644 --- a/Makefile.in +++ b/Makefile.in @@ -226,9 +226,11 @@ thin_metadata_size: thin-provisioning/thin_metadata_size.o # Cache tools CACHE_CHECK_SOURCE=\ + base/error_state.cc \ persistent-data/checksum.cc \ persistent-data/endian_utils.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 \ diff --git a/caching/cache_check.cc b/caching/cache_check.cc index 3de52dc..5cb2c7d 100644 --- a/caching/cache_check.cc +++ b/caching/cache_check.cc @@ -14,12 +14,108 @@ #include "base/error_state.h" #include "base/nested_output.h" +#include "caching/metadata.h" +#include "persistent-data/block.h" +#include "persistent-data/file_utils.h" +#include "persistent-data/space-maps/core.h" +using namespace boost; +using namespace caching; +using namespace persistent_data; using namespace std; //---------------------------------------------------------------- namespace { + + class reporter_base { + public: + reporter_base(nested_output &o) + : out_(o), + err_(NO_ERROR) { + } + + virtual ~reporter_base() {} + + nested_output &out() { + return out_; + } + + nested_output::nest push() { + return out_.push(); + } + + base::error_state get_error() const { + return err_; + } + + void mplus_error(error_state err) { + err_ = combine_errors(err_, err); + } + + private: + nested_output &out_; + error_state err_; + }; + + class superblock_reporter : public superblock_detail::damage_visitor, reporter_base { + public: + superblock_reporter(nested_output &o) + : reporter_base(o) { + } + + virtual void visit(superblock_detail::superblock_corruption const &d) { + out() << "superblock is corrupt" << end_message(); + { + nested_output::nest _ = push(); + out() << d.desc_ << end_message(); + } + + mplus_error(FATAL); + } + + using reporter_base::get_error; + }; + + class mapping_reporter : public reporter_base { + public: + mapping_reporter(nested_output &o) + : reporter_base(o) { + } + }; + + class hint_reporter : public reporter_base { + public: + hint_reporter(nested_output &o) + : reporter_base(o) { + } + }; + + //-------------------------------- + + transaction_manager::ptr open_tm(block_manager<>::ptr bm) { + space_map::ptr sm(new core_map(bm->get_nr_blocks())); + sm->inc(superblock_detail::SUPERBLOCK_LOCATION); + transaction_manager::ptr tm(new transaction_manager(bm, sm)); + return tm; + } + + //-------------------------------- + + struct flags { + flags() + : check_mappings_(false), + check_hints_(false), + ignore_non_fatal_errors_(false), + quiet_(false) { + } + + bool check_mappings_; + bool check_hints_; + bool ignore_non_fatal_errors_; + bool quiet_; + }; + struct stat guarded_stat(string const &path) { struct stat info; @@ -36,21 +132,49 @@ namespace { return info; } - int open_file(string const &path, int mode) { - int fd = open(path.c_str(), mode); - if (fd < 0) { - ostringstream msg; - char buffer[128], *ptr; + error_state metadata_check(block_manager<>::ptr bm, flags const &fs) { + error_state err = NO_ERROR; - ptr = strerror_r(errno, buffer, sizeof(buffer)); - msg << path << ": " << ptr; - throw runtime_error(msg.str()); + nested_output out(cerr, 2); + if (fs.quiet_) + out.disable(); + + superblock_reporter sb_rep(out); + mapping_reporter mapping_rep(out); + hint_reporter hint_rep(out); + + out << "examining superblock" << end_message(); + { + nested_output::nest _ = out.push(); + check_superblock(bm, sb_rep); } - return fd; + if (sb_rep.get_error() == FATAL) + return FATAL; + + superblock_detail::superblock sb = read_superblock(bm); + transaction_manager::ptr tm = open_tm(bm); + + if (fs.check_mappings_) { + out << "examining mapping array" << end_message(); + { + nested_output::nest _ = out.push(); + mapping_array ma(tm, mapping_array::ref_counter(), sb.mapping_root, sb.cache_blocks); + // check_mapping_array(ma, mapping_rep); + } + } + + if (fs.check_hints_) { + out << "examining hint array" << end_message(); + { + nested_output::nest _ = out.push(); + } + } + + return err; } - int check(string const &path, bool quiet) { + int check(string const &path, flags const &fs) { struct stat info = guarded_stat(path); if (!S_ISREG(info.st_mode) && !S_ISBLK(info.st_mode)) { @@ -59,31 +183,26 @@ namespace { throw runtime_error(msg.str()); } - int fd = open_file(path, O_RDONLY); - - ostringstream msg; - msg << path << ": " << "No superblock found"; - throw runtime_error(msg.str()); - return 0; - -#if 0 try { - metadata::ptr md(new metadata(path, metadata::OPEN)); + block_manager<>::ptr bm = open_bm(path, block_io<>::READ_ONLY); + //metadata::ptr md(new metadata(bm, metadata::OPEN)); - optional maybe_errors = metadata_check(md); + error_state err = metadata_check(bm, fs); +#if 0 if (maybe_errors) { - if (!quiet) + if (!fs.quiet_) cerr << error_selector(*maybe_errors, 3); return 1; } +#endif + } catch (std::exception &e) { - if (!quiet) + if (!fs.quiet_) cerr << e.what() << endl; return 1; } return 0; -#endif } void usage(ostream &out, string const &cmd) { @@ -102,7 +221,7 @@ namespace { int main(int argc, char **argv) { int c; - bool quiet = false; + flags fs; const char shortopts[] = "qhV"; const struct option longopts[] = { { "quiet", no_argument, NULL, 'q'}, @@ -118,7 +237,7 @@ int main(int argc, char **argv) return 0; case 'q': - quiet = true; + fs.quiet_ = true; break; case 'V': @@ -138,9 +257,9 @@ int main(int argc, char **argv) } try { - check(argv[optind], quiet); + check(argv[optind], fs); - } catch (exception const &e) { + } catch (std::exception const &e) { cerr << e.what() << endl; return 1; }