From 8664b723330cc3850edbebd5f336b982f29ed23c Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Mon, 24 Jun 2024 23:27:35 +0300 Subject: [PATCH] better internal error fix --- grovedb/src/element/query.rs | 4 +- grovedb/src/util.rs | 183 +++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 2 deletions(-) diff --git a/grovedb/src/element/query.rs b/grovedb/src/element/query.rs index eba5ae1f..0114a0a8 100644 --- a/grovedb/src/element/query.rs +++ b/grovedb/src/element/query.rs @@ -42,7 +42,6 @@ use grovedb_path::SubtreePath; #[cfg(feature = "full")] use grovedb_storage::{rocksdb_storage::RocksDbStorage, RawIterator, StorageContext}; -use crate::query_result_type::Path; #[cfg(feature = "full")] use crate::{ element::helpers::raw_decode, @@ -56,6 +55,7 @@ use crate::{ util::{merk_optional_tx, storage_context_optional_tx}, Error, PathQuery, TransactionArg, }; +use crate::{query_result_type::Path, util::merk_optional_tx_internal_error}; #[cfg(any(feature = "full", feature = "verify"))] use crate::{Element, SizedQuery}; @@ -563,7 +563,7 @@ impl Element { if !item.is_range() { // this is a query on a key if let QueryItem::Key(key) = item { - let element_res = merk_optional_tx!( + let element_res = merk_optional_tx_internal_error!( &mut cost, storage, subtree_path, diff --git a/grovedb/src/util.rs b/grovedb/src/util.rs index cbedc9af..d05f2396 100644 --- a/grovedb/src/util.rs +++ b/grovedb/src/util.rs @@ -149,6 +149,117 @@ macro_rules! storage_context_with_parent_optional_tx { }; } +/// Macro to execute same piece of code on different storage contexts +/// (transactional or not) using path argument. +macro_rules! storage_context_with_parent_optional_tx_internal_error { + ( + &mut $cost:ident, + $db:expr, + $path:expr, + $batch:expr, + $transaction:ident, + $storage:ident, + $root_key:ident, + $is_sum_tree:ident, + { $($body:tt)* } + ) => { + { + use ::grovedb_storage::Storage; + if let Some(tx) = $transaction { + let $storage = $db + .get_transactional_storage_context($path.clone(), $batch, tx) + .unwrap_add_cost(&mut $cost); + if let Some((parent_path, parent_key)) = $path.derive_parent() { + let parent_storage = $db + .get_transactional_storage_context(parent_path, $batch, tx) + .unwrap_add_cost(&mut $cost); + let result = Element::get_from_storage(&parent_storage, parent_key) + .map_err(|e| { + Error::PathParentLayerNotFound( + format!( + "could not get key for parent of subtree optional on tx: {}", + e + ) + ) + }).unwrap_add_cost(&mut $cost); + match result { + Ok(element) => { + match element { + Element::Tree(root_key, _) => { + let $root_key = root_key; + let $is_sum_tree = false; + $($body)* + } + Element::SumTree(root_key, ..) => { + let $root_key = root_key; + let $is_sum_tree = true; + $($body)* + } + _ => { + return Err(Error::CorruptedData( + "parent is not a tree" + .to_owned(), + )).wrap_with_cost($cost); + } + } + }, + Err(e) => Err(e), + } + } else { + return Err(Error::CorruptedData( + "path is empty".to_owned(), + )).wrap_with_cost($cost); + } + } else { + let $storage = $db + .get_storage_context($path.clone(), $batch).unwrap_add_cost(&mut $cost); + if let Some((parent_path, parent_key)) = $path.derive_parent() { + let parent_storage = $db.get_storage_context( + parent_path, + $batch + ).unwrap_add_cost(&mut $cost); + let result = Element::get_from_storage(&parent_storage, parent_key) + .map_err(|e| { + Error::PathParentLayerNotFound( + format!( + "could not get key for parent of subtree optional no tx: {}", + e + ) + ) + }).unwrap_add_cost(&mut $cost); + match result { + Ok(element) => { + match element { + Element::Tree(root_key, _) => { + let $root_key = root_key; + let $is_sum_tree = false; + $($body)* + } + Element::SumTree(root_key, ..) => { + let $root_key = root_key; + let $is_sum_tree = true; + $($body)* + } + _ => { + return Err(Error::CorruptedData( + "parent is not a tree" + .to_owned(), + )).wrap_with_cost($cost); + } + } + }, + Err(e) => Err(e), + } + } else { + return Err(Error::CorruptedData( + "path is empty".to_owned(), + )).wrap_with_cost($cost); + } + } + } + }; +} + /// Macro to execute same piece of code on different storage contexts with /// empty prefix. macro_rules! meta_storage_context_optional_tx { @@ -245,6 +356,76 @@ macro_rules! merk_optional_tx { }; } +/// Macro to execute same piece of code on Merk with varying storage +/// contexts. +macro_rules! merk_optional_tx_internal_error { + ( + &mut $cost:ident, + $db:expr, + $path:expr, + $batch:expr, + $transaction:ident, + $subtree:ident, + { $($body:tt)* } + ) => { + if $path.is_root() { + use crate::util::storage_context_optional_tx; + storage_context_optional_tx!( + $db, + ::grovedb_path::SubtreePath::empty(), + $batch, + $transaction, + storage, + { + let $subtree = cost_return_on_error!( + &mut $cost, + ::grovedb_merk::Merk::open_base( + storage.unwrap_add_cost(&mut $cost), + false, + Some(&Element::value_defined_cost_for_serialized_value) + ).map(|merk_res| + merk_res + .map_err(|_| crate::Error::CorruptedData( + "cannot open a subtree".to_owned() + )) + ) + ); + $($body)* + }) + } else { + use crate::util::storage_context_with_parent_optional_tx_internal_error; + storage_context_with_parent_optional_tx_internal_error!( + &mut $cost, + $db, + $path, + $batch, + $transaction, + storage, + root_key, + is_sum_tree, + { + #[allow(unused_mut)] + let mut $subtree = cost_return_on_error!( + &mut $cost, + ::grovedb_merk::Merk::open_layered_with_root_key( + storage, + root_key, + is_sum_tree, + Some(&Element::value_defined_cost_for_serialized_value), + ).map(|merk_res| + merk_res + .map_err(|_| crate::Error::CorruptedData( + "cannot open a subtree".to_owned() + )) + ) + ); + $($body)* + } + ) + } + }; +} + /// Macro to execute same piece of code on Merk with varying storage /// contexts. macro_rules! merk_optional_tx_path_not_empty { @@ -331,8 +512,10 @@ macro_rules! root_merk_optional_tx { } pub(crate) use merk_optional_tx; +pub(crate) use merk_optional_tx_internal_error; pub(crate) use merk_optional_tx_path_not_empty; pub(crate) use meta_storage_context_optional_tx; pub(crate) use root_merk_optional_tx; pub(crate) use storage_context_optional_tx; pub(crate) use storage_context_with_parent_optional_tx; +pub(crate) use storage_context_with_parent_optional_tx_internal_error;