diff --git a/firewood/src/merkle.rs b/firewood/src/merkle.rs index 168b44500..d54dcb0a5 100644 --- a/firewood/src/merkle.rs +++ b/firewood/src/merkle.rs @@ -1519,7 +1519,7 @@ impl + Send + Sync, T> Merkle { ) -> Result, MerkleError> { if let Err(ObjWriteSizeError) = write_result { let old_node_address = node.as_ptr(); - node = self.put_node(node.clone())?; + node = self.put_node(node.into_inner())?; deleted.push(old_node_address); set_parent(node.as_ptr(), parents); @@ -2323,7 +2323,6 @@ mod tests { } #[test] - #[ignore] fn single_key_proof_with_one_node() { let mut merkle = create_test_merkle(); let root = merkle.init_root().unwrap(); @@ -2362,7 +2361,6 @@ mod tests { } #[test] - #[ignore] fn update_leaf_with_larger_path() -> Result<(), MerkleError> { let path = vec![0x00]; let data = vec![0x00]; @@ -2382,7 +2380,6 @@ mod tests { } #[test] - #[ignore] fn update_leaf_with_larger_data() -> Result<(), MerkleError> { let path = vec![0x00]; let data = vec![0x00]; @@ -2402,7 +2399,6 @@ mod tests { } #[test] - #[ignore] fn update_branch_with_larger_path() -> Result<(), MerkleError> { let path = vec![0x00]; let data = vec![0x00]; @@ -2424,7 +2420,6 @@ mod tests { } #[test] - #[ignore] fn update_branch_with_larger_data() -> Result<(), MerkleError> { let path = vec![0x00]; let data = vec![0x00]; diff --git a/firewood/src/shale/compact.rs b/firewood/src/shale/compact.rs index 15306bceb..b71a3f5f0 100644 --- a/firewood/src/shale/compact.rs +++ b/firewood/src/shale/compact.rs @@ -603,7 +603,7 @@ impl Sh let cache = &self.obj_cache; - let mut obj_ref = ObjRef::new(Some(obj), cache); + let mut obj_ref = ObjRef::new(obj, cache); // should this use a `?` instead of `unwrap`? #[allow(clippy::unwrap_used)] @@ -628,7 +628,7 @@ impl Sh let cache = &self.obj_cache; if let Some(obj) = obj { - return Ok(ObjRef::new(Some(obj), cache)); + return Ok(ObjRef::new(obj, cache)); } #[allow(clippy::unwrap_used)] @@ -645,7 +645,7 @@ impl Sh let obj = self.obj_cache.put(inner.get_data_ref(ptr, payload_size)?); let cache = &self.obj_cache; - Ok(ObjRef::new(Some(obj), cache)) + Ok(ObjRef::new(obj, cache)) } #[allow(clippy::unwrap_used)] diff --git a/firewood/src/shale/mod.rs b/firewood/src/shale/mod.rs index 1d3cb79af..a7b762c13 100644 --- a/firewood/src/shale/mod.rs +++ b/firewood/src/shale/mod.rs @@ -11,6 +11,8 @@ use std::sync::{Arc, RwLock, RwLockWriteGuard}; use thiserror::Error; +use crate::merkle::{LeafNode, Node, PartialPath}; + pub mod cached; pub mod compact; pub mod disk_address; @@ -155,6 +157,17 @@ impl Obj { } } +impl Obj { + pub fn into_inner(mut self) -> Node { + let empty_node = LeafNode { + path: PartialPath(Vec::new()), + data: Vec::new().into(), + }; + + std::mem::replace(&mut self.value.decoded, Node::from_leaf(empty_node)) + } +} + impl Drop for Obj { fn drop(&mut self) { self.flush_dirty() @@ -171,12 +184,15 @@ impl Deref for Obj { /// User handle that offers read & write access to the stored [ShaleStore] item. #[derive(Debug)] pub struct ObjRef<'a, T: Storable> { + /// WARNING: + /// [Self::inner] should only set to [None] when consuming [Self] or inside [Drop::drop]. inner: Option>, cache: &'a ObjCache, } impl<'a, T: Storable + Debug> ObjRef<'a, T> { - const fn new(inner: Option>, cache: &'a ObjCache) -> Self { + const fn new(inner: Obj, cache: &'a ObjCache) -> Self { + let inner = Some(inner); Self { inner, cache } } @@ -196,6 +212,17 @@ impl<'a, T: Storable + Debug> ObjRef<'a, T> { } } +impl<'a> ObjRef<'a, Node> { + /// # Panics: + /// if inner is not set + pub fn into_inner(mut self) -> Node { + self.inner + .take() + .expect("inner should already be set") + .into_inner() + } +} + impl<'a, T: Storable + Debug> Deref for ObjRef<'a, T> { type Target = Obj; fn deref(&self) -> &Obj { @@ -207,16 +234,16 @@ impl<'a, T: Storable + Debug> Deref for ObjRef<'a, T> { impl<'a, T: Storable> Drop for ObjRef<'a, T> { fn drop(&mut self) { - #[allow(clippy::unwrap_used)] - let mut inner = self.inner.take().unwrap(); - let ptr = inner.as_ptr(); - let mut cache = self.cache.lock(); - match cache.pinned.remove(&ptr) { - Some(true) => { - inner.dirty = None; - } - _ => { - cache.cached.put(ptr, inner); + if let Some(mut inner) = self.inner.take() { + let ptr = inner.as_ptr(); + let mut cache = self.cache.lock(); + match cache.pinned.remove(&ptr) { + Some(true) => { + inner.dirty = None; + } + _ => { + cache.cached.put(ptr, inner); + } } } }