Add backend draining
This commit is contained in:
parent
b572e7e8b9
commit
c814171875
5 changed files with 109 additions and 0 deletions
|
@ -25,6 +25,7 @@ use error::{MapErrInto, StoreError as SE, StoreErrorKind as SEK};
|
||||||
|
|
||||||
use super::FileAbstraction;
|
use super::FileAbstraction;
|
||||||
use super::FileAbstractionInstance;
|
use super::FileAbstractionInstance;
|
||||||
|
use super::Drain;
|
||||||
use store::Entry;
|
use store::Entry;
|
||||||
use storeid::StoreId;
|
use storeid::StoreId;
|
||||||
|
|
||||||
|
@ -131,6 +132,20 @@ impl FileAbstraction for FSFileAbstraction {
|
||||||
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
|
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
|
||||||
Box::new(FSFileAbstractionInstance::Absent(p))
|
Box::new(FSFileAbstractionInstance::Absent(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// We return nothing from the FS here.
|
||||||
|
fn drain(&self) -> Result<Drain, SE> {
|
||||||
|
Ok(Drain::empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FileAbstraction::fill implementation that consumes the Drain and writes everything to the
|
||||||
|
/// filesystem
|
||||||
|
fn fill(&mut self, mut d: Drain) -> Result<(), SE> {
|
||||||
|
d.iter()
|
||||||
|
.fold(Ok(()), |acc, (path, element)| {
|
||||||
|
acc.and_then(|_| self.new_instance(path).write_file_content(&element))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
|
fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
|
||||||
|
|
|
@ -24,11 +24,13 @@ use std::collections::HashMap;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
use libimagerror::into::IntoError;
|
use libimagerror::into::IntoError;
|
||||||
|
|
||||||
use super::FileAbstraction;
|
use super::FileAbstraction;
|
||||||
use super::FileAbstractionInstance;
|
use super::FileAbstractionInstance;
|
||||||
|
use super::Drain;
|
||||||
use store::Entry;
|
use store::Entry;
|
||||||
use storeid::StoreId;
|
use storeid::StoreId;
|
||||||
|
|
||||||
|
@ -104,6 +106,13 @@ impl InMemoryFileAbstraction {
|
||||||
&self.virtual_filesystem
|
&self.virtual_filesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn backend_cloned<'a>(&'a self) -> Result<HashMap<PathBuf, Entry>, SE> {
|
||||||
|
self.virtual_filesystem
|
||||||
|
.lock()
|
||||||
|
.map_err(|_| SEK::LockError.into_error())
|
||||||
|
.map(|mtx| mtx.deref().borrow().clone())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileAbstraction for InMemoryFileAbstraction {
|
impl FileAbstraction for InMemoryFileAbstraction {
|
||||||
|
@ -148,5 +157,22 @@ impl FileAbstraction for InMemoryFileAbstraction {
|
||||||
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
|
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
|
||||||
Box::new(InMemoryFileAbstractionInstance::new(self.backend().clone(), p))
|
Box::new(InMemoryFileAbstractionInstance::new(self.backend().clone(), p))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn drain(&self) -> Result<Drain, SE> {
|
||||||
|
self.backend_cloned().map(Drain::new)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill<'a>(&'a mut self, mut d: Drain) -> Result<(), SE> {
|
||||||
|
debug!("Draining into : {:?}", self);
|
||||||
|
let mut mtx = try!(self.backend().lock().map_err(|_| SEK::LockError.into_error()));
|
||||||
|
let mut backend = mtx.get_mut();
|
||||||
|
|
||||||
|
for (path, element) in d.iter() {
|
||||||
|
debug!("Drain into {:?}: {:?}", self, path);
|
||||||
|
backend.insert(path, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use error::StoreError as SE;
|
use error::StoreError as SE;
|
||||||
use store::Entry;
|
use store::Entry;
|
||||||
|
@ -41,6 +42,9 @@ pub trait FileAbstraction : Debug {
|
||||||
fn create_dir_all(&self, _: &PathBuf) -> Result<(), SE>;
|
fn create_dir_all(&self, _: &PathBuf) -> Result<(), SE>;
|
||||||
|
|
||||||
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance>;
|
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance>;
|
||||||
|
|
||||||
|
fn drain(&self) -> Result<Drain, SE>;
|
||||||
|
fn fill<'a>(&'a mut self, d: Drain) -> Result<(), SE>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An abstraction trait over actions on files
|
/// An abstraction trait over actions on files
|
||||||
|
@ -54,6 +58,34 @@ pub trait FileAbstractionInstance : Debug {
|
||||||
fn write_file_content(&mut self, buf: &Entry) -> Result<(), SE>;
|
fn write_file_content(&mut self, buf: &Entry) -> Result<(), SE>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Drain(HashMap<PathBuf, Entry>);
|
||||||
|
|
||||||
|
impl Drain {
|
||||||
|
|
||||||
|
pub fn new(hm: HashMap<PathBuf, Entry>) -> Drain {
|
||||||
|
Drain(hm)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn empty() -> Drain {
|
||||||
|
Drain::new(HashMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter<'a>(&'a mut self) -> DrainIter<'a> {
|
||||||
|
DrainIter(self.0.drain())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DrainIter<'a>(::std::collections::hash_map::Drain<'a, PathBuf, Entry>);
|
||||||
|
|
||||||
|
impl<'a> Iterator for DrainIter<'a> {
|
||||||
|
type Item = (PathBuf, Entry);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.0.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
|
@ -35,6 +35,7 @@ use error::StoreErrorKind as SEK;
|
||||||
use error::StoreError as SE;
|
use error::StoreError as SE;
|
||||||
use super::FileAbstraction;
|
use super::FileAbstraction;
|
||||||
use super::FileAbstractionInstance;
|
use super::FileAbstractionInstance;
|
||||||
|
use super::Drain;
|
||||||
use super::InMemoryFileAbstraction;
|
use super::InMemoryFileAbstraction;
|
||||||
use store::Entry;
|
use store::Entry;
|
||||||
|
|
||||||
|
@ -114,5 +115,13 @@ impl<W: Write, M: Mapper> FileAbstraction for StdIoFileAbstraction<W, M> {
|
||||||
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
|
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
|
||||||
self.0.new_instance(p)
|
self.0.new_instance(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn drain(&self) -> Result<Drain, SE> {
|
||||||
|
self.0.drain()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill(&mut self, d: Drain) -> Result<(), SE> {
|
||||||
|
self.0.fill(d)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
use libimagerror::into::IntoError;
|
use libimagerror::into::IntoError;
|
||||||
use libimagerror::trace::*;
|
use libimagerror::trace::*;
|
||||||
|
@ -37,6 +38,7 @@ use error::StoreErrorKind as SEK;
|
||||||
use error::StoreError as SE;
|
use error::StoreError as SE;
|
||||||
use super::FileAbstraction;
|
use super::FileAbstraction;
|
||||||
use super::FileAbstractionInstance;
|
use super::FileAbstractionInstance;
|
||||||
|
use super::Drain;
|
||||||
use super::InMemoryFileAbstraction;
|
use super::InMemoryFileAbstraction;
|
||||||
use store::Entry;
|
use store::Entry;
|
||||||
|
|
||||||
|
@ -68,6 +70,14 @@ impl<W, M> StdoutFileAbstraction<W, M>
|
||||||
self.mem.backend()
|
self.mem.backend()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn backend_cloned(&self) -> Result<HashMap<PathBuf, Entry>, SE> {
|
||||||
|
self.mem
|
||||||
|
.backend()
|
||||||
|
.lock()
|
||||||
|
.map_err(|_| SEK::LockError.into_error())
|
||||||
|
.map(|mtx| mtx.deref().borrow().clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mapper(&self) -> &M {
|
pub fn mapper(&self) -> &M {
|
||||||
&self.mapper
|
&self.mapper
|
||||||
}
|
}
|
||||||
|
@ -125,6 +135,23 @@ impl<W: Write, M: Mapper> FileAbstraction for StdoutFileAbstraction<W, M> {
|
||||||
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
|
fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
|
||||||
self.mem.new_instance(p)
|
self.mem.new_instance(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn drain(&self) -> Result<Drain, SE> {
|
||||||
|
self.backend_cloned().map(Drain::new)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill(&mut self, mut d: Drain) -> Result<(), SE> {
|
||||||
|
debug!("Draining into : {:?}", self);
|
||||||
|
let mut mtx = try!(self.backend().lock().map_err(|_| SEK::IoError.into_error()));
|
||||||
|
let mut backend = mtx.get_mut();
|
||||||
|
|
||||||
|
for (path, element) in d.iter() {
|
||||||
|
debug!("Drain into {:?}: {:?}", self, path);
|
||||||
|
backend.insert(path, element);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue