From c0936a0273933f878141f69ab834a19596e9b13f Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 18 Jun 2017 13:02:45 +0200 Subject: [PATCH 1/7] Add Store::reset_backend() function for re-setting the backend --- libimagstore/src/store.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libimagstore/src/store.rs b/libimagstore/src/store.rs index b3d10cfc..6b54967b 100644 --- a/libimagstore/src/store.rs +++ b/libimagstore/src/store.rs @@ -295,6 +295,36 @@ impl Store { Ok(store) } + /// Reset the backend of the store during runtime + /// + /// # Warning + /// + /// This is dangerous! + /// You should not be able to do that in application code, only the libimagrt should be used to + /// do this via safe and careful wrapper functions! + /// + /// If you are able to do this without using `libimagrt`, please file an issue report. + /// + /// # Purpose + /// + /// With the I/O backend of the store, the store is able to pipe itself out via (for example) + /// JSON. But because we need a functionality where we load contents from the filesystem and + /// then pipe it to stdout, we need to be able to replace the backend during runtime. + /// + /// This also applies the other way round: If we get the store from stdin and have to persist it + /// to stdout, we need to be able to replace the in-memory backend with the real filesystem + /// backend. + /// + /// # TODO + /// + /// Currently, this is the naive implementatoin which does not transfer contents of the + /// backends. + /// + pub fn reset_backend(&mut self, backend: Box) -> Result<()> { + self.backend = backend; + Ok(()) + } + /// Get the store configuration pub fn config(&self) -> Option<&Value> { self.configuration.as_ref() From 41f3b10976d7ef635a3cd1a6e989e793c583d433 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 18 Jun 2017 13:04:08 +0200 Subject: [PATCH 2/7] Add Runtime::store_backend_to_stdio() function --- libimagrt/src/runtime.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/libimagrt/src/runtime.rs b/libimagrt/src/runtime.rs index 33bcfd53..f8f29a2d 100644 --- a/libimagrt/src/runtime.rs +++ b/libimagrt/src/runtime.rs @@ -343,6 +343,31 @@ impl<'a> Runtime<'a> { &self.store } + /// Change the store backend to stdout + /// + /// For the documentation on purpose and cavecats, have a look at the documentation of the + /// `Store::reset_backend()` function. + /// + pub fn store_backend_to_stdio(&mut self) -> Result<(), RuntimeError> { + use libimagstore::file_abstraction::stdio::*; + use libimagstore::file_abstraction::stdio::mapper::json::JsonMapper; + use std::rc::Rc; + use std::cell::RefCell; + + let mut input = ::std::io::empty(); + let output = ::std::io::stdout(); + let output = Rc::new(RefCell::new(output)); + let mapper = JsonMapper::new(); + + StdIoFileAbstraction::new(&mut input, output, mapper) + .map_err_into(RuntimeErrorKind::Instantiate) + .and_then(|backend| { + self.store + .reset_backend(Box::new(backend)) + .map_err_into(RuntimeErrorKind::Instantiate) + }) + } + /// Get a editor command object which can be called to open the $EDITOR pub fn editor(&self) -> Option { self.cli() From caf77012d9f83cb7d9a08cd336952da42f6b16fa Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 18 Jun 2017 13:21:17 +0200 Subject: [PATCH 3/7] Add tests to test backend replacing --- libimagstore/src/store.rs | 144 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/libimagstore/src/store.rs b/libimagstore/src/store.rs index 6b54967b..6ef04837 100644 --- a/libimagstore/src/store.rs +++ b/libimagstore/src/store.rs @@ -1562,5 +1562,149 @@ mod store_tests { } } + #[test] + fn test_swap_backend_during_runtime() { + use file_abstraction::InMemoryFileAbstraction; + + let mut store = { + let backend = InMemoryFileAbstraction::new(); + let backend = Box::new(backend); + + Store::new_with_backend(PathBuf::from("/"), None, backend).unwrap() + }; + + for n in 1..100 { + let s = format!("test-{}", n); + let entry = store.create(PathBuf::from(s.clone())).unwrap(); + assert!(entry.verify().is_ok()); + let loc = entry.get_location().clone().into_pathbuf().unwrap(); + assert!(loc.starts_with("/")); + assert!(loc.ends_with(s)); + } + + { + let other_backend = InMemoryFileAbstraction::new(); + let other_backend = Box::new(other_backend); + + assert!(store.reset_backend(other_backend).is_ok()) + } + + for n in 1..100 { + let s = format!("test-{}", n); + let entry = store.get(PathBuf::from(s.clone())); + + assert!(entry.is_ok()); + let entry = entry.unwrap(); + + assert!(entry.is_some()); + let entry = entry.unwrap(); + + assert!(entry.verify().is_ok()); + + let loc = entry.get_location().clone().into_pathbuf().unwrap(); + assert!(loc.starts_with("/")); + assert!(loc.ends_with(s)); + } + } + + #[test] + fn test_swap_backend_during_runtime_with_io() { + use std::io::Cursor; + use std::rc::Rc; + use std::cell::RefCell; + use serde_json::Value; + use file_abstraction::stdio::out::StdoutFileAbstraction; + use file_abstraction::stdio::mapper::json::JsonMapper; + + // The output we later read from and check whether there is an entry + let output = Rc::new(RefCell::new(vec![])); + + { + let mut store = { + use file_abstraction::stdio::StdIoFileAbstraction; + use file_abstraction::stdio::mapper::json::JsonMapper; + + // Lets have an empty store as input + let mut input = Cursor::new(r#" + { "version": "0.3.0", + "store": { + "example": { + "header": { + "imag": { + "version": "0.3.0" + } + }, + "content": "foobar" + } + } + } + "#); + + let output = Rc::new(RefCell::new(::std::io::sink())); + let mapper = JsonMapper::new(); + let backend = StdIoFileAbstraction::new(&mut input, output, mapper).unwrap(); + let backend = Box::new(backend); + + Store::new_with_backend(PathBuf::from("/"), None, backend).unwrap() + }; + + // Replacing the backend + + { + let mapper = JsonMapper::new(); + let backend = StdoutFileAbstraction::new(output.clone(), mapper); + let _ = assert!(backend.is_ok(), format!("Should be ok: {:?}", backend)); + let backend = backend.unwrap(); + let backend = Box::new(backend); + + assert!(store.reset_backend(backend).is_ok()); + } + } + + let vec = Rc::try_unwrap(output).unwrap().into_inner(); + let errstr = format!("Not UTF8: '{:?}'", vec); + let string = String::from_utf8(vec); + assert!(string.is_ok(), errstr); + let string = string.unwrap(); + + assert!(!string.is_empty(), format!("Expected not to be empty: '{}'", string)); + + let json : ::serde_json::Value = ::serde_json::from_str(&string).unwrap(); + + match json { + Value::Object(ref map) => { + assert!(map.get("version").is_some(), format!("No 'version' in JSON")); + match map.get("version").unwrap() { + &Value::String(ref s) => assert_eq!("0.3.0", s), + _ => panic!("Wrong type in JSON at 'version'"), + } + + assert!(map.get("store").is_some(), format!("No 'store' in JSON")); + match map.get("store").unwrap() { + &Value::Object(ref objs) => { + let s = String::from("example"); + assert!(objs.get(&s).is_some(), format!("No entry: '{}' in \n{:?}", s, objs)); + match objs.get(&s).unwrap() { + &Value::Object(ref entry) => { + match entry.get("header").unwrap() { + &Value::Object(_) => assert!(true), + _ => panic!("Wrong type in JSON at 'store.'{}'.header'", s), + } + + match entry.get("content").unwrap() { + &Value::String(_) => assert!(true), + _ => panic!("Wrong type in JSON at 'store.'{}'.content'", s), + } + }, + _ => panic!("Wrong type in JSON at 'store.'{}''", s), + } + }, + _ => panic!("Wrong type in JSON at 'store'"), + } + }, + _ => panic!("Wrong type in JSON at top level"), + } + + } } From b572e7e8b9d51d7aacedd500ef1244b057bbde13 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 18 Jun 2017 13:31:20 +0200 Subject: [PATCH 4/7] Abstract away the output of the IO backend This patch refactors the output part of the IO backend into an own backend which is simply used by the IO-backend. This way we can have a pure-output backend. --- .../src/file_abstraction/stdio/mod.rs | 91 +++++------- .../src/file_abstraction/stdio/out.rs | 130 ++++++++++++++++++ 2 files changed, 167 insertions(+), 54 deletions(-) create mode 100644 libimagstore/src/file_abstraction/stdio/out.rs diff --git a/libimagstore/src/file_abstraction/stdio/mod.rs b/libimagstore/src/file_abstraction/stdio/mod.rs index 899d6442..dcc8fe3f 100644 --- a/libimagstore/src/file_abstraction/stdio/mod.rs +++ b/libimagstore/src/file_abstraction/stdio/mod.rs @@ -20,16 +20,16 @@ use std::rc::Rc; use std::cell::RefCell; use std::collections::HashMap; -use std::fmt::Debug; -use std::fmt::Error as FmtError; -use std::fmt::Formatter; use std::io::{Read, Write}; use std::path::PathBuf; use std::sync::Arc; use std::sync::Mutex; +use std::ops::Deref; +use std::fmt::Debug; +use std::fmt::Error as FmtError; +use std::fmt::Formatter; use libimagerror::into::IntoError; -use libimagerror::trace::*; use error::StoreErrorKind as SEK; use error::StoreError as SE; @@ -39,25 +39,14 @@ use super::InMemoryFileAbstraction; use store::Entry; pub mod mapper; +pub mod out; use self::mapper::Mapper; +use self::out::StdoutFileAbstraction; // Because this is not exported in super::inmemory; type Backend = Arc>>>; -pub struct StdIoFileAbstraction { - mapper: M, - mem: InMemoryFileAbstraction, - out: Rc>, -} - -impl Debug for StdIoFileAbstraction - where M: Mapper, - W: Write -{ - fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { - write!(f, "StdIoFileAbstraction({:?}", self.mem) - } -} +pub struct StdIoFileAbstraction(StdoutFileAbstraction); impl StdIoFileAbstraction where M: Mapper, @@ -65,71 +54,65 @@ impl StdIoFileAbstraction { pub fn new(in_stream: &mut R, out_stream: Rc>, mapper: M) -> Result, SE> { - let mem = InMemoryFileAbstraction::new(); + StdoutFileAbstraction::new(out_stream, mapper) + .and_then(|out| { + let fill_res = match out.backend().lock() { + Err(_) => Err(SEK::LockError.into_error()), + Ok(mut mtx) => out.mapper().read_to_fs(in_stream, mtx.get_mut()) + }; + let _ = try!(fill_res); - { - let fill_res = match mem.backend().lock() { - Err(_) => Err(SEK::LockError.into_error()), - Ok(mut mtx) => mapper.read_to_fs(in_stream, mtx.get_mut()) - }; - let _ = try!(fill_res); - } - - Ok(StdIoFileAbstraction { - mapper: mapper, - mem: mem, - out: out_stream, - }) + Ok(StdIoFileAbstraction(out)) + }) } pub fn backend(&self) -> &Backend { - self.mem.backend() + self.0.backend() } } -impl Drop for StdIoFileAbstraction +impl Debug for StdIoFileAbstraction where M: Mapper, W: Write { - fn drop(&mut self) { - use std::ops::DerefMut; - - let fill_res = match self.mem.backend().lock() { - Err(_) => Err(SEK::LockError.into_error()), - Ok(mut mtx) => { - self.mapper.fs_to_write(mtx.get_mut(), self.out.borrow_mut().deref_mut()) - }, - }; - - // We can do nothing but end this here with a trace. - // As this drop gets called when imag almost exits, there is no point in exit()ing here - // again. - let _ = fill_res.map_err_trace(); + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "StdIoFileAbstraction({:?}", self.0) } } +impl Deref for StdIoFileAbstraction + where M: Mapper, + W: Write +{ + type Target = StdoutFileAbstraction; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +// basically #[derive(FileAbstraction)] impl FileAbstraction for StdIoFileAbstraction { fn remove_file(&self, path: &PathBuf) -> Result<(), SE> { - self.mem.remove_file(path) + self.0.remove_file(path) } fn copy(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> { - self.mem.copy(from, to) + self.0.copy(from, to) } fn rename(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> { - self.mem.rename(from, to) + self.0.rename(from, to) } fn create_dir_all(&self, pb: &PathBuf) -> Result<(), SE> { - self.mem.create_dir_all(pb) + self.0.create_dir_all(pb) } fn new_instance(&self, p: PathBuf) -> Box { - self.mem.new_instance(p) + self.0.new_instance(p) } } - diff --git a/libimagstore/src/file_abstraction/stdio/out.rs b/libimagstore/src/file_abstraction/stdio/out.rs new file mode 100644 index 00000000..fffe535e --- /dev/null +++ b/libimagstore/src/file_abstraction/stdio/out.rs @@ -0,0 +1,130 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +//! A StdIoFileAbstraction which does not read from stdin. + +use std::rc::Rc; +use std::cell::RefCell; +use std::collections::HashMap; +use std::fmt::Debug; +use std::fmt::Error as FmtError; +use std::fmt::Formatter; +use std::io::Write; +use std::path::PathBuf; +use std::sync::Arc; +use std::sync::Mutex; + +use libimagerror::into::IntoError; +use libimagerror::trace::*; + +use error::StoreErrorKind as SEK; +use error::StoreError as SE; +use super::FileAbstraction; +use super::FileAbstractionInstance; +use super::InMemoryFileAbstraction; +use store::Entry; + +use super::mapper::Mapper; + +// Because this is not exported in super::inmemory; +type Backend = Arc>>>; + +pub struct StdoutFileAbstraction { + mapper: M, + mem: InMemoryFileAbstraction, + out: Rc>, +} + +impl StdoutFileAbstraction + where M: Mapper, + W: Write +{ + + pub fn new(out_stream: Rc>, mapper: M) -> Result, SE> { + Ok(StdoutFileAbstraction { + mapper: mapper, + mem: InMemoryFileAbstraction::new(), + out: out_stream, + }) + } + + pub fn backend(&self) -> &Backend { + self.mem.backend() + } + + pub fn mapper(&self) -> &M { + &self.mapper + } + +} + +impl Debug for StdoutFileAbstraction + where M: Mapper, + W: Write +{ + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "StdoutFileAbstraction({:?}", self.mem) + } +} + +impl Drop for StdoutFileAbstraction + where M: Mapper, + W: Write +{ + fn drop(&mut self) { + use std::ops::DerefMut; + + let fill_res = match self.mem.backend().lock() { + Err(_) => Err(SEK::LockError.into_error()), + Ok(mut mtx) => { + self.mapper.fs_to_write(mtx.get_mut(), self.out.borrow_mut().deref_mut()) + }, + }; + + // We can do nothing but end this here with a trace. + // As this drop gets called when imag almost exits, there is no point in exit()ing here + // again. + let _ = fill_res.map_err_trace(); + } +} + +impl FileAbstraction for StdoutFileAbstraction { + + fn remove_file(&self, path: &PathBuf) -> Result<(), SE> { + self.mem.remove_file(path) + } + + fn copy(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> { + self.mem.copy(from, to) + } + + fn rename(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> { + self.mem.rename(from, to) + } + + fn create_dir_all(&self, pb: &PathBuf) -> Result<(), SE> { + self.mem.create_dir_all(pb) + } + + fn new_instance(&self, p: PathBuf) -> Box { + self.mem.new_instance(p) + } +} + + From c81417187531469701050c4c123fc60ea5d9440a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 18 Jun 2017 13:41:43 +0200 Subject: [PATCH 5/7] 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(()) + } + } From a4188a3100bcf4f861fa135f0fda5c3141a851c7 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 18 Jun 2017 18:48:08 +0200 Subject: [PATCH 6/7] Add proper impl of Store::reset_backend() --- libimagstore/src/store.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libimagstore/src/store.rs b/libimagstore/src/store.rs index 6ef04837..38e5dd6b 100644 --- a/libimagstore/src/store.rs +++ b/libimagstore/src/store.rs @@ -320,9 +320,11 @@ impl Store { /// Currently, this is the naive implementatoin which does not transfer contents of the /// backends. /// - pub fn reset_backend(&mut self, backend: Box) -> Result<()> { - self.backend = backend; - Ok(()) + pub fn reset_backend(&mut self, mut backend: Box) -> Result<()> { + self.backend + .drain() + .and_then(|drain| backend.fill(drain)) + .map(|_| self.backend = backend) } /// Get the store configuration From a672e4db2126f6be1d651c33648e50598ed4bb2e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 18 Jun 2017 19:33:52 +0200 Subject: [PATCH 7/7] Remove TODO from Store::reset_backend() --- libimagstore/src/store.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libimagstore/src/store.rs b/libimagstore/src/store.rs index 38e5dd6b..d7e7fe2f 100644 --- a/libimagstore/src/store.rs +++ b/libimagstore/src/store.rs @@ -315,11 +315,6 @@ impl Store { /// to stdout, we need to be able to replace the in-memory backend with the real filesystem /// backend. /// - /// # TODO - /// - /// Currently, this is the naive implementatoin which does not transfer contents of the - /// backends. - /// pub fn reset_backend(&mut self, mut backend: Box) -> Result<()> { self.backend .drain()