add IndexFile trait
We want to be able to iterate through digests of index files, but without always having to distinguish between dynamic and fixed types, so add a trait we can use as a trait object. Unfortunately the iterator needs to yield copies as iterators cannot yield values with life times when represented as trait objects (Box<dyn Iterator<Item = ?>>) Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
		@ -20,6 +20,9 @@ pub use chunker::*;
 | 
			
		||||
mod chunk_store;
 | 
			
		||||
pub use chunk_store::*;
 | 
			
		||||
 | 
			
		||||
mod index;
 | 
			
		||||
pub use index::*;
 | 
			
		||||
 | 
			
		||||
mod fixed_index;
 | 
			
		||||
pub use fixed_index::*;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
use failure::*;
 | 
			
		||||
 | 
			
		||||
use crate::tools;
 | 
			
		||||
use super::IndexFile;
 | 
			
		||||
use super::chunk_stat::*;
 | 
			
		||||
use super::chunk_store::*;
 | 
			
		||||
use super::chunker::*;
 | 
			
		||||
@ -196,6 +197,22 @@ impl DynamicIndexReader {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IndexFile for DynamicIndexReader {
 | 
			
		||||
    fn index_count(&self) -> usize {
 | 
			
		||||
        self.index_entries
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn index_digest(&self, pos: usize) -> Option<&[u8; 32]> {
 | 
			
		||||
        if pos >= self.index_entries {
 | 
			
		||||
            None
 | 
			
		||||
        } else {
 | 
			
		||||
            Some(unsafe {
 | 
			
		||||
                std::mem::transmute(self.chunk_digest(pos).as_ptr())
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct BufferedDynamicReader {
 | 
			
		||||
    index: DynamicIndexReader,
 | 
			
		||||
    archive_size: u64,
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
use failure::*;
 | 
			
		||||
 | 
			
		||||
use crate::tools;
 | 
			
		||||
use super::IndexFile;
 | 
			
		||||
use super::chunk_stat::*;
 | 
			
		||||
use super::chunk_store::*;
 | 
			
		||||
 | 
			
		||||
@ -132,14 +133,14 @@ impl FixedIndexReader {
 | 
			
		||||
 | 
			
		||||
        if self.index == std::ptr::null_mut() { bail!("detected closed index file."); }
 | 
			
		||||
 | 
			
		||||
        let index_count = (self.size + self.chunk_size - 1)/self.chunk_size;
 | 
			
		||||
        let index_count = self.index_count();
 | 
			
		||||
 | 
			
		||||
        status.used_bytes += index_count * self.chunk_size;
 | 
			
		||||
        status.used_chunks += index_count;
 | 
			
		||||
 | 
			
		||||
        for pos in 0..index_count {
 | 
			
		||||
 | 
			
		||||
            let digest = unsafe { std::slice::from_raw_parts_mut(self.index.add(pos*32), 32) };
 | 
			
		||||
            let digest = self.index_digest(pos).unwrap();
 | 
			
		||||
            if let Err(err) = self.store.touch_chunk(digest) {
 | 
			
		||||
                bail!("unable to access chunk {}, required by {:?} - {}",
 | 
			
		||||
                      tools::digest_to_hex(digest), self.filename, err);
 | 
			
		||||
@ -158,6 +159,20 @@ impl FixedIndexReader {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IndexFile for FixedIndexReader {
 | 
			
		||||
    fn index_count(&self) -> usize {
 | 
			
		||||
        (self.size + self.chunk_size - 1)/self.chunk_size
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn index_digest(&self, pos: usize) -> Option<&[u8; 32]> {
 | 
			
		||||
        if pos >= self.index_count() {
 | 
			
		||||
            None
 | 
			
		||||
        } else {
 | 
			
		||||
            Some(unsafe { std::mem::transmute(self.index.add(pos*32)) })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct FixedIndexWriter {
 | 
			
		||||
    store: Arc<ChunkStore>,
 | 
			
		||||
    filename: PathBuf,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										44
									
								
								src/backup/index.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/backup/index.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
pub trait IndexFile {
 | 
			
		||||
    fn index_count(&self) -> usize;
 | 
			
		||||
    fn index_digest(&self, pos: usize) -> Option<&[u8; 32]>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct IndexIterator {
 | 
			
		||||
    pos: usize,
 | 
			
		||||
    count: usize,
 | 
			
		||||
    reader: Box<dyn IndexFile + Send>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Iterator for IndexIterator {
 | 
			
		||||
    type Item = [u8; 32];
 | 
			
		||||
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        if self.pos == self.count {
 | 
			
		||||
            return None;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let digest = self.reader.index_digest(self.pos).unwrap();
 | 
			
		||||
        self.pos += 1;
 | 
			
		||||
        Some(*digest)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<Box<dyn IndexFile + Send>> for IndexIterator {
 | 
			
		||||
    fn from(file: Box<dyn IndexFile + Send>) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            pos: 0,
 | 
			
		||||
            count: file.index_count(),
 | 
			
		||||
            reader: file,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: IndexFile + Send + 'static> From<Box<T>> for IndexIterator {
 | 
			
		||||
    fn from(file: Box<T>) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            pos: 0,
 | 
			
		||||
            count: file.index_count(),
 | 
			
		||||
            reader: file,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user