Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fominok committed Dec 10, 2024
1 parent 919ed0e commit 5ff62ec
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 90 deletions.
10 changes: 5 additions & 5 deletions grovedb-version/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::version::GroveVersion;
use version::GroveVersion;

pub mod error;
pub mod version;
Expand All @@ -8,7 +8,7 @@ macro_rules! check_grovedb_v0_with_cost {
($method:expr, $version:expr) => {{
const EXPECTED_VERSION: u16 = 0;
if $version != EXPECTED_VERSION {
return Err(GroveVersionError::UnknownVersionMismatch {
return Err($crate::error::GroveVersionError::UnknownVersionMismatch {
method: $method.to_string(),
known_versions: vec![EXPECTED_VERSION],
received: $version,
Expand All @@ -24,7 +24,7 @@ macro_rules! check_grovedb_v0 {
($method:expr, $version:expr) => {{
const EXPECTED_VERSION: u16 = 0;
if $version != EXPECTED_VERSION {
return Err(GroveVersionError::UnknownVersionMismatch {
return Err($crate::error::GroveVersionError::UnknownVersionMismatch {
method: $method.to_string(),
known_versions: vec![EXPECTED_VERSION],
received: $version,
Expand All @@ -39,7 +39,7 @@ macro_rules! check_merk_v0_with_cost {
($method:expr, $version:expr) => {{
const EXPECTED_VERSION: u16 = 0;
if $version != EXPECTED_VERSION {
return Err(GroveVersionError::UnknownVersionMismatch {
return Err($crate::error::GroveVersionError::UnknownVersionMismatch {
method: $method.to_string(),
known_versions: vec![EXPECTED_VERSION],
received: $version,
Expand All @@ -55,7 +55,7 @@ macro_rules! check_merk_v0 {
($method:expr, $version:expr) => {{
const EXPECTED_VERSION: u16 = 0;
if $version != EXPECTED_VERSION {
return Err(GroveVersionError::UnknownVersionMismatch {
return Err($crate::error::GroveVersionError::UnknownVersionMismatch {
method: $method.to_string(),
known_versions: vec![EXPECTED_VERSION],
received: $version,
Expand Down
64 changes: 25 additions & 39 deletions grovedb/src/merk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type TxMerk<'db> = Merk<PrefixedRocksDbTransactionContext<'db>>;
/// Structure to keep subtrees open in memory for repeated access.
pub(crate) struct MerkCache<'db, 'b, B: AsRef<[u8]>> {
db: &'db GroveDb,
version: &'db GroveVersion,
pub(crate) version: &'db GroveVersion,
batch: Box<StorageBatch>,
tx: &'db Transaction<'db>,
merks: UnsafeCell<BTreeMap<SubtreePathBuilder<'b, B>, Box<(Cell<bool>, TxMerk<'db>)>>>,

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

View workflow job for this annotation

GitHub Actions / clippy

very complex type used. Consider factoring parts into `type` definitions

warning: very complex type used. Consider factoring parts into `type` definitions --> grovedb/src/merk_cache.rs:28:12 | 28 | merks: UnsafeCell<BTreeMap<SubtreePathBuilder<'b, B>, Box<(Cell<bool>, TxMerk<'db>)>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity = note: `#[warn(clippy::type_complexity)]` on by default
Expand All @@ -44,11 +44,7 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {
}
}

/// Returns cached Merk reference or opens one if needed.
///
/// # Panics
/// Borrowing one Merk several times will cause a panic, previous borrow
/// shall reach end of the scope or to be `drop`ped manually.
/// Gets a smart pointer to a cached Merk or opens one if needed.
pub(crate) fn get_merk<'c>(
&'c self,
path: SubtreePathBuilder<'b, B>,
Expand Down Expand Up @@ -82,15 +78,9 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {
self.version
)
);
e.insert(Box::new((true.into(), merk)))
}
Entry::Occupied(e) => {
if e.get().0.get() {
e.into_mut()
} else {
panic!("Double borrow of a cached Merk")
}
e.insert(Box::new((false.into(), merk)))
}
Entry::Occupied(e) => e.into_mut(),
};

let taken_handle_ref: *const Cell<bool> = &boxed_flag_merk.0 as *const _;
Expand Down Expand Up @@ -158,14 +148,14 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {
);
cost_return_on_error!(
&mut cost,
GroveDb::update_tree_item_preserve_flag(
&mut parent_merk,
parent_merk.for_merk(|m| GroveDb::update_tree_item_preserve_flag(
m,
parent_key,
root_key,
root_hash,
sum,
self.version,
)
))
);
}
}
Expand All @@ -176,27 +166,19 @@ impl<'db, 'b, B: AsRef<[u8]>> MerkCache<'db, 'b, B> {

/// Wrapper over `Merk` tree to manage unqiue borrow dynamically.
pub(crate) struct MerkHandle<'db, 'c> {
merk: &'c mut TxMerk<'db>,
merk: *mut TxMerk<'db>,
taken_handle: &'c Cell<bool>,
}

impl<'db, 'c> Deref for MerkHandle<'db, 'c> {
type Target = TxMerk<'db>;

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

impl<'db, 'c> DerefMut for MerkHandle<'db, 'c> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.merk
}
}

impl<'db, 'c> Drop for MerkHandle<'db, 'c> {
fn drop(&mut self) {
impl<'db, 'c> MerkHandle<'db, 'c> {

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

View workflow job for this annotation

GitHub Actions / clippy

the following explicit lifetimes could be elided: 'c

warning: the following explicit lifetimes could be elided: 'c --> grovedb/src/merk_cache.rs:173:11 | 173 | impl<'db, 'c> MerkHandle<'db, 'c> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 173 - impl<'db, 'c> MerkHandle<'db, 'c> { 173 + impl<'db> MerkHandle<'db, '_> { |
pub(crate) fn for_merk<T>(&mut self, f: impl FnOnce(&mut TxMerk<'db>) -> T) -> T {
if self.taken_handle.get() {
panic!("Attempt to have double &mut borrow on Merk");
}
self.taken_handle.set(true);
let result = f(unsafe { self.merk.as_mut().expect("pointer to Box cannot be null") });
self.taken_handle.set(false);
result
}
}

Expand All @@ -221,14 +203,20 @@ mod tests {

let cache = MerkCache::new(&db, &tx, version);

cache
let mut merk1 = cache
.get_merk(SubtreePath::empty().derive_owned())
.unwrap()
.unwrap();
cache
let mut merk2 = cache
.get_merk(SubtreePath::empty().derive_owned())
.unwrap()
.unwrap();

merk1.for_merk(|_m1| {
merk2.for_merk(|_m2| {
// this shouldn't happen
})
});
}

#[test]
Expand Down Expand Up @@ -259,9 +247,7 @@ mod tests {

let mut merk = cache.get_merk(path.derive_owned()).unwrap().unwrap();

item.insert(&mut merk, b"k1", None, &version)
.unwrap()
.unwrap();
merk.for_merk(|m| item.insert(m, b"k1", None, &version).unwrap().unwrap());

drop(merk);

Expand Down
61 changes: 27 additions & 34 deletions grovedb/src/operations/insert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ use grovedb_costs::{
cost_return_on_error, cost_return_on_error_no_add, CostResult, CostsExt, OperationCost,
};
use grovedb_merk::{tree::NULL_HASH, Merk, MerkOptions};

Check warning on line 8 in grovedb/src/operations/insert/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `Merk`

warning: unused import: `Merk` --> grovedb/src/operations/insert/mod.rs:8:37 | 8 | use grovedb_merk::{tree::NULL_HASH, Merk, MerkOptions}; | ^^^^
use grovedb_path::SubtreePath;
use grovedb_path::{SubtreePath, SubtreePathBuilder};

Check warning on line 9 in grovedb/src/operations/insert/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `SubtreePathBuilder`

warning: unused import: `SubtreePathBuilder` --> grovedb/src/operations/insert/mod.rs:9:33 | 9 | use grovedb_path::{SubtreePath, SubtreePathBuilder}; | ^^^^^^^^^^^^^^^^^^
use grovedb_storage::{rocksdb_storage::PrefixedRocksDbTransactionContext, Storage, StorageBatch};

Check warning on line 10 in grovedb/src/operations/insert/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused imports: `StorageBatch` and `rocksdb_storage::PrefixedRocksDbTransactionContext`

warning: unused imports: `StorageBatch` and `rocksdb_storage::PrefixedRocksDbTransactionContext` --> grovedb/src/operations/insert/mod.rs:10:23 | 10 | use grovedb_storage::{rocksdb_storage::PrefixedRocksDbTransactionContext, Storage, StorageBatch}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
use grovedb_version::{
check_grovedb_v0_with_cost, error::GroveVersionError, version::GroveVersion,

Check warning on line 12 in grovedb/src/operations/insert/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `error::GroveVersionError`

warning: unused import: `error::GroveVersionError` --> grovedb/src/operations/insert/mod.rs:12:33 | 12 | check_grovedb_v0_with_cost, error::GroveVersionError, version::GroveVersion, | ^^^^^^^^^^^^^^^^^^^^^^^^
};

use crate::{
merk_cache::MerkCache, reference_path::path_from_reference_path_type, util::TxRef, Element,
Error, GroveDb, Transaction, TransactionArg,
merk_cache::{MerkCache, MerkHandle},
reference_path::path_from_reference_path_type,

Check warning on line 17 in grovedb/src/operations/insert/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

unused imports: `Transaction` and `reference_path::path_from_reference_path_type`

warning: unused imports: `Transaction` and `reference_path::path_from_reference_path_type` --> grovedb/src/operations/insert/mod.rs:17:5 | 17 | reference_path::path_from_reference_path_type, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 18 | util::{self, TxRef}, 19 | Element, Error, GroveDb, Transaction, TransactionArg, | ^^^^^^^^^^^
util::{self, TxRef},
Element, Error, GroveDb, Transaction, TransactionArg,
};
#[derive(Clone)]
/// Insert options
Expand Down Expand Up @@ -100,15 +102,15 @@ impl GroveDb {
/// first make sure other merk exist
/// if it exists, then create merk to be inserted, and get root hash
/// we only care about root hash of merk to be inserted
fn add_element_on_transaction<'db, 'b, B: AsRef<[u8]>>(
fn add_element_on_transaction<'db, 'b, 'c, B: AsRef<[u8]>>(
&'db self,
path: SubtreePath<'b, B>,
key: &[u8],
element: Element,
options: InsertOptions,
merk_cache: &MerkCache<'db, 'b, B>,
merk_cache: &'c MerkCache<'db, 'b, B>,
grove_version: &GroveVersion,
) -> CostResult<Merk<PrefixedRocksDbTransactionContext<'db>>, Error> {
) -> CostResult<MerkHandle<'db, 'c>, Error> {
check_grovedb_v0_with_cost!(
"add_element_on_transaction",
grove_version
Expand All @@ -128,12 +130,12 @@ impl GroveDb {
let maybe_element_bytes = cost_return_on_error!(
&mut cost,
subtree_to_insert_into
.get(
.for_merk(|m| m.get(
key,
true,
Some(&Element::value_defined_cost_for_serialized_value),
grove_version,
)
))
.map_err(|e| Error::CorruptedData(e.to_string()))
);
if let Some(element_bytes) = maybe_element_bytes {
Expand Down Expand Up @@ -164,24 +166,16 @@ impl GroveDb {

match element {
Element::Reference(ref reference_path, ..) => {
let path = path.to_vec(); // TODO: need for support for references in path library
let reference_path = cost_return_on_error!(
let referenced_item: Element = cost_return_on_error!(
&mut cost,
path_from_reference_path_type(reference_path.clone(), &path, Some(key))
.wrap_with_cost(OperationCost::default())
util::follow_reference(
merk_cache,
path.derive_owned(),
key,
reference_path.clone()
)
);

let referenced_item: Element = todo!();
// cost_return_on_error!(
// &mut cost,
// self.follow_reference(
// reference_path.as_slice().into(),
// false,
// transaction,
// grove_version
// )
// );

if matches!(
referenced_item,
Element::Tree(_, _) | Element::SumTree(_, _, _)
Expand All @@ -197,13 +191,13 @@ impl GroveDb {

cost_return_on_error!(
&mut cost,
element.insert_reference(
&mut subtree_to_insert_into,
subtree_to_insert_into.for_merk(|m| element.insert_reference(
m,
key,
referenced_element_value_hash,
Some(options.as_merk_options()),
grove_version,
)
))
);
}
Element::Tree(ref value, _) | Element::SumTree(ref value, ..) => {
Expand All @@ -215,31 +209,30 @@ impl GroveDb {
} else {
cost_return_on_error!(
&mut cost,
element.insert_subtree(
&mut subtree_to_insert_into,
subtree_to_insert_into.for_merk(|m| element.insert_subtree(
m,
key,
NULL_HASH,
Some(options.as_merk_options()),
grove_version
)
))
);
}
}
_ => {
cost_return_on_error!(
&mut cost,
element.insert(
&mut subtree_to_insert_into,
subtree_to_insert_into.for_merk(|m| element.insert(
m,
key,
Some(options.as_merk_options()),
grove_version
)
))
);
}
}

// Ok(subtree_to_insert_into).wrap_with_cost(cost)
todo!()
Ok(subtree_to_insert_into).wrap_with_cost(cost)
}

/// Inserts an element at the specified path and key if it does not already
Expand Down
Loading

0 comments on commit 5ff62ec

Please sign in to comment.