Add backend draining

This commit is contained in:
Matthias Beyer 2017-06-18 13:41:43 +02:00
parent b572e7e8b9
commit c814171875
5 changed files with 109 additions and 0 deletions

View file

@ -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> {

View 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(())
}
} }

View file

@ -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;

View file

@ -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)
}
} }

View file

@ -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(())
}
} }