diff --git a/caching/cache_check.cc b/caching/cache_check.cc index cbe4581..419169f 100644 --- a/caching/cache_check.cc +++ b/caching/cache_check.cc @@ -254,7 +254,7 @@ namespace { out << "examining discard bitset" << end_message(); { nested_output::nest _ = out.push(); - bitset discards(tm, sb.discard_root, sb.discard_nr_blocks); + persistent_data::bitset discards(tm, sb.discard_root, sb.discard_nr_blocks); } } } diff --git a/caching/cache_repair.cc b/caching/cache_repair.cc index 5d1aafa..4a8cd9c 100644 --- a/caching/cache_repair.cc +++ b/caching/cache_repair.cc @@ -23,7 +23,7 @@ namespace { emitter::ptr output_emitter(string const &path) { block_manager<>::ptr bm = open_bm(path, block_io<>::READ_WRITE); metadata::ptr md(new metadata(bm, metadata::CREATE)); - return create_restore_emitter(md); + return create_restore_emitter(md, true); } int repair(string const &old_path, string const &new_path) { diff --git a/caching/cache_restore.cc b/caching/cache_restore.cc index b672932..536ef82 100644 --- a/caching/cache_restore.cc +++ b/caching/cache_restore.cc @@ -23,20 +23,23 @@ namespace { struct flags { flags() : metadata_version(1), - override_metadata_version(false) { + override_metadata_version(false), + clean_shutdown(true) { } optional input; optional output; + uint32_t metadata_version; bool override_metadata_version; + bool clean_shutdown; }; int restore(flags const &fs) { try { block_manager<>::ptr bm = open_bm(*fs.output, block_io<>::READ_WRITE); metadata::ptr md(new metadata(bm, metadata::CREATE)); - emitter::ptr restorer = create_restore_emitter(md); + emitter::ptr restorer = create_restore_emitter(md, fs.clean_shutdown); if (fs.override_metadata_version) { cerr << "overriding" << endl; @@ -63,7 +66,8 @@ namespace { << " {-o|--output} " << endl << " {-V|--version}" << endl << endl - << " {--debug-override-metadata-version} " << endl; + << " {--debug-override-metadata-version} " << endl + << " {--omit-clean-shutdown}" << endl; } } @@ -76,6 +80,7 @@ int main(int argc, char **argv) char const *short_opts = "hi:o:V"; option const long_opts[] = { { "debug-override-metadata-version", required_argument, NULL, 0 }, + { "omit-clean-shutdown", no_argument, NULL, 1 }, { "help", no_argument, NULL, 'h'}, { "input", required_argument, NULL, 'i' }, { "output", required_argument, NULL, 'o'}, @@ -90,6 +95,10 @@ int main(int argc, char **argv) fs.override_metadata_version = true; break; + case 1: + fs.clean_shutdown = false; + break; + case 'h': usage(cout, prog_name); return 0; diff --git a/caching/metadata.cc b/caching/metadata.cc index 2d8ef83..0a246f9 100644 --- a/caching/metadata.cc +++ b/caching/metadata.cc @@ -47,13 +47,13 @@ metadata::metadata(block_manager<>::ptr bm, open_type ot) } void -metadata::commit() +metadata::commit(bool clean_shutdown) { commit_space_map(); commit_mappings(); commit_hints(); commit_discard_bits(); - commit_superblock(); + commit_superblock(clean_shutdown); } void @@ -79,7 +79,7 @@ metadata::create_metadata(block_manager<>::ptr bm) // We can't instantiate the hint array yet, since we don't know the // hint width. - discard_bits_ = bitset::ptr(new bitset(tm_)); + discard_bits_ = persistent_data::bitset::ptr(new persistent_data::bitset(tm_)); } void @@ -100,8 +100,8 @@ metadata::open_metadata(block_manager<>::ptr bm) sb_.hint_root, sb_.cache_blocks)); if (sb_.discard_root) - discard_bits_ = bitset::ptr( - new bitset(tm_, sb_.discard_root, sb_.discard_nr_blocks)); + discard_bits_ = persistent_data::bitset::ptr( + new persistent_data::bitset(tm_, sb_.discard_root, sb_.discard_nr_blocks)); } void @@ -130,10 +130,13 @@ metadata::commit_discard_bits() } void -metadata::commit_superblock() +metadata::commit_superblock(bool clean_shutdown) { - sb_.flags.set_flag(superblock_flags::CLEAN_SHUTDOWN); + if (clean_shutdown) + sb_.flags.set_flag(superblock_flags::CLEAN_SHUTDOWN); + write_superblock(tm_->get_bm(), sb_); + sb_.flags.clear_flag(superblock_flags::CLEAN_SHUTDOWN); } diff --git a/caching/metadata.h b/caching/metadata.h index a606878..46c2b93 100644 --- a/caching/metadata.h +++ b/caching/metadata.h @@ -29,7 +29,7 @@ namespace caching { metadata(block_manager<>::ptr bm, open_type ot); - void commit(); + void commit(bool clean_shutdown = true); void setup_hint_array(size_t width); @@ -39,7 +39,7 @@ namespace caching { checked_space_map::ptr metadata_sm_; mapping_array::ptr mappings_; hint_array::ptr hints_; - bitset::ptr discard_bits_; + persistent_data::bitset::ptr discard_bits_; private: void init_superblock(); @@ -51,7 +51,7 @@ namespace caching { void commit_mappings(); void commit_hints(); void commit_discard_bits(); - void commit_superblock(); + void commit_superblock(bool clean_shutdown); }; }; diff --git a/caching/restore_emitter.cc b/caching/restore_emitter.cc index 6c862bf..55be343 100644 --- a/caching/restore_emitter.cc +++ b/caching/restore_emitter.cc @@ -11,9 +11,10 @@ using namespace superblock_damage; namespace { class restorer : public emitter { public: - restorer(metadata::ptr md) + restorer(metadata::ptr md, bool clean_shutdown) : in_superblock_(false), - md_(md) { + md_(md), + clean_shutdown_(clean_shutdown) { } virtual ~restorer() { @@ -44,7 +45,7 @@ namespace { } virtual void end_superblock() { - md_->commit(); + md_->commit(clean_shutdown_); } virtual void begin_mappings() { @@ -99,15 +100,16 @@ namespace { private: bool in_superblock_; metadata::ptr md_; + bool clean_shutdown_; }; } //---------------------------------------------------------------- emitter::ptr -caching::create_restore_emitter(metadata::ptr md) +caching::create_restore_emitter(metadata::ptr md, bool clean_shutdown) { - return emitter::ptr(new restorer(md)); + return emitter::ptr(new restorer(md, clean_shutdown)); } //---------------------------------------------------------------- diff --git a/caching/restore_emitter.h b/caching/restore_emitter.h index 658dc68..9282895 100644 --- a/caching/restore_emitter.h +++ b/caching/restore_emitter.h @@ -7,7 +7,7 @@ //---------------------------------------------------------------- namespace caching { - emitter::ptr create_restore_emitter(metadata::ptr md); + emitter::ptr create_restore_emitter(metadata::ptr md, bool clean_shutdown = true); } //---------------------------------------------------------------- diff --git a/features/cache_restore.feature b/features/cache_restore.feature index b9eef7d..1052089 100644 --- a/features/cache_restore.feature +++ b/features/cache_restore.feature @@ -21,6 +21,7 @@ Feature: thin_restore {-V|--version} {--debug-override-metadata-version} + {--omit-clean-shutdown} """ @@ -38,6 +39,7 @@ Feature: thin_restore {-V|--version} {--debug-override-metadata-version} + {--omit-clean-shutdown} """ @@ -72,3 +74,9 @@ Feature: thin_restore And an empty dev file When I run cache_restore with -i metadata.xml -o metadata.bin --debug-override-metadata-version 10298 Then it should pass + + Scenario: accepts --omit-clean-shutdown + Given a small xml file + And an empty dev file + When I run cache_restore with -i metadata.xml -o metadata.bin --omit-clean-shutdown + Then it should pass diff --git a/persistent-data/data-structures/bitset.cc b/persistent-data/data-structures/bitset.cc index c9ad0b4..1de628f 100644 --- a/persistent-data/data-structures/bitset.cc +++ b/persistent-data/data-structures/bitset.cc @@ -202,18 +202,18 @@ namespace persistent_data { //---------------------------------------------------------------- -bitset::bitset(tm_ptr tm) +persistent_data::bitset::bitset(tm_ptr tm) : impl_(new bitset_impl(tm)) { } -bitset::bitset(tm_ptr tm, block_address root, unsigned nr_bits) +persistent_data::bitset::bitset(tm_ptr tm, block_address root, unsigned nr_bits) : impl_(new bitset_impl(tm, root, nr_bits)) { } block_address -bitset::get_root() const +persistent_data::bitset::get_root() const { return impl_->get_root(); } @@ -225,37 +225,37 @@ bitset::get_nr_bits() const } void -bitset::grow(unsigned new_nr_bits, bool default_value) +persistent_data::bitset::grow(unsigned new_nr_bits, bool default_value) { impl_->grow(new_nr_bits, default_value); } void -bitset::destroy() +persistent_data::bitset::destroy() { impl_->destroy(); } bool -bitset::get(unsigned n) +persistent_data::bitset::get(unsigned n) { return impl_->get(n); } void -bitset::set(unsigned n, bool value) +persistent_data::bitset::set(unsigned n, bool value) { impl_->set(n, value); } void -bitset::flush() +persistent_data::bitset::flush() { impl_->flush(); } void -bitset::walk_bitset(bitset_visitor &v) const +persistent_data::bitset::walk_bitset(bitset_visitor &v) const { impl_->walk_bitset(v); }