summaryrefslogtreecommitdiffstats
path: root/lib/core/libimagstore/src/store.rs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/core/libimagstore/src/store.rs')
-rw-r--r--lib/core/libimagstore/src/store.rs103
1 files changed, 52 insertions, 51 deletions
diff --git a/lib/core/libimagstore/src/store.rs b/lib/core/libimagstore/src/store.rs
index aa3ae4ba..3cd0bfeb 100644
--- a/lib/core/libimagstore/src/store.rs
+++ b/lib/core/libimagstore/src/store.rs
@@ -43,12 +43,10 @@ use failure::Error;
use storeid::{IntoStoreId, StoreId};
use iter::Entries;
+use file_abstraction::FileAbstraction;
use file_abstraction::FileAbstractionInstance;
-
-// We re-export the following things so tests can use them
-pub use file_abstraction::FileAbstraction;
-pub use file_abstraction::FSFileAbstraction;
-pub use file_abstraction::InMemoryFileAbstraction;
+use file_abstraction::fs::FSFileAbstraction;
+use file_abstraction::inmemory::InMemoryFileAbstraction;
use libimagutil::debug_result::*;
@@ -64,14 +62,15 @@ enum StoreEntryStatus {
#[derive(Debug)]
struct StoreEntry {
id: StoreId,
+ store_base: PathBuf, // small sacrefice over lifetimes on the Store type
file: Box<FileAbstractionInstance>,
status: StoreEntryStatus,
}
impl StoreEntry {
- fn new(id: StoreId, backend: &Arc<FileAbstraction>) -> Result<StoreEntry> {
- let pb = id.clone().into_pathbuf()?;
+ fn new(store_base: PathBuf, id: StoreId, backend: &Arc<FileAbstraction>) -> Result<StoreEntry> {
+ let pb = id.clone().with_base(&store_base).into_pathbuf()?;
#[cfg(feature = "fs-lock")]
{
@@ -82,6 +81,7 @@ impl StoreEntry {
Ok(StoreEntry {
id,
+ store_base,
file: backend.new_instance(pb),
status: StoreEntryStatus::Present,
})
@@ -95,7 +95,7 @@ impl StoreEntry {
fn get_entry(&mut self) -> Result<Entry> {
if !self.is_borrowed() {
- match self.file.get_file_content(self.id.clone())? {
+ match self.file.get_file_content(self.id.clone().with_base(&self.store_base))? {
Some(file) => Ok(file),
None => Ok(Entry::new(self.id.clone()))
}
@@ -170,13 +170,24 @@ impl Store {
Store::new_with_backend(location, store_config, backend)
}
+ /// Create the store with an in-memory filesystem
+ ///
+ /// # Usage
+ ///
+ /// this is for testing purposes only
+ #[inline]
+ pub fn new_inmemory(location: PathBuf, store_config: &Option<Value>) -> Result<Store> {
+ let backend = Arc::new(InMemoryFileAbstraction::default());
+ Self::new_with_backend(location, store_config, backend)
+ }
+
/// Create a Store object as descripbed in `Store::new()` documentation, but with an alternative
/// backend implementation.
///
/// Do not use directly, only for testing purposes.
- pub fn new_with_backend(location: PathBuf,
- store_config: &Option<Value>,
- backend: Arc<FileAbstraction>) -> Result<Store> {
+ pub(crate) fn new_with_backend(location: PathBuf,
+ store_config: &Option<Value>,
+ backend: Arc<FileAbstraction>) -> Result<Store> {
use configuration::*;
debug!("Building new Store object");
@@ -218,7 +229,7 @@ impl Store {
/// On success: FileLockEntry
///
pub fn create<'a, S: IntoStoreId>(&'a self, id: S) -> Result<FileLockEntry<'a>> {
- let id = id.into_storeid()?.with_base(self.path().clone());
+ let id = id.into_storeid()?;
debug!("Creating id: '{}'", id);
@@ -244,7 +255,7 @@ impl Store {
}
hsmap.insert(id.clone(), {
debug!("Creating: '{}'", id);
- let mut se = StoreEntry::new(id.clone(), &self.backend)?;
+ let mut se = StoreEntry::new(self.path().clone(), id.clone(), &self.backend)?;
se.status = StoreEntryStatus::Borrowed;
se
});
@@ -266,14 +277,14 @@ impl Store {
/// On success: FileLockEntry
///
pub fn retrieve<'a, S: IntoStoreId>(&'a self, id: S) -> Result<FileLockEntry<'a>> {
- let id = id.into_storeid()?.with_base(self.path().clone());
+ let id = id.into_storeid()?;
debug!("Retrieving id: '{}'", id);
let entry = self
.entries
.write()
.map_err(|_| Error::from(EM::LockError))
.and_then(|mut es| {
- let new_se = StoreEntry::new(id.clone(), &self.backend)?;
+ let new_se = StoreEntry::new(self.path().clone(), id.clone(), &self.backend)?;
let se = es.entry(id.clone()).or_insert(new_se);
let entry = se.get_entry();
se.status = StoreEntryStatus::Borrowed;
@@ -296,7 +307,7 @@ impl Store {
/// - Errors Store::retrieve() might return
///
pub fn get<'a, S: IntoStoreId + Clone>(&'a self, id: S) -> Result<Option<FileLockEntry<'a>>> {
- let id = id.into_storeid()?.with_base(self.path().clone());
+ let id = id.into_storeid()?;
debug!("Getting id: '{}'", id);
@@ -409,7 +420,7 @@ impl Store {
/// On success: Entry
///
pub fn get_copy<S: IntoStoreId>(&self, id: S) -> Result<Entry> {
- let id = id.into_storeid()?.with_base(self.path().clone());
+ let id = id.into_storeid()?;
debug!("Retrieving copy of '{}'", id);
let entries = self.entries.write()
.map_err(|_| Error::from(EM::LockError))
@@ -422,7 +433,7 @@ impl Store {
.map_err(Error::from)
}
- StoreEntry::new(id, &self.backend)?.get_entry()
+ StoreEntry::new(self.path().clone(), id, &self.backend)?.get_entry()
}
/// Delete an entry and the corrosponding file on disk
@@ -432,7 +443,7 @@ impl Store {
/// On success: ()
///
pub fn delete<S: IntoStoreId>(&self, id: S) -> Result<()> {
- let id = id.into_storeid()?.with_base(self.path().clone());
+ let id = id.into_storeid()?;
debug!("Deleting id: '{}'", id);
@@ -440,7 +451,7 @@ impl Store {
// StoreId::exists(), a PathBuf object gets allocated. So we simply get a
// PathBuf here, check whether it is there and if it is, we can re-use it to
// delete the filesystem file.
- let pb = id.clone().into_pathbuf()?;
+ let pb = id.clone().with_base(self.path()).into_pathbuf()?;
{
let mut entries = self
@@ -507,7 +518,6 @@ impl Store {
fn save_to_other_location(&self, entry: &FileLockEntry, new_id: StoreId, remove_old: bool)
-> Result<()>
{
- let new_id = new_id.with_base(self.path().clone());
let hsmap = self
.entries
.write()
@@ -522,8 +532,8 @@ impl Store {
let old_id = entry.get_location().clone();
- let old_id_as_path = old_id.clone().with_base(self.path().clone()).into_pathbuf()?;
- let new_id_as_path = new_id.clone().with_base(self.path().clone()).into_pathbuf()?;
+ let old_id_as_path = old_id.clone().with_base(self.path()).into_pathbuf()?;
+ let new_id_as_path = new_id.clone().with_base(self.path()).into_pathbuf()?;
self.backend
.copy(&old_id_as_path, &new_id_as_path)
.and_then(|_| if remove_old {
@@ -571,9 +581,6 @@ impl Store {
/// So the link is _partly dangling_, so to say.
///
pub fn move_by_id(&self, old_id: StoreId, new_id: StoreId) -> Result<()> {
- let new_id = new_id.with_base(self.path().clone());
- let old_id = old_id.with_base(self.path().clone());
-
debug!("Moving '{}' to '{}'", old_id, new_id);
{
@@ -594,8 +601,8 @@ impl Store {
debug!("Old id is not yet borrowed");
- let old_id_pb = old_id.clone().with_base(self.path().clone()).into_pathbuf()?;
- let new_id_pb = new_id.clone().with_base(self.path().clone()).into_pathbuf()?;
+ let old_id_pb = old_id.clone().with_base(self.path()).into_pathbuf()?;
+ let new_id_pb = new_id.clone().with_base(self.path()).into_pathbuf()?;
if self.backend.exists(&new_id_pb)? {
return Err(format_err!("Entry already exists: {}", new_id));
@@ -618,8 +625,8 @@ impl Store {
assert!(hsmap
.remove(&old_id)
.and_then(|mut entry| {
- entry.id = new_id.clone();
- hsmap.insert(new_id.clone(), entry)
+ entry.id = new_id.clone().into();
+ hsmap.insert(new_id.clone().into(), entry)
}).is_none())
}
@@ -631,7 +638,7 @@ impl Store {
pub fn entries<'a>(&'a self) -> Result<Entries<'a>> {
trace!("Building 'Entries' iterator");
self.backend
- .pathes_recursively(self.path().clone(), self.path().clone(), self.backend.clone())
+ .pathes_recursively(self.path().clone(), self.path(), self.backend.clone())
.map(|i| Entries::new(i, self))
}
@@ -645,7 +652,7 @@ impl Store {
.context(format_err!("CreateCallError: {}", id));
let backend_has_entry = |id: StoreId|
- self.backend.exists(&id.with_base(self.path().to_path_buf()).into_pathbuf()?);
+ self.backend.exists(&id.with_base(self.path()).into_pathbuf()?);
Ok(cache_has_entry(&id)? || backend_has_entry(id)?)
}
@@ -1000,7 +1007,7 @@ Hai
setup_logging();
debug!("{}", TEST_ENTRY);
- let entry = Entry::from_str(StoreId::new_baseless(PathBuf::from("test/foo~1.3")).unwrap(),
+ let entry = Entry::from_str(StoreId::new(PathBuf::from("test/foo~1.3")).unwrap(),
TEST_ENTRY).unwrap();
assert_eq!(entry.content, "Hai");
@@ -1014,7 +1021,7 @@ Hai
setup_logging();
debug!("{}", TEST_ENTRY);
- let entry = Entry::from_str(StoreId::new_baseless(PathBuf::from("test/foo~1.3")).unwrap(),
+ let entry = Entry::from_str(StoreId::new(PathBuf::from("test/foo~1.3")).unwrap(),
TEST_ENTRY).unwrap();
let string = entry.to_str().unwrap();
@@ -1029,7 +1036,7 @@ Hai
setup_logging();
debug!("{}", TEST_ENTRY_TNL);
- let entry = Entry::from_str(StoreId::new_baseless(PathBuf::from("test/foo~1.3")).unwrap(),
+ let entry = Entry::from_str(StoreId::new(PathBuf::from("test/foo~1.3")).unwrap(),
TEST_ENTRY_TNL).unwrap();
let string = entry.to_str().unwrap();
@@ -1049,9 +1056,9 @@ mod store_tests {
}
use super::Store;
- use file_abstraction::InMemoryFileAbstraction;
pub fn get_store() -> Store {
+ use file_abstraction::inmemory::InMemoryFileAbstraction;
let backend = Arc::new(InMemoryFileAbstraction::default());
Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap()
}
@@ -1072,7 +1079,7 @@ mod store_tests {
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();
+ let loc = entry.get_location().clone().with_base(store.path()).into_pathbuf().unwrap();
assert!(loc.starts_with("/"));
assert!(loc.ends_with(s));
}
@@ -1093,7 +1100,7 @@ mod store_tests {
assert!(entry.verify().is_ok());
- let loc = entry.get_location().clone().into_pathbuf().unwrap();
+ let loc = entry.get_location().clone().with_base(store.path()).into_pathbuf().unwrap();
assert!(loc.starts_with("/"));
assert!(loc.ends_with(s));
@@ -1125,7 +1132,7 @@ mod store_tests {
.ok()
.map(|entry| {
assert!(entry.verify().is_ok());
- let loc = entry.get_location().clone().into_pathbuf().unwrap();
+ let loc = entry.get_location().clone().with_base(store.path()).into_pathbuf().unwrap();
assert!(loc.starts_with("/"));
assert!(loc.ends_with(s));
});
@@ -1139,12 +1146,10 @@ mod store_tests {
let store = get_store();
for n in 1..100 {
- let pb = StoreId::new_baseless(PathBuf::from(format!("test-{}", n))).unwrap();
+ let pb = StoreId::new(PathBuf::from(format!("test-{}", n))).unwrap();
assert!(store.entries.read().unwrap().get(&pb).is_none());
assert!(store.create(pb.clone()).is_ok());
-
- let pb = pb.with_base(store.path().clone());
assert!(store.entries.read().unwrap().get(&pb).is_some());
}
}
@@ -1156,12 +1161,10 @@ mod store_tests {
let store = get_store();
for n in 1..100 {
- let pb = StoreId::new_baseless(PathBuf::from(format!("test-{}", n))).unwrap();
+ let pb = StoreId::new(PathBuf::from(format!("test-{}", n))).unwrap();
assert!(store.entries.read().unwrap().get(&pb).is_none());
assert!(store.retrieve(pb.clone()).is_ok());
-
- let pb = pb.with_base(store.path().clone());
assert!(store.entries.read().unwrap().get(&pb).is_some());
}
}
@@ -1199,8 +1202,8 @@ mod store_tests {
for n in 1..100 {
if n % 2 == 0 { // every second
- let id = StoreId::new_baseless(PathBuf::from(format!("t-{}", n))).unwrap();
- let id_mv = StoreId::new_baseless(PathBuf::from(format!("t-{}", n - 1))).unwrap();
+ let id = StoreId::new(PathBuf::from(format!("t-{}", n))).unwrap();
+ let id_mv = StoreId::new(PathBuf::from(format!("t-{}", n - 1))).unwrap();
{
assert!(store.entries.read().unwrap().get(&id).is_none());
@@ -1211,16 +1214,14 @@ mod store_tests {
}
{
- let id_with_base = id.clone().with_base(store.path().clone());
- assert!(store.entries.read().unwrap().get(&id_with_base).is_some());
+ assert!(store.entries.read().unwrap().get(&id).is_some());
}
let r = store.move_by_id(id.clone(), id_mv.clone());
assert!(r.map_err(|e| debug!("ERROR: {:?}", e)).is_ok());
{
- let id_mv_with_base = id_mv.clone().with_base(store.path().clone());
- assert!(store.entries.read().unwrap().get(&id_mv_with_base).is_some());
+ assert!(store.entries.read().unwrap().get(&id_mv).is_some());
}
let res = store.get(id.clone());