backup: add ChunkIterator
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
		@ -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 {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user