1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/// compute consolidated data for directories: modified date, size, and count.
/// A cache is used to avoid recomputing the same directories again and again.
/// On unix, hard links are checked to avoid counting twice an inode.
mod sum_computation;
use {
crate::task_sync::Dam,
std::{
collections::HashMap,
ops::AddAssign,
path::{Path, PathBuf},
sync::Mutex,
},
};
lazy_static! {
static ref SUM_CACHE_MUTEX: Mutex<HashMap<PathBuf, FileSum>> = Mutex::new(HashMap::new());
}
pub fn clear_cache() {
let mut sum_cache = SUM_CACHE_MUTEX.lock().unwrap();
sum_cache.clear();
}
/// Reduction of counts, dates and sizes on a file or directory
#[derive(Debug, Copy, Clone)]
pub struct FileSum {
real_size: u64, // bytes, the space it takes on disk
count: usize, // number of files
modified: u32, // seconds from Epoch to last modification, or 0 if there was an error
sparse: bool, // only for non directories: tells whether the file is sparse
}
impl FileSum {
pub fn new(
real_size: u64,
sparse: bool,
count: usize,
modified: u32,
) -> Self {
Self { real_size, sparse, count, modified }
}
pub fn zero() -> Self {
Self::new(0, false, 0, 0)
}
pub fn incr(&mut self) {
self.count += 1;
}
/// return the sum of the given file, which is assumed
/// to be a normal file (ie not a directory)
pub fn from_file(path: &Path) -> Self {
sum_computation::compute_file_sum(path)
}
/// Return the sum of the directory, either by computing it of by
/// fetching it from cache.
/// If the lifetime expires before complete computation, None is returned.
pub fn from_dir(path: &Path, dam: &Dam) -> Option<Self> {
let mut sum_cache = SUM_CACHE_MUTEX.lock().unwrap();
match sum_cache.get(path) {
Some(sum) => Some(*sum),
None => {
let sum = time!(
Debug,
"sum computation",
path,
sum_computation::compute_dir_sum(path, &mut sum_cache, dam),
);
if let Some(sum) = sum {
sum_cache.insert(PathBuf::from(path), sum);
}
sum
}
}
}
pub fn part_of_size(self, total: Self) -> f32 {
if total.real_size == 0 {
0.0
} else {
self.real_size as f32 / total.real_size as f32
}
}
/// return the number of files (normally at least 1)
pub fn to_count(self) -> usize {
self.count
}
/// return the number of seconds from Epoch to last modification,
/// or 0 if the computation failed
pub fn to_seconds(self) -> u32 {
self.modified
}
/// return the size in bytes
pub fn to_size(self) -> u64 {
self.real_size
}
pub fn to_valid_seconds(self) -> Option<i64> {
if self.modified != 0 {
Some(self.modified as i64)
} else {
None
}
}
/// tell whether the file has holes (in which case the size displayed by
/// other tools may be greater than the "real" one returned by broot).
/// Not computed (return false) on windows or for directories.
pub fn is_sparse(self) -> bool {
self.sparse
}
}
impl AddAssign for FileSum {
#[allow(clippy::suspicious_op_assign_impl)]
fn add_assign(&mut self, other: Self) {
*self = Self::new(
self.real_size + other.real_size,
self.sparse | other.sparse,
self.count + other.count,
self.modified.max(other.modified),
);
}
}
|