Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fominok committed Nov 5, 2024
1 parent 740d97d commit eb7b6b2
Showing 1 changed file with 40 additions and 15 deletions.
55 changes: 40 additions & 15 deletions grovedb/src/merk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ use crate::{Element, Error, GroveDb, Transaction};

type TxMerk<'db> = Merk<PrefixedRocksDbTransactionContext<'db>>;

struct CachedMerk<'db> {

Check warning on line 20 in grovedb/src/merk_cache.rs

View workflow job for this annotation

GitHub Actions / clippy

struct `CachedMerk` is never constructed

warning: struct `CachedMerk` is never constructed --> grovedb/src/merk_cache.rs:20:8 | 20 | struct CachedMerk<'db> { | ^^^^^^^^^^
updated: bool,
merk: TxMerk<'db>,
}

/// Merk caching structure.
///
/// Since we usually postpone all writes to the very end with a single RocksDB
Expand All @@ -29,7 +34,7 @@ pub(crate) struct MerkCache<'db, 'b, B> {
tx: &'db Transaction<'db>,
batch: &'db StorageBatch,
version: &'db GroveVersion,
merks: BTreeMap<SubtreePath<'b, B>, TxMerk<'db>>,
merks: BTreeMap<SubtreePath<'b, B>, CachedMerk<'db>>,
}

impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {
Expand All @@ -54,7 +59,7 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {
fn get_merk_mut_internal<'s>(
&'s mut self,
path: SubtreePath<'b, B>,
) -> CostResult<&'s mut TxMerk<'db>, Error> {
) -> CostResult<&'s mut CachedMerk<'db>, Error> {
let mut cost = Default::default();

match self.merks.entry(path) {
Expand All @@ -69,7 +74,11 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {
self.version
)
);
Ok(e.insert(merk)).wrap_with_cost(cost)
Ok(e.insert(CachedMerk {
merk,
updated: false,
}))
.wrap_with_cost(cost)
}
}
}
Expand All @@ -84,8 +93,8 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {
pub(crate) fn get_multi_mut<'s, const N: usize>(
&'s mut self,
paths: [SubtreePath<'b, B>; N],
) -> CostResult<[MerkHandle<'db, 's>; N], Error> {
let mut result_uninit = [const { MaybeUninit::<MerkHandle<'db, 's>>::uninit() }; N];
) -> CostResult<[MerkHandle<'db, 's, 'b, B>; N], Error> {
let mut result_uninit = [const { MaybeUninit::<MerkHandle<'db, 's, 'b, B>>::uninit() }; N];
let mut cost = Default::default();

let unique_args: HashSet<_> = paths.iter().collect();
Expand All @@ -100,13 +109,14 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {
// mutable references. The mandatory keys' uniqueness check above makes
// sure no overlapping memory will be referenced.
let merk_ref = unsafe {
MerkHandle {
merk: (cost_return_on_error!(&mut cost, self.get_merk_mut_internal(path))
as *mut TxMerk<'db>)
MerkHandle::new(
path.clone(),
(cost_return_on_error!(&mut cost, self.get_merk_mut_internal(path))
as *mut CachedMerk<'db>)
.as_mut::<'s>()
.expect("not a null pointer"),
version: &self.version,
}
&self.version,

Check warning on line 118 in grovedb/src/merk_cache.rs

View workflow job for this annotation

GitHub Actions / clippy

this expression creates a reference which is immediately dereferenced by the compiler

warning: this expression creates a reference which is immediately dereferenced by the compiler --> grovedb/src/merk_cache.rs:118:21 | 118 | &self.version, | ^^^^^^^^^^^^^ help: change this to: `self.version` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
)
};
result_uninit[i].write(merk_ref);
}
Expand All @@ -116,30 +126,32 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {
// N in our case. `mem::transmute` would represent it better, however,
// due to poor support of const generics in stable Rust we bypass
// compile-time size checks with pointer casts.
let result = unsafe { (&result_uninit as *const _ as *const [MerkHandle; N]).read() };
let result = unsafe { (&result_uninit as *const _ as *const [MerkHandle<B>; N]).read() };
mem::forget(result_uninit);

Check warning on line 130 in grovedb/src/merk_cache.rs

View workflow job for this annotation

GitHub Actions / clippy

call to `std::mem::forget` with a value that does not implement `Drop`. Forgetting such a type is the same as dropping it

warning: call to `std::mem::forget` with a value that does not implement `Drop`. Forgetting such a type is the same as dropping it --> grovedb/src/merk_cache.rs:130:9 | 130 | mem::forget(result_uninit); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: argument has type `[std::mem::MaybeUninit<merk_cache::MerkHandle<'_, '_, '_, B>>; N]` --> grovedb/src/merk_cache.rs:130:21 | 130 | mem::forget(result_uninit); | ^^^^^^^^^^^^^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#forget_non_drop = note: `#[warn(clippy::forget_non_drop)]` on by default

Ok(result).wrap_with_cost(cost)
}
}

/// Handle to a cached Merk.
pub(crate) struct MerkHandle<'db, 'c> {
pub(crate) struct MerkHandle<'db, 'c, 'b, B> {

Check warning on line 137 in grovedb/src/merk_cache.rs

View workflow job for this annotation

GitHub Actions / clippy

struct `MerkHandle` is never constructed

warning: struct `MerkHandle` is never constructed --> grovedb/src/merk_cache.rs:137:19 | 137 | pub(crate) struct MerkHandle<'db, 'c, 'b, B> { | ^^^^^^^^^^
path: SubtreePath<'b, B>,
merk: &'c mut TxMerk<'db>,
version: &'db GroveVersion,
updated: &'c mut bool,
}

/// It is allowed to dereference `MerkHandle` to regular Merks but in a
/// non-mutable way since we want to track what have been done to those Merks.
impl<'db, 'c> Deref for MerkHandle<'db, 'c> {
impl<'db, 'c, 'b, B> Deref for MerkHandle<'db, 'c, 'b, B> {
type Target = TxMerk<'db>;

fn deref(&self) -> &Self::Target {
&self.merk

Check warning on line 150 in grovedb/src/merk_cache.rs

View workflow job for this annotation

GitHub Actions / clippy

this expression creates a reference which is immediately dereferenced by the compiler

warning: this expression creates a reference which is immediately dereferenced by the compiler --> grovedb/src/merk_cache.rs:150:9 | 150 | &self.merk | ^^^^^^^^^^ help: change this to: `self.merk` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
}
}

impl<'db, 'c> MerkHandle<'db, 'c> {
impl<'db, 'c, 'b, B> MerkHandle<'db, 'c, 'b, B> {
pub(crate) fn insert(

Check warning on line 155 in grovedb/src/merk_cache.rs

View workflow job for this annotation

GitHub Actions / clippy

associated items `insert` and `new` are never used

warning: associated items `insert` and `new` are never used --> grovedb/src/merk_cache.rs:155:19 | 154 | impl<'db, 'c, 'b, B> MerkHandle<'db, 'c, 'b, B> { | ----------------------------------------------- associated items in this implementation 155 | pub(crate) fn insert( | ^^^^^^ ... 166 | fn new( | ^^^
&mut self,
key: impl AsRef<[u8]>,
Expand All @@ -148,7 +160,20 @@ impl<'db, 'c> MerkHandle<'db, 'c> {
) -> CostResult<(), Error> {
element
.insert(self.merk, key, options, self.version)
.for_ok(|_| todo!())
.for_ok(|_| *self.updated = true)
}

fn new(
path: SubtreePath<'b, B>,
cached_merk: &'c mut CachedMerk<'db>,
version: &'db GroveVersion,
) -> Self {
Self {
path,
merk: &mut cached_merk.merk,
version,
updated: &mut cached_merk.updated,
}
}
}

Expand Down

0 comments on commit eb7b6b2

Please sign in to comment.