summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPiotr Wach <pwach@bloomberg.net>2024-01-13 21:44:42 +0000
committerPiotr Wach <pwach@bloomberg.net>2024-01-14 15:01:17 +0000
commit969e64bbde872d0598b1ebf6278f5d55e152f7b1 (patch)
tree01192ffbb4158c01b150df7740c9316906a02c18 /src
parent226cbb8b2d6388ddd7a7e48fdac1a4db2ee75474 (diff)
Moved traversal stats to separate type
Diffstat (limited to 'src')
-rw-r--r--src/interactive/app/eventloop.rs29
-rw-r--r--src/interactive/app/state.rs4
-rw-r--r--src/interactive/app/terminal.rs22
-rw-r--r--src/interactive/app/tree_view.rs12
-rw-r--r--src/traverse.rs88
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);
}