zvault/src/backups/metadata.rs

79 lines
2.8 KiB
Rust
Raw Normal View History

2017-07-21 09:21:59 +00:00
use prelude::*;
2017-03-21 10:28:11 +00:00
2018-03-10 15:35:40 +00:00
use std::path::Path;
use std::fs::File;
use std::io::{Read, Write};
2017-03-15 11:32:44 +00:00
2018-03-11 22:32:54 +00:00
use super::*;
2017-03-15 11:32:44 +00:00
2018-03-11 22:32:54 +00:00
impl BackupRepository {
2017-07-21 09:21:59 +00:00
pub fn create_inode<P: AsRef<Path>>(
&mut self,
path: P,
reference: Option<&Inode>,
) -> Result<Inode, RepositoryError> {
2017-03-15 11:32:44 +00:00
let mut inode = try!(Inode::get_from(path.as_ref()));
if inode.file_type == FileType::File && inode.size > 0 {
2017-03-20 21:24:53 +00:00
if let Some(reference) = reference {
2017-03-29 21:24:26 +00:00
if reference.is_same_meta_quick(&inode) {
2017-04-03 05:35:00 +00:00
inode.data = reference.data.clone();
2017-07-21 09:21:59 +00:00
return Ok(inode);
2017-03-20 21:24:53 +00:00
}
}
2017-03-16 08:42:30 +00:00
let mut file = try!(File::open(path));
2017-03-15 11:32:44 +00:00
if inode.size < 100 {
let mut data = Vec::with_capacity(inode.size as usize);
2017-03-16 08:42:30 +00:00
try!(file.read_to_end(&mut data));
2017-04-03 05:35:00 +00:00
inode.data = Some(FileData::Inline(data.into()));
2017-03-15 11:32:44 +00:00
} else {
2018-03-11 22:32:54 +00:00
let mut chunks = try!(self.repo.put_stream(BundleMode::Data, &mut file));
2017-03-16 08:42:30 +00:00
if chunks.len() < 10 {
2017-04-03 05:35:00 +00:00
inode.data = Some(FileData::ChunkedDirect(chunks));
2017-03-16 08:42:30 +00:00
} else {
2017-03-18 14:41:59 +00:00
let mut chunk_data = Vec::with_capacity(chunks.encoded_size());
chunks.write_to(&mut chunk_data).unwrap();
2018-03-11 22:32:54 +00:00
chunks = try!(self.repo.put_data(BundleMode::Meta, &chunk_data));
2017-04-03 05:35:00 +00:00
inode.data = Some(FileData::ChunkedIndirect(chunks));
2017-03-16 08:42:30 +00:00
}
2017-03-15 11:32:44 +00:00
}
}
2017-03-16 11:33:10 +00:00
Ok(inode)
}
2017-03-17 06:15:19 +00:00
#[inline]
2017-03-18 14:41:59 +00:00
pub fn put_inode(&mut self, inode: &Inode) -> Result<ChunkList, RepositoryError> {
2018-03-11 22:32:54 +00:00
self.repo.put_data(BundleMode::Meta, &try!(inode.encode()))
2017-03-15 11:32:44 +00:00
}
#[inline]
2017-03-16 08:42:30 +00:00
pub fn get_inode(&mut self, chunks: &[Chunk]) -> Result<Inode, RepositoryError> {
2017-03-22 08:19:16 +00:00
Ok(try!(Inode::decode(&try!(self.get_data(chunks)))))
2017-03-15 11:32:44 +00:00
}
2017-03-15 20:53:05 +00:00
2017-07-21 09:21:59 +00:00
pub fn save_inode_at<P: AsRef<Path>>(
&mut self,
inode: &Inode,
path: P,
) -> Result<(), RepositoryError> {
2017-03-15 20:53:05 +00:00
if let Some(mut file) = try!(inode.create_at(path.as_ref())) {
2017-04-03 05:35:00 +00:00
if let Some(ref contents) = inode.data {
2017-03-15 20:53:05 +00:00
match *contents {
2017-04-03 05:35:00 +00:00
FileData::Inline(ref data) => {
2017-04-27 11:35:48 +00:00
try!(file.write_all(data));
2017-07-21 09:21:59 +00:00
}
2017-04-03 05:35:00 +00:00
FileData::ChunkedDirect(ref chunks) => {
2018-03-11 22:32:54 +00:00
try!(self.repo.get_stream(chunks, &mut file));
2017-07-21 09:21:59 +00:00
}
2017-04-03 05:35:00 +00:00
FileData::ChunkedIndirect(ref chunks) => {
2017-03-16 08:42:30 +00:00
let chunk_data = try!(self.get_data(chunks));
2017-03-18 14:41:59 +00:00
let chunks = ChunkList::read_from(&chunk_data);
2018-03-11 22:32:54 +00:00
try!(self.repo.get_stream(&chunks, &mut file));
2017-03-15 20:53:05 +00:00
}
}
}
}
Ok(())
}
2017-03-15 11:32:44 +00:00
}