From c81417187531469701050c4c123fc60ea5d9440a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 18 Jun 2017 13:41:43 +0200 Subject: [PATCH] Add backend draining --- libimagstore/src/file_abstraction/fs.rs | 15 +++++++++ libimagstore/src/file_abstraction/inmemory.rs | 26 +++++++++++++++ libimagstore/src/file_abstraction/mod.rs | 32 +++++++++++++++++++ .../src/file_abstraction/stdio/mod.rs | 9 ++++++ .../src/file_abstraction/stdio/out.rs | 27 ++++++++++++++++ 5 files changed, 109 insertions(+) diff --git a/libimagstore/src/file_abstraction/fs.rs b/libimagstore/src/file_abstraction/fs.rs index b8770f1b..ba15be5e 100644 --- a/libimagstore/src/file_abstraction/fs.rs +++ b/libimagstore/src/file_abstraction/fs.rs @@ -25,6 +25,7 @@ use error::{MapErrInto, StoreError as SE, StoreErrorKind as SEK}; use super::FileAbstraction; use super::FileAbstractionInstance; +use super::Drain; use store::Entry; use storeid::StoreId; @@ -131,6 +132,20 @@ impl FileAbstraction for FSFileAbstraction { fn new_instance(&self, p: PathBuf) -> Box { Box::new(FSFileAbstractionInstance::Absent(p)) } + + /// We return nothing from the FS here. + fn drain(&self) -> Result { + 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>(p: A) -> ::std::io::Result { diff --git a/libimagstore/src/file_abstraction/inmemory.rs b/libimagstore/src/file_abstraction/inmemory.rs index aadeb01e..fef1bff0 100644 --- a/libimagstore/src/file_abstraction/inmemory.rs +++ b/libimagstore/src/file_abstraction/inmemory.rs @@ -24,11 +24,13 @@ use std::collections::HashMap; use std::sync::Mutex; use std::cell::RefCell; use std::sync::Arc; +use std::ops::Deref; use libimagerror::into::IntoError; use super::FileAbstraction; use super::FileAbstractionInstance; +use super::Drain; use store::Entry; use storeid::StoreId; @@ -104,6 +106,13 @@ impl InMemoryFileAbstraction { &self.virtual_filesystem } + fn backend_cloned<'a>(&'a self) -> Result, SE> { + self.virtual_filesystem + .lock() + .map_err(|_| SEK::LockError.into_error()) + .map(|mtx| mtx.deref().borrow().clone()) + } + } impl FileAbstraction for InMemoryFileAbstraction { @@ -148,5 +157,22 @@ impl FileAbstraction for InMemoryFileAbstraction { fn new_instance(&self, p: PathBuf) -> Box { Box::new(InMemoryFileAbstractionInstance::new(self.backend().clone(), p)) } + + fn drain(&self) -> Result { + 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(()) + } } diff --git a/libimagstore/src/file_abstraction/mod.rs b/libimagstore/src/file_abstraction/mod.rs index 9fb30f89..332f2503 100644 --- a/libimagstore/src/file_abstraction/mod.rs +++ b/libimagstore/src/file_abstraction/mod.rs @@ -19,6 +19,7 @@ use std::path::PathBuf; use std::fmt::Debug; +use std::collections::HashMap; use error::StoreError as SE; use store::Entry; @@ -41,6 +42,9 @@ pub trait FileAbstraction : Debug { fn create_dir_all(&self, _: &PathBuf) -> Result<(), SE>; fn new_instance(&self, p: PathBuf) -> Box; + + fn drain(&self) -> Result; + fn fill<'a>(&'a mut self, d: Drain) -> Result<(), SE>; } /// 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>; } +pub struct Drain(HashMap); + +impl Drain { + + pub fn new(hm: HashMap) -> 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.0.next() + } +} + #[cfg(test)] mod test { use std::path::PathBuf; diff --git a/libimagstore/src/file_abstraction/stdio/mod.rs b/libimagstore/src/file_abstraction/stdio/mod.rs index dcc8fe3f..e2ac5ec4 100644 --- a/libimagstore/src/file_abstraction/stdio/mod.rs +++ b/libimagstore/src/file_abstraction/stdio/mod.rs @@ -35,6 +35,7 @@ use error::StoreErrorKind as SEK; use error::StoreError as SE; use super::FileAbstraction; use super::FileAbstractionInstance; +use super::Drain; use super::InMemoryFileAbstraction; use store::Entry; @@ -114,5 +115,13 @@ impl FileAbstraction for StdIoFileAbstraction { fn new_instance(&self, p: PathBuf) -> Box { self.0.new_instance(p) } + + fn drain(&self) -> Result { + self.0.drain() + } + + fn fill(&mut self, d: Drain) -> Result<(), SE> { + self.0.fill(d) + } } diff --git a/libimagstore/src/file_abstraction/stdio/out.rs b/libimagstore/src/file_abstraction/stdio/out.rs index fffe535e..eca99114 100644 --- a/libimagstore/src/file_abstraction/stdio/out.rs +++ b/libimagstore/src/file_abstraction/stdio/out.rs @@ -29,6 +29,7 @@ use std::io::Write; use std::path::PathBuf; use std::sync::Arc; use std::sync::Mutex; +use std::ops::Deref; use libimagerror::into::IntoError; use libimagerror::trace::*; @@ -37,6 +38,7 @@ use error::StoreErrorKind as SEK; use error::StoreError as SE; use super::FileAbstraction; use super::FileAbstractionInstance; +use super::Drain; use super::InMemoryFileAbstraction; use store::Entry; @@ -68,6 +70,14 @@ impl StdoutFileAbstraction self.mem.backend() } + fn backend_cloned(&self) -> Result, SE> { + self.mem + .backend() + .lock() + .map_err(|_| SEK::LockError.into_error()) + .map(|mtx| mtx.deref().borrow().clone()) + } + pub fn mapper(&self) -> &M { &self.mapper } @@ -125,6 +135,23 @@ impl FileAbstraction for StdoutFileAbstraction { fn new_instance(&self, p: PathBuf) -> Box { self.mem.new_instance(p) } + + fn drain(&self) -> Result { + 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(()) + } + }