backup: add ChunkIterator
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
6ed25cbe3a
commit
4070096c6a
|
@ -7,9 +7,10 @@ use openssl::sha;
|
|||
use std::sync::Mutex;
|
||||
|
||||
use std::fs::File;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
|
||||
use crate::tools;
|
||||
use crate::tools::borrow::Tied;
|
||||
|
||||
pub struct GarbageCollectionStatus {
|
||||
pub used_bytes: usize,
|
||||
|
@ -56,6 +57,83 @@ fn digest_to_prefix(digest: &[u8]) -> PathBuf {
|
|||
path.into()
|
||||
}
|
||||
|
||||
// This is one thing which would actually get nicer with futures & tokio-fs...
|
||||
pub struct ChunkIterator {
|
||||
base_dir: nix::dir::Dir,
|
||||
index: usize,
|
||||
subdir: Option<
|
||||
Tied<nix::dir::Dir, Iterator<Item = nix::Result<nix::dir::Entry>>>
|
||||
>,
|
||||
subdir_fd: RawFd,
|
||||
}
|
||||
|
||||
impl ChunkIterator {
|
||||
fn new(base_dir: nix::dir::Dir) -> Self {
|
||||
ChunkIterator {
|
||||
base_dir,
|
||||
index: 0,
|
||||
subdir: None,
|
||||
subdir_fd: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn next_subdir(&mut self) -> Result<bool, Error> {
|
||||
if self.index == 0x10000 {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let l1name = PathBuf::from(format!("{:04x}", self.index));
|
||||
self.index += 1;
|
||||
|
||||
use nix::dir::{Dir, Entry};
|
||||
use nix::fcntl::OFlag;
|
||||
use nix::sys::stat::Mode;
|
||||
match Dir::openat(self.base_dir.as_raw_fd(), &l1name, OFlag::O_RDONLY, Mode::empty()) {
|
||||
Ok(dir) => {
|
||||
self.subdir_fd = dir.as_raw_fd();
|
||||
self.subdir = Some(Tied::new(dir, |dir| {
|
||||
Box::new(unsafe { (*dir).iter() })
|
||||
as Box<Iterator<Item = nix::Result<Entry>>>
|
||||
}));
|
||||
return Ok(true);
|
||||
}
|
||||
Err(err) => {
|
||||
self.index = 0x10000;
|
||||
bail!("unable to open chunk dir {:?}: {}", l1name, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ChunkIterator {
|
||||
type Item = Result<(RawFd, nix::dir::Entry), Error>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
match self.subdir {
|
||||
None => {
|
||||
match self.next_subdir() {
|
||||
Ok(true) => continue, // Enter the Some case
|
||||
Ok(false) => return None,
|
||||
Err(e) => return Some(Err(e)),
|
||||
}
|
||||
}
|
||||
Some(ref mut dir) => {
|
||||
let dir = dir.as_mut();
|
||||
match dir.next() {
|
||||
Some(Ok(entry)) => return Some(Ok((self.subdir_fd, entry))),
|
||||
Some(Err(e)) => return Some(Err(e.into())),
|
||||
None => {
|
||||
// Go to the next directory
|
||||
self.subdir = None;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ChunkStore {
|
||||
|
||||
|
|
Loading…
Reference in New Issue