diff --git a/src/backup.rs b/src/backup.rs index 394091f6..e8947917 100644 --- a/src/backup.rs +++ b/src/backup.rs @@ -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::*; diff --git a/src/backup/dynamic_index.rs b/src/backup/dynamic_index.rs index 3a9b8beb..01e9d16f 100644 --- a/src/backup/dynamic_index.rs +++ b/src/backup/dynamic_index.rs @@ -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, diff --git a/src/backup/fixed_index.rs b/src/backup/fixed_index.rs index d41601db..bb3197ba 100644 --- a/src/backup/fixed_index.rs +++ b/src/backup/fixed_index.rs @@ -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, filename: PathBuf, diff --git a/src/backup/index.rs b/src/backup/index.rs new file mode 100644 index 00000000..1cad4e69 --- /dev/null +++ b/src/backup/index.rs @@ -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, +} + +impl Iterator for IndexIterator { + type Item = [u8; 32]; + + fn next(&mut self) -> Option { + if self.pos == self.count { + return None; + } + + let digest = self.reader.index_digest(self.pos).unwrap(); + self.pos += 1; + Some(*digest) + } +} + +impl From> for IndexIterator { + fn from(file: Box) -> Self { + Self { + pos: 0, + count: file.index_count(), + reader: file, + } + } +} + +impl From> for IndexIterator { + fn from(file: Box) -> Self { + Self { + pos: 0, + count: file.index_count(), + reader: file, + } + } +}