Merge branch 'store-fixes' into master
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
commit
564a740741
2 changed files with 74 additions and 22 deletions
|
@ -28,6 +28,7 @@ use libimagerror::errors::ErrorMsg as EM;
|
||||||
|
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use failure::err_msg;
|
||||||
|
|
||||||
use super::FileAbstraction;
|
use super::FileAbstraction;
|
||||||
use super::FileAbstractionInstance;
|
use super::FileAbstractionInstance;
|
||||||
|
@ -137,7 +138,18 @@ impl FileAbstraction for InMemoryFileAbstraction {
|
||||||
let backend = mtx.get_mut();
|
let backend = mtx.get_mut();
|
||||||
|
|
||||||
let a = backend.remove(from).ok_or_else(|| EM::FileNotFound)?;
|
let a = backend.remove(from).ok_or_else(|| EM::FileNotFound)?;
|
||||||
backend.insert(to.clone(), a);
|
let new_entry = {
|
||||||
|
let new_location = if to.starts_with("/") {
|
||||||
|
let s = to.to_str().map(String::from).ok_or_else(|| err_msg("Failed to convert path to str"))?;
|
||||||
|
PathBuf::from(s.replace("/", ""))
|
||||||
|
} else {
|
||||||
|
to.to_path_buf()
|
||||||
|
};
|
||||||
|
|
||||||
|
Entry::from_str(crate::storeid::StoreId::new(new_location)?, &a.to_str()?)?
|
||||||
|
};
|
||||||
|
|
||||||
|
backend.insert(to.clone(), new_entry);
|
||||||
debug!("Renaming: {:?} -> {:?} worked", from, to);
|
debug!("Renaming: {:?} -> {:?} worked", from, to);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -590,18 +590,21 @@ impl Store {
|
||||||
}
|
}
|
||||||
debug!("New id does not exist in cache");
|
debug!("New id does not exist in cache");
|
||||||
|
|
||||||
// if we do not have an entry here, we fail in `FileAbstraction::rename()` below.
|
|
||||||
// if we have one, but it is borrowed, we really should not rename it, as this might
|
|
||||||
// lead to strange errors
|
|
||||||
if hsmap.get(&old_id).map(|e| e.is_borrowed()).unwrap_or(false) {
|
|
||||||
return Err(format_err!("Entry already borrowed: {}", old_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("Old id is not yet borrowed");
|
|
||||||
|
|
||||||
let old_id_pb = old_id.clone().with_base(self.path()).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()?;
|
let new_id_pb = new_id.clone().with_base(self.path()).into_pathbuf()?;
|
||||||
|
|
||||||
|
if !self.backend.exists(&old_id_pb)? {
|
||||||
|
return Err(format_err!("Entry does not exist: {}", old_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it is borrowed, we really should not rename it, as this might
|
||||||
|
// lead to strange errors
|
||||||
|
//
|
||||||
|
// Also, remove this object from the cache
|
||||||
|
if hsmap.remove(&old_id).map(|e| e.is_borrowed()).unwrap_or(false) {
|
||||||
|
return Err(format_err!("Entry already borrowed: {}", old_id));
|
||||||
|
}
|
||||||
|
|
||||||
if self.backend.exists(&new_id_pb)? {
|
if self.backend.exists(&new_id_pb)? {
|
||||||
return Err(format_err!("Entry already exists: {}", new_id));
|
return Err(format_err!("Entry already exists: {}", new_id));
|
||||||
}
|
}
|
||||||
|
@ -617,17 +620,6 @@ impl Store {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
debug!("Rename worked on filesystem");
|
debug!("Rename worked on filesystem");
|
||||||
|
|
||||||
// assert enforced through check hsmap.contains_key(&new_id) above.
|
|
||||||
// Should therefor never fail
|
|
||||||
let hsmap_does_not_have_key = hsmap
|
|
||||||
.remove(&old_id)
|
|
||||||
.and_then(|mut entry| {
|
|
||||||
entry.id = new_id.clone();
|
|
||||||
hsmap.insert(new_id.clone(), entry)
|
|
||||||
})
|
|
||||||
.is_none();
|
|
||||||
assert!(hsmap_does_not_have_key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Moved");
|
debug!("Moved");
|
||||||
|
@ -1204,23 +1196,32 @@ mod store_tests {
|
||||||
let id = StoreId::new(PathBuf::from(format!("t-{}", n))).unwrap();
|
let id = StoreId::new(PathBuf::from(format!("t-{}", n))).unwrap();
|
||||||
let id_mv = StoreId::new(PathBuf::from(format!("t-{}", n - 1))).unwrap();
|
let id_mv = StoreId::new(PathBuf::from(format!("t-{}", n - 1))).unwrap();
|
||||||
|
|
||||||
|
debug!("Trying to move: {} -> {}", id, id_mv);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
debug!("Checking presence: {}", id);
|
||||||
assert!(store.entries.read().unwrap().get(&id).is_none());
|
assert!(store.entries.read().unwrap().get(&id).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
debug!("Creating : {}", id);
|
||||||
assert!(store.create(id.clone()).is_ok());
|
assert!(store.create(id.clone()).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
debug!("Checking presence: {}", id);
|
||||||
assert!(store.entries.read().unwrap().get(&id).is_some());
|
assert!(store.entries.read().unwrap().get(&id).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("Moving: {} -> {}", id, id_mv);
|
||||||
let r = store.move_by_id(id.clone(), id_mv.clone());
|
let r = store.move_by_id(id.clone(), id_mv.clone());
|
||||||
assert!(r.map_err(|e| debug!("ERROR: {:?}", e)).is_ok());
|
assert!(r.map_err(|e| debug!("ERROR: {:?}", e)).is_ok());
|
||||||
|
|
||||||
{
|
{
|
||||||
assert!(store.entries.read().unwrap().get(&id_mv).is_some());
|
debug!("Checking presence: {}", id_mv);
|
||||||
|
assert!(store.entries.read().unwrap().get(&id_mv).is_none()); // entry not in cache yet
|
||||||
|
assert!(store.get(id_mv.clone()).unwrap().is_some()); // get entry from backend
|
||||||
|
assert!(store.entries.read().unwrap().get(&id_mv).is_some()); // entry in cache
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = store.get(id.clone());
|
let res = store.get(id.clone());
|
||||||
|
@ -1234,4 +1235,43 @@ mod store_tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_moving_entry_with_writing_before_and_after() {
|
||||||
|
use crate::storeid::StoreId;
|
||||||
|
setup_logging();
|
||||||
|
|
||||||
|
let store = get_store();
|
||||||
|
|
||||||
|
let old_name = StoreId::new(PathBuf::from("old")).unwrap();
|
||||||
|
let new_name = StoreId::new(PathBuf::from("new")).unwrap();
|
||||||
|
|
||||||
|
debug!("Creating old entry");
|
||||||
|
{
|
||||||
|
let mut entry = store.create(old_name.clone()).unwrap();
|
||||||
|
entry.get_content_mut().push_str("first line");
|
||||||
|
drop(entry);
|
||||||
|
} // make sure entry is dropped
|
||||||
|
|
||||||
|
debug!("Moving");
|
||||||
|
store.move_by_id(old_name.clone(), new_name.clone()).unwrap();
|
||||||
|
|
||||||
|
debug!("Getting old entry again (should not work)");
|
||||||
|
assert!(store.get(old_name).unwrap().is_none());
|
||||||
|
|
||||||
|
debug!("Getting new entry");
|
||||||
|
{
|
||||||
|
let mut entry = store.get(new_name.clone()).unwrap().unwrap();
|
||||||
|
assert_eq!(entry.get_content(), "first line");
|
||||||
|
entry.get_content_mut().push_str("second line");
|
||||||
|
drop(entry);
|
||||||
|
} // make sure entry is dropped
|
||||||
|
|
||||||
|
{
|
||||||
|
debug!("Getting new entry again");
|
||||||
|
debug!("Store = {:#?}", store);
|
||||||
|
let new_entry = store.get(new_name).unwrap().unwrap();
|
||||||
|
assert_eq!(new_entry.get_content(), "first linesecond line");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue