From 85ba887a9ce56c94861cfc60cce6eae90b9f3a79 Mon Sep 17 00:00:00 2001 From: sharkdp Date: Sun, 4 Nov 2018 20:35:45 +0100 Subject: Move error handling to main thread --- src/main.rs | 2 +- src/walk.rs | 51 ++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/main.rs b/src/main.rs index 83b1027..1a17a51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,9 @@ #[macro_use] extern crate clap; +extern crate crossbeam_channel; extern crate humansize; extern crate num_cpus; extern crate rayon; -extern crate crossbeam_channel; mod walk; diff --git a/src/walk.rs b/src/walk.rs index a5daac6..28a1059 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -8,12 +8,16 @@ use crossbeam_channel as channel; use rayon::prelude::*; -#[derive(Eq,PartialEq,Hash)] +#[derive(Eq, PartialEq, Hash)] struct UniqueID(u64, u64); -struct SizeEntry(Option, u64); +enum Message { + SizeEntry(Option, u64), + NoMetadataForPath(PathBuf), + CouldNotReadDir(PathBuf), +} -fn walk(tx: channel::Sender, entries: &[PathBuf]) { +fn walk(tx: channel::Sender, entries: &[PathBuf]) { entries.into_par_iter().for_each_with(tx, |tx_ref, entry| { if let Ok(metadata) = entry.symlink_metadata() { // If the entry has more than one hard link, generate @@ -27,20 +31,27 @@ fn walk(tx: channel::Sender, entries: &[PathBuf]) { let size = metadata.len(); - tx_ref.send(SizeEntry(unique_id, size)).unwrap(); + tx_ref.send(Message::SizeEntry(unique_id, size)).unwrap(); if metadata.is_dir() { let mut children = vec![]; - for child_entry in fs::read_dir(entry).unwrap() { - if let Ok(child_entry) = child_entry { - children.push(child_entry.path()); + match fs::read_dir(entry) { + Ok(child_entries) => { + for child_entry in child_entries { + if let Ok(child_entry) = child_entry { + children.push(child_entry.path()); + } + } + } + Err(err) => { + tx_ref.send(Message::CouldNotReadDir(entry.clone())).unwrap(); } } walk(tx_ref.clone(), &children[..]); }; } else { - eprintln!("Could not get file metadata: '{}'", entry.to_string_lossy()); + tx_ref.send(Message::NoMetadataForPath(entry.clone())).unwrap(); }; }); } @@ -64,14 +75,24 @@ impl<'a> Walk<'a> { let receiver_thread = thread::spawn(move || { let mut total = 0; let mut ids = HashSet::new(); - for SizeEntry(unique_id, size) in rx { - if let Some(unique_id) = unique_id { - // Only count this entry if the ID has not been seen - if ids.insert(unique_id) { - total += size; + for msg in rx { + match msg { + Message::SizeEntry(unique_id, size) => { + if let Some(unique_id) = unique_id { + // Only count this entry if the ID has not been seen + if ids.insert(unique_id) { + total += size; + } + } else { + total += size; + } + } + Message::NoMetadataForPath(path) => { + eprintln!("diskus: could not metadata for path '{}'", path.to_string_lossy()); + } + Message::CouldNotReadDir(path) => { + eprintln!("diskus: could not contents of directory '{}'", path.to_string_lossy()); } - } else { - total += size; } } -- cgit v1.2.3