backup/chunk_store: rework chunk iterator
We can now use iter::from_fn() which makes for a much nicer logic. The only thing better is going to be when we can use generators with `yield`. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
99168f43e6
commit
a3f3e91da2
@ -200,40 +200,68 @@ impl ChunkStore {
|
|||||||
self.name, self.chunk_dir, err),
|
self.name, self.chunk_dir, err),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut verbose = true;
|
let mut done = false;
|
||||||
|
let mut inner: Option<tools::fs::ReadDir> = None;
|
||||||
|
let mut at = 0;
|
||||||
|
let mut percentage = 0;
|
||||||
|
Ok(std::iter::from_fn(move || {
|
||||||
|
if done {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
Ok((0..0x10000).filter_map(move |index| {
|
loop {
|
||||||
let percentage = (index * 100) / 0x10000;
|
if let Some(ref mut inner) = inner {
|
||||||
let subdir: &str = &format!("{:04x}", index);
|
match inner.next() {
|
||||||
match tools::fs::read_subdir(base_handle.as_raw_fd(), subdir) {
|
Some(Ok(entry)) => {
|
||||||
Err(e) => {
|
// skip files if they're not a hash
|
||||||
if verbose {
|
let bytes = entry.file_name().to_bytes();
|
||||||
eprintln!("Error iterating through chunks: {}", e);
|
if bytes.len() != 64 {
|
||||||
verbose = false;
|
continue;
|
||||||
|
}
|
||||||
|
if !bytes.iter().all(u8::is_ascii_hexdigit) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return Some((Ok(entry), percentage));
|
||||||
|
}
|
||||||
|
Some(Err(err)) => {
|
||||||
|
// stop after first error
|
||||||
|
done = true;
|
||||||
|
// and pass the error through:
|
||||||
|
return Some((Err(err), percentage));
|
||||||
|
}
|
||||||
|
None => (), // open next directory
|
||||||
}
|
}
|
||||||
None
|
|
||||||
}
|
}
|
||||||
Ok(iter) => Some(iter.map(move |item| (item, percentage))),
|
|
||||||
}
|
inner = None;
|
||||||
})
|
|
||||||
.flatten()
|
if at == 0x10000 {
|
||||||
.filter(|(entry, _percentage)| {
|
done = true;
|
||||||
// Check that the file name is actually a hash! (64 hex digits)
|
return None;
|
||||||
let entry = match entry {
|
}
|
||||||
Err(_) => return true, // pass errors onwards
|
|
||||||
Ok(ref entry) => entry,
|
let subdir: &str = &format!("{:04x}", at);
|
||||||
};
|
percentage = (at * 100) / 0x10000;
|
||||||
let bytes = entry.file_name().to_bytes();
|
at += 1;
|
||||||
if bytes.len() != 64 {
|
match tools::fs::read_subdir(base_handle.as_raw_fd(), subdir) {
|
||||||
return false;
|
Ok(dir) => {
|
||||||
}
|
inner = Some(dir);
|
||||||
for b in bytes {
|
// start reading:
|
||||||
if !b.is_ascii_hexdigit() {
|
continue;
|
||||||
return false;
|
}
|
||||||
|
Err(ref err) if err.as_errno() == Some(nix::errno::Errno::ENOENT) => {
|
||||||
|
// non-existing directories are okay, just keep going:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
// other errors are fatal, so end our iteration
|
||||||
|
done = true;
|
||||||
|
// and pass the error through:
|
||||||
|
return Some((Err(err.into()), percentage));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
}).fuse())
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn oldest_writer(&self) -> Option<i64> {
|
pub fn oldest_writer(&self) -> Option<i64> {
|
||||||
|
Loading…
Reference in New Issue
Block a user