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),
|
||||
};
|
||||
|
||||
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| {
|
||||
let percentage = (index * 100) / 0x10000;
|
||||
let subdir: &str = &format!("{:04x}", index);
|
||||
match tools::fs::read_subdir(base_handle.as_raw_fd(), subdir) {
|
||||
Err(e) => {
|
||||
if verbose {
|
||||
eprintln!("Error iterating through chunks: {}", e);
|
||||
verbose = false;
|
||||
}
|
||||
None
|
||||
}
|
||||
Ok(iter) => Some(iter.map(move |item| (item, percentage))),
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.filter(|(entry, _percentage)| {
|
||||
// Check that the file name is actually a hash! (64 hex digits)
|
||||
let entry = match entry {
|
||||
Err(_) => return true, // pass errors onwards
|
||||
Ok(ref entry) => entry,
|
||||
};
|
||||
loop {
|
||||
if let Some(ref mut inner) = inner {
|
||||
match inner.next() {
|
||||
Some(Ok(entry)) => {
|
||||
// skip files if they're not a hash
|
||||
let bytes = entry.file_name().to_bytes();
|
||||
if bytes.len() != 64 {
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
for b in bytes {
|
||||
if !b.is_ascii_hexdigit() {
|
||||
return false;
|
||||
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
|
||||
}
|
||||
}
|
||||
true
|
||||
}))
|
||||
|
||||
inner = None;
|
||||
|
||||
if at == 0x10000 {
|
||||
done = true;
|
||||
return None;
|
||||
}
|
||||
|
||||
let subdir: &str = &format!("{:04x}", at);
|
||||
percentage = (at * 100) / 0x10000;
|
||||
at += 1;
|
||||
match tools::fs::read_subdir(base_handle.as_raw_fd(), subdir) {
|
||||
Ok(dir) => {
|
||||
inner = Some(dir);
|
||||
// start reading:
|
||||
continue;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}).fuse())
|
||||
}
|
||||
|
||||
pub fn oldest_writer(&self) -> Option<i64> {
|
||||
|
Loading…
Reference in New Issue
Block a user