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:
parent
5be4065baf
commit
7bc1d72778
@ -20,6 +20,9 @@ pub use chunker::*;
|
|||||||
mod chunk_store;
|
mod chunk_store;
|
||||||
pub use chunk_store::*;
|
pub use chunk_store::*;
|
||||||
|
|
||||||
|
mod index;
|
||||||
|
pub use index::*;
|
||||||
|
|
||||||
mod fixed_index;
|
mod fixed_index;
|
||||||
pub use fixed_index::*;
|
pub use fixed_index::*;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use failure::*;
|
use failure::*;
|
||||||
|
|
||||||
use crate::tools;
|
use crate::tools;
|
||||||
|
use super::IndexFile;
|
||||||
use super::chunk_stat::*;
|
use super::chunk_stat::*;
|
||||||
use super::chunk_store::*;
|
use super::chunk_store::*;
|
||||||
use super::chunker::*;
|
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 {
|
pub struct BufferedDynamicReader {
|
||||||
index: DynamicIndexReader,
|
index: DynamicIndexReader,
|
||||||
archive_size: u64,
|
archive_size: u64,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use failure::*;
|
use failure::*;
|
||||||
|
|
||||||
use crate::tools;
|
use crate::tools;
|
||||||
|
use super::IndexFile;
|
||||||
use super::chunk_stat::*;
|
use super::chunk_stat::*;
|
||||||
use super::chunk_store::*;
|
use super::chunk_store::*;
|
||||||
|
|
||||||
@ -132,14 +133,14 @@ impl FixedIndexReader {
|
|||||||
|
|
||||||
if self.index == std::ptr::null_mut() { bail!("detected closed index file."); }
|
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_bytes += index_count * self.chunk_size;
|
||||||
status.used_chunks += index_count;
|
status.used_chunks += index_count;
|
||||||
|
|
||||||
for pos in 0..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) {
|
if let Err(err) = self.store.touch_chunk(digest) {
|
||||||
bail!("unable to access chunk {}, required by {:?} - {}",
|
bail!("unable to access chunk {}, required by {:?} - {}",
|
||||||
tools::digest_to_hex(digest), self.filename, err);
|
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 {
|
pub struct FixedIndexWriter {
|
||||||
store: Arc<ChunkStore>,
|
store: Arc<ChunkStore>,
|
||||||
filename: PathBuf,
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user