disk watch: a footprint walk that ran out of budget counts as unknown, not small
This commit is contained in:
parent
041779d910
commit
8f8217100b
1 changed files with 32 additions and 6 deletions
|
|
@ -74,7 +74,8 @@ const REPORT_DEPTH: usize = 4;
|
|||
/// depth on a pathological tree.
|
||||
const MAX_DEPTH: usize = 24;
|
||||
/// Directory entries the scan will look at before giving up. Bounds the
|
||||
/// worst case on a huge tree; a truncated scan just names fewer dirs.
|
||||
/// worst case on a huge tree. A truncated scan names fewer dirs, and its
|
||||
/// footprint total is treated as unknown rather than small.
|
||||
const SCAN_BUDGET: u64 = 400_000;
|
||||
|
||||
/// Background loop: periodically reconcile the disk todo. Detached task —
|
||||
|
|
@ -217,17 +218,27 @@ fn roots() -> Vec<PathBuf> {
|
|||
/// walk trades a little redundant `read_dir` work for keeping this and
|
||||
/// [`big_dirs`] as two small, independently obvious functions instead of
|
||||
/// one that returns a tuple nobody asked for.
|
||||
///
|
||||
/// A walk that runs out of its entry budget has only counted part of the
|
||||
/// tree, so its sum is a lower bound. That is reported as `u64::MAX`
|
||||
/// ("at least the floor") so a truncated scan can make the todo fire but
|
||||
/// never silence it.
|
||||
fn agent_footprint_bytes() -> u64 {
|
||||
let mut budget = SCAN_BUDGET;
|
||||
footprint_within(&roots(), SCAN_BUDGET)
|
||||
}
|
||||
|
||||
/// [`agent_footprint_bytes`] over the given roots with an explicit entry
|
||||
/// budget, so the truncation rule is testable without a huge tree.
|
||||
fn footprint_within(roots: &[PathBuf], mut budget: u64) -> u64 {
|
||||
let mut discard = Vec::new();
|
||||
let mut total: u64 = 0;
|
||||
for root in roots() {
|
||||
let Ok(md) = std::fs::metadata(&root) else {
|
||||
for root in roots {
|
||||
let Ok(md) = std::fs::metadata(root) else {
|
||||
continue;
|
||||
};
|
||||
total = total.saturating_add(dir_bytes(&root, md.dev(), 0, &mut budget, &mut discard));
|
||||
total = total.saturating_add(dir_bytes(root, md.dev(), 0, &mut budget, &mut discard));
|
||||
}
|
||||
total
|
||||
if budget == 0 { u64::MAX } else { total }
|
||||
}
|
||||
|
||||
/// Walk the agent's own tree and return the directories worth naming:
|
||||
|
|
@ -460,4 +471,19 @@ mod tests {
|
|||
reconcile(&todos, &wake, None);
|
||||
assert!(todos.list(Some(SUBSYSTEM)).expect("list").is_empty());
|
||||
}
|
||||
|
||||
/// A walk that fits its budget reports the real byte total; one that
|
||||
/// runs out reports "unknown, at least the floor", so a big tree that
|
||||
/// is only partly counted cannot fall under the footprint floor.
|
||||
#[test]
|
||||
fn a_truncated_footprint_walk_is_not_taken_for_a_small_one() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
for name in ["a", "b", "c", "d"] {
|
||||
std::fs::write(dir.path().join(name), [0u8; 10]).expect("write");
|
||||
}
|
||||
let roots = [dir.path().to_path_buf()];
|
||||
|
||||
assert_eq!(footprint_within(&roots, 100), 40);
|
||||
assert_eq!(footprint_within(&roots, 2), u64::MAX);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue