Add implementation of Test Lazyfile

This commit is contained in:
Marcel Müller 2016-07-22 13:39:29 +02:00
parent bc1af19750
commit 74dcd1f141
No known key found for this signature in database
GPG key ID: 84BD3634786D56CF
2 changed files with 52 additions and 47 deletions

View file

@ -6,13 +6,21 @@ mod fs {
use std::io::Cursor; use std::io::Cursor;
use std::path::PathBuf; use std::path::PathBuf;
/// `LazyFile` type use std::collections::HashMap;
use std::sync::Mutex;
lazy_static! {
static ref MAP: Mutex<HashMap<PathBuf, Cursor<Vec<u8>>>> = {
Mutex::new(HashMap::new())
};
}
/// `LazyFile` type, this is the Test version!
/// ///
/// A lazy file is either absent, but a path to it is available, or it is present. /// A lazy file is either absent, but a path to it is available, or it is present.
#[derive(Debug)] #[derive(Debug)]
pub enum LazyFile { pub enum LazyFile {
Absent(PathBuf), Absent(PathBuf),
File(Cursor<Vec<u8>>)
} }
impl LazyFile { impl LazyFile {
@ -20,35 +28,31 @@ mod fs {
/** /**
* Get the mutable file behind a LazyFile object * Get the mutable file behind a LazyFile object
*/ */
pub fn get_file_mut(&mut self) -> Result<&mut Cursor<Vec<u8>>, SE> { pub fn get_file_content(&mut self) -> Result<Cursor<Vec<u8>>, SE> {
debug!("Getting lazy file: {:?}", self); debug!("Getting lazy file: {:?}", self);
let file = match *self { match *self {
LazyFile::File(ref mut f) => return { LazyFile::Absent(ref f) => {
Ok(f) let map = MAP.lock().unwrap();
return Ok(map.get(f).unwrap().clone());
}, },
LazyFile::Absent(ref p) => unreachable!(),
}; };
*self = LazyFile::File(file);
if let LazyFile::File(ref mut f) = *self {
return Ok(f);
}
unreachable!()
} }
/** pub fn write_file_content(&mut self, buf: &[u8]) -> Result<(), SE> {
* Create a file out of this LazyFile object match *self {
*/ LazyFile::Absent(ref f) => {
pub fn create_file(&mut self) -> Result<&mut Cursor<Vec<u8>>, SE> { let mut map = MAP.lock().unwrap();
debug!("Creating lazy file: {:?}", self); if let Some(ref mut cur) = map.get_mut(f) {
let file = match *self { let mut vec = cur.get_mut();
LazyFile::File(ref mut f) => return Ok(f), vec.clear();
LazyFile::Absent(ref p) => unreachable!(), vec.extend_from_slice(buf);
return Ok(());
}
let vec = Vec::from(buf);
map.insert(f.clone(), Cursor::new(vec));
return Ok(());
},
}; };
*self = LazyFile::File(file);
if let LazyFile::File(ref mut f) = *self {
return Ok(f);
}
unreachable!()
} }
} }
} }
@ -56,7 +60,7 @@ mod fs {
#[cfg(not(test))] #[cfg(not(test))]
mod fs { mod fs {
use error::{MapErrInto, StoreError as SE, StoreErrorKind as SEK}; use error::{MapErrInto, StoreError as SE, StoreErrorKind as SEK};
use std::io::{Seek, SeekFrom}; use std::io::{Seek, SeekFrom, Read};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::fs::{File, OpenOptions, create_dir_all}; use std::fs::{File, OpenOptions, create_dir_all};
@ -86,17 +90,17 @@ mod fs {
impl LazyFile { impl LazyFile {
/** /**
* Get the mutable file behind a LazyFile object * Get the content behind this file
*/ */
pub fn get_file_mut(&mut self) -> Result<&mut File, SE> { pub fn get_file_content(&mut self) -> Result<&mut Read, SE> {
debug!("Getting lazy file: {:?}", self); debug!("Getting lazy file: {:?}", self);
let file = match *self { let file = match *self {
LazyFile::File(ref mut f) => return { LazyFile::File(ref mut f) => return {
// We seek to the beginning of the file since we expect each // We seek to the beginning of the file since we expect each
// access to the file to be in a different context // access to the file to be in a different context
f.seek(SeekFrom::Start(0)) try!(f.seek(SeekFrom::Start(0))
.map_err_into(SEK::FileNotCreated) .map_err_into(SEK::FileNotSeeked));
.map(|_| f) Ok(f)
}, },
LazyFile::Absent(ref p) => try!(open_file(p).map_err_into(SEK::FileNotFound)), LazyFile::Absent(ref p) => try!(open_file(p).map_err_into(SEK::FileNotFound)),
}; };
@ -108,23 +112,25 @@ mod fs {
} }
/** /**
* Create a file out of this LazyFile object * Write the content of this file
*/ */
pub fn create_file(&mut self) -> Result<&mut File, SE> { pub fn write_file_content(&mut self, buf: &[u8]) -> Result<(), SE> {
debug!("Creating lazy file: {:?}", self); use std::io::Write;
let file = match *self { let file = match *self {
LazyFile::File(ref mut f) => { LazyFile::File(ref mut f) => return {
try!(f.set_len(0).map_err_into(SEK::FileError)); // We seek to the beginning of the file since we expect each
return Ok(f) // access to the file to be in a different context
try!(f.seek(SeekFrom::Start(0))
.map_err_into(SEK::FileNotCreated));
f.write_all(buf).map_err_into(SEK::FileNotWritten)
}, },
LazyFile::Absent(ref p) => try!(create_file(p).map_err_into(SEK::FileNotFound)), LazyFile::Absent(ref p) => try!(create_file(p).map_err_into(SEK::FileNotCreated)),
}; };
*self = LazyFile::File(file); *self = LazyFile::File(file);
if let LazyFile::File(ref mut f) = *self { if let LazyFile::File(ref mut f) = *self {
try!(f.set_len(0).map_err_into(SEK::FileError)); return f.write_all(buf).map_err_into(SEK::FileNotWritten);
return Ok(f);
} }
unreachable!() unreachable!();
} }
} }
} }

View file

@ -129,7 +129,7 @@ impl StoreEntry {
fn get_entry(&mut self) -> Result<Entry> { fn get_entry(&mut self) -> Result<Entry> {
if !self.is_borrowed() { if !self.is_borrowed() {
let file = self.file.get_file_mut(); let file = self.file.get_file_content();
if let Err(err) = file { if let Err(err) = file {
if err.err_type() == SEK::FileNotFound { if err.err_type() == SEK::FileNotFound {
Ok(Entry::new(self.id.clone())) Ok(Entry::new(self.id.clone()))
@ -138,7 +138,7 @@ impl StoreEntry {
} }
} else { } else {
// TODO: // TODO:
let entry = Entry::from_reader(self.id.clone(), file.unwrap()); let entry = Entry::from_reader(self.id.clone(), &mut file.unwrap());
entry entry
} }
} else { } else {
@ -148,11 +148,10 @@ impl StoreEntry {
fn write_entry(&mut self, entry: &Entry) -> Result<()> { fn write_entry(&mut self, entry: &Entry) -> Result<()> {
if self.is_borrowed() { if self.is_borrowed() {
use std::io::Write;
let file = try!(self.file.create_file());
assert_eq!(self.id, entry.location); assert_eq!(self.id, entry.location);
file.write_all(entry.to_str().as_bytes()).map_err_into(SEK::FileError) self.file.write_file_content(entry.to_str().as_bytes())
.map_err_into(SEK::FileError)
.map(|_| ())
} else { } else {
Ok(()) Ok(())
} }