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