diff --git a/grovedb/src/merk_cache.rs b/grovedb/src/merk_cache.rs index 7804fad3..31219ee0 100644 --- a/grovedb/src/merk_cache.rs +++ b/grovedb/src/merk_cache.rs @@ -30,25 +30,24 @@ struct CachedMerk<'db> { /// structure. Eventually we'll have enough info at the same place to perform /// necessary propagations as well. pub(crate) struct MerkCache<'db, 'b, B> { + merks: BTreeMap, CachedMerk<'db>>, db: &'db GroveDb, tx: &'db Transaction<'db>, - batch: &'db StorageBatch, + batch: &'static StorageBatch, version: &'db GroveVersion, - merks: BTreeMap, CachedMerk<'db>>, } impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> { pub(crate) fn new( db: &'db GroveDb, tx: &'db Transaction<'db>, - batch: &'db StorageBatch, version: &'db GroveVersion, ) -> Self { MerkCache { db, tx, - batch, version, + batch: Box::leak(Box::new(StorageBatch::default())), merks: Default::default(), } } @@ -131,6 +130,19 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> { Ok(result).wrap_with_cost(cost) } + + /// Summarizes all performed operations on this `MerkCache` with necessary + /// propagations into a `Storagebatch`. + pub(crate) fn finalize(self) -> Box { + let batch_ptr = self.batch as *const _; + // Remove all possible usages of the `StorageBatch`: + drop(self); + + // SAFETY: The batch reference was created by `Box::leak` and restored into a + // `Box` form. No shared usage of that memory exists because the + // `MerkCache` structure was dropped above. + unsafe { Box::from_raw(batch_ptr as *mut _) } + } } /// Handle to a cached Merk. @@ -193,7 +205,7 @@ mod tests { let db = make_deep_tree(&version); let tx = db.start_transaction(); let batch = StorageBatch::new(); - let mut cache = MerkCache::new(&db, &tx, &batch, version); + let mut cache = MerkCache::new(&db, &tx, version); let mut cost: OperationCost = Default::default(); let [test1, test2] = cache @@ -231,7 +243,7 @@ mod tests { let db = make_deep_tree(&version); let tx = db.start_transaction(); let batch = StorageBatch::new(); - let mut cache = MerkCache::new(&db, &tx, &batch, version); + let mut cache = MerkCache::new(&db, &tx, version); let _ = cache.get_multi_mut([ SubtreePath::from(&[TEST_LEAF]),