Watch
0
0
Fork
You've already forked hyperhive
0

disk watch: a footprint walk that ran out of budget counts as unknown, not small

This commit is contained in:
damocles 2026-10-21 21:36:57 +02:00 • committed by mara
commit 8f8217100b

View file

@ -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);
}
}