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::sync::Mutex;
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
|
||||||
use crate::tools;
|
use crate::tools;
|
||||||
|
use crate::tools::borrow::Tied;
|
||||||
|
|
||||||
pub struct GarbageCollectionStatus {
|
pub struct GarbageCollectionStatus {
|
||||||
pub used_bytes: usize,
|
pub used_bytes: usize,
|
||||||
|
@ -56,6 +57,83 @@ fn digest_to_prefix(digest: &[u8]) -> PathBuf {
|
||||||
path.into()
|
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 {
|
impl ChunkStore {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue