diff --git a/src/bin/cache_restore.rs b/src/bin/cache_restore.rs index e1f4209..f580777 100644 --- a/src/bin/cache_restore.rs +++ b/src/bin/cache_restore.rs @@ -29,6 +29,12 @@ fn main() { .value_name("OVERRIDE_MAPPING_ROOT") .takes_value(true), ) + .arg( + Arg::with_name("QUIET") + .help("Suppress output messages, return only exit code.") + .short("q") + .long("quiet"), + ) // options .arg( Arg::with_name("INPUT") diff --git a/src/cache/dump.rs b/src/cache/dump.rs index c5c33c1..a5b9309 100644 --- a/src/cache/dump.rs +++ b/src/cache/dump.rs @@ -218,15 +218,12 @@ fn mk_context(opts: &CacheDumpOptions) -> anyhow::Result { Ok(Context { engine }) } -fn dump_metadata( - ctx: &Context, - w: &mut dyn Write, +pub fn dump_metadata( + engine: Arc, + out: &mut dyn MetadataVisitor, sb: &Superblock, _repair: bool, ) -> anyhow::Result<()> { - let engine = &ctx.engine; - - let mut out = xml::XmlWriter::new(w); let xml_sb = ir::Superblock { uuid: "".to_string(), block_size: sb.data_block_size, @@ -240,7 +237,7 @@ fn dump_metadata( let valid_mappings = match sb.version { 1 => { let w = ArrayWalker::new(engine.clone(), false); - let mut emitter = format1::MappingEmitter::new(sb.cache_blocks as usize, &mut out); + let mut emitter = format1::MappingEmitter::new(sb.cache_blocks as usize, out); w.walk(&mut emitter, sb.mapping_root)?; emitter.get_valid() } @@ -263,7 +260,7 @@ fn dump_metadata( let w = ArrayWalker::new(engine.clone(), false); let mut emitter = - format2::MappingEmitter::new(sb.cache_blocks as usize, dirty_bits, &mut out); + format2::MappingEmitter::new(sb.cache_blocks as usize, dirty_bits, out); w.walk(&mut emitter, sb.mapping_root)?; emitter.get_valid() } @@ -276,7 +273,7 @@ fn dump_metadata( out.hints_b()?; { let w = ArrayWalker::new(engine.clone(), false); - let mut emitter = HintEmitter::new(&mut out, valid_mappings); + let mut emitter = HintEmitter::new(out, valid_mappings); w.walk(&mut emitter, sb.hint_root)?; } out.hints_e()?; @@ -289,17 +286,17 @@ fn dump_metadata( pub fn dump(opts: CacheDumpOptions) -> anyhow::Result<()> { let ctx = mk_context(&opts)?; - let engine = &ctx.engine; - let sb = read_superblock(engine.as_ref(), SUPERBLOCK_LOCATION)?; + let sb = read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION)?; - let mut writer: Box; + let writer: Box; if opts.output.is_some() { writer = Box::new(BufWriter::new(File::create(opts.output.unwrap())?)); } else { writer = Box::new(BufWriter::new(std::io::stdout())); } + let mut out = xml::XmlWriter::new(writer); - dump_metadata(&ctx, &mut writer, &sb, opts.repair) + dump_metadata(ctx.engine.clone(), &mut out, &sb, opts.repair) } //------------------------------------------ diff --git a/src/cache/restore.rs b/src/cache/restore.rs index 5d5f23c..067462a 100644 --- a/src/cache/restore.rs +++ b/src/cache/restore.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result}; +use anyhow::Result; use std::convert::TryInto; use std::fs::OpenOptions; @@ -56,15 +56,7 @@ fn mk_context(opts: &CacheRestoreOptions) -> anyhow::Result { //------------------------------------------ -struct RestoreResult { - sb: ir::Superblock, - mapping_root: u64, - dirty_root: Option, - hint_root: u64, - discard_root: u64, -} - -struct Restorer<'a> { +pub struct Restorer<'a> { write_batcher: &'a mut WriteBatcher, sb: Option, mapping_builder: Option>, @@ -78,7 +70,7 @@ struct Restorer<'a> { } impl<'a> Restorer<'a> { - fn new(w: &'a mut WriteBatcher) -> Restorer<'a> { + pub fn new(w: &'a mut WriteBatcher) -> Restorer<'a> { Restorer { write_batcher: w, sb: None, @@ -93,22 +85,42 @@ impl<'a> Restorer<'a> { } } - fn get_result(self) -> Result { - self.write_batcher.flush()?; + fn finalize(&mut self) -> Result<()> { + // build metadata space map + let metadata_sm_root = build_metadata_sm(self.write_batcher)?; - if self.sb.is_none() || self.discard_root.is_none() { - return Err(anyhow!("No superblock found in xml file")); - } - if self.mapping_root.is_none() || self.hint_root.is_none() { - return Err(anyhow!("No mappings or hints sections in xml file")); - } - Ok(RestoreResult { - sb: self.sb.unwrap(), - mapping_root: self.mapping_root.unwrap(), - dirty_root: self.dirty_root, - hint_root: self.hint_root.unwrap(), - discard_root: self.discard_root.unwrap(), - }) + let sb = self.sb.as_ref().unwrap(); + let mapping_root = self.mapping_root.as_ref().unwrap(); + let hint_root = self.hint_root.as_ref().unwrap(); + let discard_root = self.discard_root.as_ref().unwrap(); + let sb = Superblock { + flags: SuperblockFlags { + clean_shutdown: true, + needs_check: false, + }, + block: SUPERBLOCK_LOCATION, + version: 2, + policy_name: sb.policy.as_bytes().to_vec(), + policy_version: vec![2, 0, 0], + policy_hint_size: sb.hint_width, + metadata_sm_root, + mapping_root: *mapping_root, + dirty_root: self.dirty_root, // dirty_root is optional + hint_root: *hint_root, + discard_root: *discard_root, + discard_block_size: 0, + discard_nr_blocks: 0, + data_block_size: sb.block_size, + cache_blocks: sb.nr_cache_blocks, + compat_flags: 0, + compat_ro_flags: 0, + incompat_flags: 0, + read_hits: 0, + read_misses: 9, + write_hits: 0, + write_misses: 0, + }; + write_superblock(self.write_batcher.engine.as_ref(), SUPERBLOCK_LOCATION, &sb) } } @@ -127,6 +139,7 @@ impl<'a> MetadataVisitor for Restorer<'a> { } fn superblock_e(&mut self) -> Result { + self.finalize()?; Ok(Visit::Continue) } @@ -252,39 +265,6 @@ pub fn restore(opts: CacheRestoreOptions) -> Result<()> { // build cache mappings let mut restorer = Restorer::new(&mut w); xml::read(input, &mut restorer)?; - let result = restorer.get_result()?; - - // build metadata space map - let metadata_sm_root = build_metadata_sm(&mut w)?; - - let sb = Superblock { - flags: SuperblockFlags { - clean_shutdown: true, - needs_check: false, - }, - block: SUPERBLOCK_LOCATION, - version: 2, - policy_name: result.sb.policy.as_bytes().to_vec(), - policy_version: vec![2, 0, 0], - policy_hint_size: result.sb.hint_width, - metadata_sm_root, - mapping_root: result.mapping_root, - dirty_root: result.dirty_root, - hint_root: result.hint_root, - discard_root: result.discard_root, - discard_block_size: 0, - discard_nr_blocks: 0, - data_block_size: result.sb.block_size, - cache_blocks: result.sb.nr_cache_blocks, - compat_flags: 0, - compat_ro_flags: 0, - incompat_flags: 0, - read_hits: 0, - read_misses: 9, - write_hits: 0, - write_misses: 0, - }; - write_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION, &sb)?; Ok(()) }