Merge branch 'store-fixes' into master

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
Matthias Beyer 2019-10-26 10:42:58 +02:00
commit 564a740741
2 changed files with 74 additions and 22 deletions

View file

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

View file

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