From afa3f2f04d234783165291a7de2bab745acb9c57 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 12 Aug 2020 10:25:06 +0100 Subject: [PATCH] [thin_check (rust)] Rename Spinner -> Reporter --- src/thin/check.rs | 117 +++++++++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 38 deletions(-) diff --git a/src/thin/check.rs b/src/thin/check.rs index 23f8307..1ffce8e 100644 --- a/src/thin/check.rs +++ b/src/thin/check.rs @@ -179,69 +179,109 @@ impl<'a> NodeVisitor for OverflowChecker<'a> { //------------------------------------------ -enum SpinnerCmd { +struct ReportOptions {} + +#[derive(Clone)] +enum ReportOutcome { + Success, + NonFatal, + Fatal, +} + +use ReportOutcome::*; + +impl ReportOutcome { + fn combine(lhs: &ReportOutcome, rhs: &ReportOutcome) -> ReportOutcome { + match (lhs, rhs) { + (Success, rhs) => rhs.clone(), + (lhs, Success) => lhs.clone(), + (Fatal, _) => Fatal, + (_, Fatal) => Fatal, + (_, _) => NonFatal, + } + } +} + +enum ReportCmd { Log(String), Complete, - Abort, Title(String), } -struct Spinner { - tx: Sender, +struct Report { + opts: ReportOptions, + outcome: ReportOutcome, + tx: Sender, tid: thread::JoinHandle<()>, } -impl Spinner { - fn new(sm: Arc>, total_allocated: u64) -> Result { +impl Report { + fn new( + opts: ReportOptions, + sm: Arc>, + total_allocated: u64, + ) -> Result { let (tx, rx) = channel(); - let tid = thread::spawn(move || spinner_thread(sm, total_allocated, rx)); - Ok(Spinner { tx, tid }) + let tid = thread::spawn(move || report_thread(sm, total_allocated, rx)); + Ok(Report { + opts, + outcome: ReportOutcome::Success, + tx, + tid, + }) } - fn log>(&mut self, txt: I) -> Result<()> { - self.tx.send(SpinnerCmd::Log(txt.into()))?; + fn info>(&mut self, txt: I) -> Result<()> { + self.tx.send(ReportCmd::Log(txt.into()))?; + Ok(()) + } + + fn add_outcome(&mut self, rhs: ReportOutcome) { + self.outcome = ReportOutcome::combine(&self.outcome, &rhs); + } + + fn non_fatal>(&mut self, txt: I) -> Result<()> { + self.add_outcome(NonFatal); + self.tx.send(ReportCmd::Log(txt.into()))?; + Ok(()) + } + + fn fatal>(&mut self, txt: I) -> Result<()> { + self.add_outcome(Fatal); + self.tx.send(ReportCmd::Log(txt.into()))?; Ok(()) } fn complete(self) -> Result<()> { - self.tx.send(SpinnerCmd::Complete)?; - self.tid.join(); - Ok(()) - } - - fn abort(self) -> Result<()> { - self.tx.send(SpinnerCmd::Abort)?; + self.tx.send(ReportCmd::Complete)?; self.tid.join(); Ok(()) } fn set_title(&mut self, txt: &str) -> Result<()> { - self.tx.send(SpinnerCmd::Title(txt.to_string()))?; + self.tx.send(ReportCmd::Title(txt.to_string()))?; Ok(()) } } -fn spinner_thread( +fn report_thread( sm: Arc>, total_allocated: u64, - rx: Receiver, + rx: Receiver, ) { let interval = time::Duration::from_millis(250); let bar = ProgressBar::new(total_allocated); loop { loop { match rx.try_recv() { - Ok(SpinnerCmd::Log(txt)) => { + Ok(ReportCmd::Log(txt)) => { bar.println(txt); } - Ok(SpinnerCmd::Complete) => { + Ok(ReportCmd::Complete) => { bar.finish(); return; } - Ok(SpinnerCmd::Abort) => { - return; - } - Ok(SpinnerCmd::Title(txt)) => { + Ok(ReportCmd::Title(txt)) => { let mut fmt = "Checking thin metadata [{bar:40}] Remaining {eta}, ".to_string(); fmt.push_str(&txt); bar.set_style( @@ -275,7 +315,7 @@ fn spinner_thread( fn check_space_map( kind: &str, engine: Arc, - bar: &mut Spinner, + bar: &mut Report, entries: Vec, metadata_sm: Option>>, sm: Arc>, @@ -327,7 +367,7 @@ fn check_space_map( if actual == 1 && expected == 0 { leaks += 1; } else if actual != expected as u8 { - bar.log(format!("Bad reference count for {} block {}. Expected {}, but space map contains {}.", + bar.fatal(format!("Bad reference count for {} block {}. Expected {}, but space map contains {}.", kind, blocknr, expected, actual))?; fail = true; } @@ -335,7 +375,7 @@ fn check_space_map( BitmapEntry::Overflow => { let expected = sm.get(blocknr)?; if expected < 3 { - bar.log(format!("Bad reference count for {} block {}. Expected {}, but space map says it's >= 3.", + bar.fatal(format!("Bad reference count for {} block {}. Expected {}, but space map says it's >= 3.", kind, blocknr, expected))?; fail = true; } @@ -346,7 +386,7 @@ fn check_space_map( } if leaks > 0 { - bar.log(format!( + bar.non_fatal(format!( "{} {} blocks have leaked. Use --auto-repair to fix.", leaks, kind ))?; @@ -404,9 +444,10 @@ pub fn check(opts: &ThinCheckOptions) -> Result<()> { let devs = btree_to_map::(engine.clone(), false, sb.details_root)?; let nr_devs = devs.len(); let metadata_sm = core_sm(engine.get_nr_blocks(), nr_devs as u32); - let mut spinner = Spinner::new(metadata_sm.clone(), nr_allocated_metadata)?; + let opts = ReportOptions {}; + let mut report = Report::new(opts, metadata_sm.clone(), nr_allocated_metadata)?; - spinner.set_title("device details tree")?; + report.set_title("device details tree")?; let _devs = btree_to_map_with_sm::( engine.clone(), metadata_sm.clone(), @@ -424,7 +465,7 @@ pub fn check(opts: &ThinCheckOptions) -> Result<()> { let roots = btree_to_map::(engine.clone(), false, sb.mapping_root)?; // Check the mappings filling in the data_sm as we go. - spinner.set_title("mapping tree")?; + report.set_title("mapping tree")?; let data_sm; { // FIXME: with a thread pool we need to return errors another way. @@ -456,7 +497,7 @@ pub fn check(opts: &ThinCheckOptions) -> Result<()> { pool.join(); } - spinner.set_title("data space map")?; + report.set_title("data space map")?; let root = unpack::(&sb.data_sm_root[0..])?; let entries = btree_to_map_with_sm::( @@ -471,14 +512,14 @@ pub fn check(opts: &ThinCheckOptions) -> Result<()> { check_space_map( "data", engine.clone(), - &mut spinner, + &mut report, entries, Some(metadata_sm.clone()), data_sm.clone(), root, )?; - spinner.set_title("metadata space map")?; + report.set_title("metadata space map")?; let root = unpack::(&sb.metadata_sm_root[0..])?; let mut b = Block::new(root.bitmap_root); engine.read(&mut b)?; @@ -503,14 +544,14 @@ pub fn check(opts: &ThinCheckOptions) -> Result<()> { check_space_map( "metadata", engine.clone(), - &mut spinner, + &mut report, entries, None, metadata_sm.clone(), root, )?; - spinner.complete()?; + report.complete()?; Ok(()) }