diff options
author | Piotr Wach <pwach@bloomberg.net> | 2024-01-13 21:44:42 +0000 |
---|---|---|
committer | Piotr Wach <pwach@bloomberg.net> | 2024-01-14 15:01:17 +0000 |
commit | 969e64bbde872d0598b1ebf6278f5d55e152f7b1 (patch) | |
tree | 01192ffbb4158c01b150df7740c9316906a02c18 /src | |
parent | 226cbb8b2d6388ddd7a7e48fdac1a4db2ee75474 (diff) |
Moved traversal stats to separate type
Diffstat (limited to 'src')
-rw-r--r-- | src/interactive/app/eventloop.rs | 29 | ||||
-rw-r--r-- | src/interactive/app/state.rs | 4 | ||||
-rw-r--r-- | src/interactive/app/terminal.rs | 22 | ||||
-rw-r--r-- | src/interactive/app/tree_view.rs | 12 | ||||
-rw-r--r-- | src/traverse.rs | 88 |
5 files changed, 94 insertions, 61 deletions
diff --git a/src/interactive/app/eventloop.rs b/src/interactive/app/eventloop.rs index 5ce8cd6..561b8f7 100644 --- a/src/interactive/app/eventloop.rs +++ b/src/interactive/app/eventloop.rs @@ -10,7 +10,7 @@ use crossbeam::channel::Receiver; use crosstermion::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; use crosstermion::input::Event; use dua::{ - traverse::{BackgroundTraversal, EntryData, Traversal}, + traverse::{BackgroundTraversal, EntryData, Traversal, TreeIndex}, WalkResult, }; use std::path::PathBuf; @@ -43,10 +43,10 @@ impl AppState { { let props = MainWindowProps { current_path: tree_view.current_path(self.navigation().view_root), - entries_traversed: tree_view.traversal.entries_traversed, - total_bytes: tree_view.traversal.total_bytes, - start: tree_view.traversal.start, - elapsed: tree_view.traversal.elapsed, + entries_traversed: self.stats.entries_traversed, + total_bytes: self.stats.total_bytes, + start: self.stats.start, + elapsed: self.stats.elapsed, display, state: self, }; @@ -72,6 +72,15 @@ impl AppState { Ok(()) } + fn recompute_sizes_recursively( + &mut self, + traversal: &mut Traversal, + node_index: TreeIndex) + { + let mut tree_view = self.tree_view(traversal); + tree_view.recompute_sizes_recursively(node_index); + } + fn refresh_screen<B>( &mut self, window: &mut MainWindow, @@ -125,7 +134,7 @@ impl AppState { crossbeam::select! { recv(events) -> event => { let Ok(event) = event else { - return Ok(Some(WalkResult { num_errors: traversal.io_errors })); + return Ok(Some(WalkResult { num_errors: self.stats.io_errors })); }; let res = self.process_terminal_event( window, @@ -144,6 +153,8 @@ impl AppState { if let Some(is_finished) = active_traversal.integrate_traversal_event(traversal, event) { if is_finished { + let root_index = active_traversal.root_idx; + self.recompute_sizes_recursively(traversal, root_index); self.active_traversal = None; } self.update_state(traversal); @@ -153,7 +164,7 @@ impl AppState { } } else { let Ok(event) = events.recv() else { - return Ok(Some(WalkResult { num_errors: traversal.io_errors })); + return Ok(Some(WalkResult { num_errors: self.stats.io_errors })); }; let result = self.process_terminal_event(window, traversal, display, terminal, event)?; @@ -222,7 +233,7 @@ impl AppState { Char('?') if !glob_focussed => self.toggle_help_pane(window), Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) && !glob_focussed => { return Ok(Some(WalkResult { - num_errors: tree_view.traversal.io_errors, + num_errors: self.stats.io_errors, })) } Char('q') if !glob_focussed => { @@ -402,7 +413,7 @@ impl AppState { self.handle_glob_quit(tree_view, window); } else { return Some(Ok(WalkResult { - num_errors: tree_view.traversal.io_errors, + num_errors: self.stats.io_errors, })); } } diff --git a/src/interactive/app/state.rs b/src/interactive/app/state.rs index 5dcdbff..e242a71 100644 --- a/src/interactive/app/state.rs +++ b/src/interactive/app/state.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use dua::traverse::BackgroundTraversal; +use dua::traverse::{BackgroundTraversal, TraversalStats}; use dua::WalkOptions; use crate::interactive::widgets::Column; @@ -33,6 +33,7 @@ pub struct AppState { pub focussed: FocussedPane, pub received_events: bool, pub active_traversal: Option<BackgroundTraversal>, + pub stats: TraversalStats, pub walk_options: WalkOptions, } @@ -48,6 +49,7 @@ impl AppState { focussed: Default::default(), received_events: false, active_traversal: None, + stats: TraversalStats::default(), walk_options, } } diff --git a/src/interactive/app/terminal.rs b/src/interactive/app/terminal.rs index 6672188..8b62386 100644 --- a/src/interactive/app/terminal.rs +++ b/src/interactive/app/terminal.rs @@ -4,7 +4,7 @@ use anyhow::Result; use crossbeam::channel::Receiver; use crosstermion::input::Event; use dua::{ - traverse::{EntryData, Traversal, Tree}, + traverse::{EntryData, Traversal, Tree, TraversalStats}, ByteFormat, WalkOptions, WalkResult, }; use tui::prelude::Backend; @@ -17,6 +17,7 @@ use super::{sorted_entries, state::AppState, DisplayOptions}; /// State and methods representing the interactive disk usage analyser for the terminal pub struct TerminalApp { pub traversal: Traversal, + pub stats: TraversalStats, pub display: DisplayOptions, pub state: AppState, pub window: MainWindow, @@ -38,20 +39,8 @@ impl TerminalApp { let window = MainWindow::default(); let mut state = AppState::new(walk_options); - - let traversal = { - let mut tree = Tree::new(); - let root_index = tree.add_node(EntryData::default()); - Traversal { - tree, - root_index, - entries_traversed: 0, - start: std::time::Instant::now(), - elapsed: None, - io_errors: 0, - total_bytes: None, - } - }; + let traversal = Traversal::new(); + let stats = TraversalStats::default(); state.navigation_mut().view_root = traversal.root_index; state.entries = sorted_entries( @@ -66,6 +55,7 @@ impl TerminalApp { state, display, traversal, + stats, window, }; Ok(app) @@ -120,7 +110,7 @@ mod tests { return Ok(res); } } - Ok(WalkResult { num_errors: self.traversal.io_errors }) + Ok(WalkResult { num_errors: self.stats.io_errors }) } } } diff --git a/src/interactive/app/tree_view.rs b/src/interactive/app/tree_view.rs index 2126206..558c022 100644 --- a/src/interactive/app/tree_view.rs +++ b/src/interactive/app/tree_view.rs @@ -68,7 +68,8 @@ impl TreeView<'_> { continue; } self.tree_mut().remove_node(nx); - self.traversal.entries_traversed -= 1; + // TODO: don't need this right? + // self.traversal.entries_traversed -= 1; entries_deleted += 1; } entries_deleted @@ -96,10 +97,11 @@ impl TreeView<'_> { Some(parent) => index = parent, } } - self.traversal.total_bytes = self - .tree() - .node_weight(self.traversal.root_index) - .map(|w| w.size); + // TODO: don't need this right? + // self.traversal.total_bytes = self + // .tree() + // .node_weight(self.traversal.root_index) + // .map(|w| w.size); } } diff --git a/src/traverse.rs b/src/traverse.rs index b879698..e3a3cc7 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -58,7 +58,28 @@ pub struct Traversal { /// A tree representing the entire filestem traversal pub tree: Tree, /// The top-level node of the tree. - pub root_index: TreeIndex, + pub root_index: TreeIndex, +} + +impl Traversal { + pub fn new() -> Self { + let mut tree = Tree::new(); + let root_index = tree.add_node(EntryData::default()); + Self { + tree, + root_index, + } + } + + pub fn recompute_node_size(&self, node_index: TreeIndex) -> u128 { + self.tree + .neighbors_directed(node_index, Direction::Outgoing) + .map(|idx| get_size_or_panic(&self.tree, idx)) + .sum() + } +} + +pub struct TraversalStats { /// Amount of files or directories we have seen during the filesystem traversal pub entries_traversed: u64, /// The time at which the traversal started. @@ -71,12 +92,15 @@ pub struct Traversal { pub total_bytes: Option<u128>, } -impl Traversal { - pub fn recompute_node_size(&self, node_index: TreeIndex) -> u128 { - self.tree - .neighbors_directed(node_index, Direction::Outgoing) - .map(|idx| get_size_or_panic(&self.tree, idx)) - .sum() +impl Default for TraversalStats { + fn default() -> Self { + Self { + entries_traversed: 0, + start: std::time::Instant::now(), + elapsed: None, + io_errors: 0, + total_bytes: None, + } } } @@ -134,7 +158,8 @@ pub enum TraversalEvent { /// An in-progress traversal which exposes newly obtained entries pub struct BackgroundTraversal { walk_options: WalkOptions, - root_idx: TreeIndex, + pub root_idx: TreeIndex, + pub stats: TraversalStats, previous_node_idx: TreeIndex, parent_node_idx: TreeIndex, directory_info_per_depth_level: Vec<EntryInfo>, @@ -177,7 +202,6 @@ impl BackgroundTraversal { .iter_from_path(root_path.as_ref(), device_id, skip_root) .into_iter() { - log::info!("{:?}", entry); if entry_tx .send(TraversalEvent::Entry( entry, @@ -201,6 +225,7 @@ impl BackgroundTraversal { Ok(Self { walk_options: walk_options.clone(), root_idx, + stats: TraversalStats::default(), previous_node_idx: root_idx, parent_node_idx: root_idx, directory_info_per_depth_level: Vec::new(), @@ -222,12 +247,12 @@ impl BackgroundTraversal { /// * `None` - the event was written into the traversal, but there is nothing else to do pub fn integrate_traversal_event( &mut self, - t: &mut Traversal, + traversal: &mut Traversal, event: TraversalEvent, ) -> Option<bool> { match event { TraversalEvent::Entry(entry, root_path, device_id) => { - t.entries_traversed += 1; + self.stats.entries_traversed += 1; let mut data = EntryData::default(); match entry { Ok(mut entry) => { @@ -256,7 +281,7 @@ impl BackgroundTraversal { } else { file_size = size_on_disk(&entry.parent_path, &data.name, m) .unwrap_or_else(|_| { - t.io_errors += 1; + self.stats.io_errors += 1; data.metadata_io_error = true; 0 }) @@ -272,13 +297,13 @@ impl BackgroundTraversal { mtime = modified; } Err(_) => { - t.io_errors += 1; + self.stats.io_errors += 1; data.metadata_io_error = true; } } } Some(Err(_)) => { - t.io_errors += 1; + self.stats.io_errors += 1; data.metadata_io_error = true; } None => {} @@ -297,7 +322,7 @@ impl BackgroundTraversal { (n, p) if n < p => { for _ in n..p { set_entry_info_or_panic( - &mut t.tree, + &mut traversal.tree, self.parent_node_idx, self.current_directory_at_depth, ); @@ -308,7 +333,7 @@ impl BackgroundTraversal { self.current_directory_at_depth.add_count(&dir_info); self.parent_node_idx = - parent_or_panic(&mut t.tree, self.parent_node_idx); + parent_or_panic(&mut traversal.tree, self.parent_node_idx); } self.current_directory_at_depth.size += file_size; *self @@ -316,7 +341,7 @@ impl BackgroundTraversal { .entries_count .get_or_insert(0) += 1; set_entry_info_or_panic( - &mut t.tree, + &mut traversal.tree, self.parent_node_idx, self.current_directory_at_depth, ); @@ -332,20 +357,20 @@ impl BackgroundTraversal { data.mtime = mtime; data.size = file_size; - let entry_index = t.tree.add_node(data); + let entry_index = traversal.tree.add_node(data); - t.tree.add_edge(self.parent_node_idx, entry_index, ()); + traversal.tree.add_edge(self.parent_node_idx, entry_index, ()); self.previous_node_idx = entry_index; self.previous_depth = entry.depth; } Err(_) => { if self.previous_depth == 0 { data.name = (*root_path).clone(); - let entry_index = t.tree.add_node(data); - t.tree.add_edge(self.parent_node_idx, entry_index, ()); + let entry_index = traversal.tree.add_node(data); + traversal.tree.add_edge(self.parent_node_idx, entry_index, ()); } - t.io_errors += 1 + self.stats.io_errors += 1 } } @@ -354,35 +379,38 @@ impl BackgroundTraversal { } } TraversalEvent::Finished(io_errors) => { - t.io_errors += io_errors; + self.stats.io_errors += io_errors; self.throttle = None; self.directory_info_per_depth_level .push(self.current_directory_at_depth); self.current_directory_at_depth = EntryInfo::default(); + // TODO: this loop is broken for _ in 0..self.previous_depth { let dir_info = pop_or_panic(&mut self.directory_info_per_depth_level); self.current_directory_at_depth.size += dir_info.size; self.current_directory_at_depth.add_count(&dir_info); set_entry_info_or_panic( - &mut t.tree, + &mut traversal.tree, self.parent_node_idx, self.current_directory_at_depth, ); - self.parent_node_idx = parent_or_panic(&mut t.tree, self.parent_node_idx); + self.parent_node_idx = parent_or_panic(&mut traversal.tree, self.parent_node_idx); } - let root_size = t.recompute_node_size(self.root_idx); + // TODO: this is a hack because the loop above is broken + log::info!("directory_info_per_depth_level.size() = {}", self.directory_info_per_depth_level.len()); + let root_size = traversal.recompute_node_size(self.root_idx); set_entry_info_or_panic( - &mut t.tree, + &mut traversal.tree, self.root_idx, EntryInfo { size: root_size, - entries_count: (t.entries_traversed > 0).then_some(t.entries_traversed), + entries_count: (self.stats.entries_traversed > 0).then_some(self.stats.entries_traversed), }, ); - t.total_bytes = Some(root_size); - t.elapsed = Some(t.start.elapsed()); + self.stats.total_bytes = Some(root_size); + self.stats.elapsed = Some(self.stats.start.elapsed()); return Some(true); } |