Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fominok committed Dec 11, 2024
1 parent f1214f3 commit f382038
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 113 deletions.
138 changes: 79 additions & 59 deletions grovedb/src/element/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ pub const SUM_TREE_COST_SIZE: u32 = SUM_LAYER_COST_SIZE; // 12
/// int 64 sum value
pub type SumValue = i64;

#[cfg(any(feature = "full", feature = "verify"))]
/// if the item is deleted or updated should we cascade
pub type CascadeOnUpdate = bool;

#[cfg(any(feature = "full", feature = "verify"))]
/// Variants of GroveDB stored entities
///
Expand All @@ -92,23 +88,27 @@ pub enum Element {
/// A reference to an object by its path
BidirectionalReference(
ReferencePathType,
Option<(ReferencePathType, CascadeOnUpdate)>,
Option<BackwardReference>,
MaxReferenceHop,
Option<ElementFlags>,
),
/// An ordinary value that has a backwards reference
ItemWithBackwardsReferences(
Vec<u8>,
Vec<(ReferencePathType, CascadeOnUpdate)>,
Option<ElementFlags>,
),
ItemWithBackwardsReferences(Vec<u8>, Vec<BackwardReference>, Option<ElementFlags>),
/// Signed integer value that can be totaled in a sum tree that has a
/// backwards reference
SumItemWithBackwardsReferences(
SumValue,
Vec<(ReferencePathType, CascadeOnUpdate)>,
Option<ElementFlags>,
),
SumItemWithBackwardsReferences(SumValue, Vec<BackwardReference>, Option<ElementFlags>),
}

/// A reference that points to an existing `Element::BidirectionalReference`
/// with a flag indicating whether to issue deletion of that reference chain if
/// the current `Element` no longer exists as a variant with backward reference
/// support or has been deleted completely.
#[derive(Clone, Encode, Decode, PartialEq, Eq, Hash)]
#[cfg_attr(not(any(feature = "full", feature = "visualize")), derive(Debug))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BackwardReference {
pub reference_path: ReferencePathType,
pub cascade_delete: bool,
}

impl fmt::Display for Element {
Expand Down Expand Up @@ -183,34 +183,44 @@ impl fmt::Display for Element {
let backwards_references_info = if backwards_references_count < 4 {
backwards_references
.iter()
.map(|(backwards_reference, cascade_on_update)| {
format!(
"{}:{}",
backwards_reference,
if *cascade_on_update {
"cascade"
} else {
"no cascade"
}
)
})
.map(
|BackwardReference {
reference_path,
cascade_delete,
}| {
format!(
"{}:{}",
reference_path,
if *cascade_delete {
"cascade"
} else {
"no cascade"
}
)
},
)
.collect::<Vec<_>>()
.join("|")
} else {
let first_backwards_references = backwards_references
.iter()
.take(3)
.map(|(backwards_reference, cascade_on_update)| {
format!(
"{}:{}",
backwards_reference,
if *cascade_on_update {
"cascade"
} else {
"no cascade"
}
)
})
.map(
|BackwardReference {
reference_path,
cascade_delete,
}| {
format!(
"{}:{}",
reference_path,
if *cascade_delete {
"cascade"
} else {
"no cascade"
}
)
},
)
.collect::<Vec<_>>()
.join("|");
format!(
Expand All @@ -233,34 +243,44 @@ impl fmt::Display for Element {
let backwards_references_info = if backwards_references_count < 4 {
backwards_references
.iter()
.map(|(backwards_reference, cascade_on_update)| {
format!(
"{}:{}",
backwards_reference,
if *cascade_on_update {
"cascade"
} else {
"no cascade"
}
)
})
.map(
|BackwardReference {
reference_path,
cascade_delete,
}| {
format!(
"{}:{}",
reference_path,
if *cascade_delete {
"cascade"
} else {
"no cascade"
}
)
},
)
.collect::<Vec<_>>()
.join("|")
} else {
let first_backwards_references = backwards_references
.iter()
.take(3)
.map(|(backwards_reference, cascade_on_update)| {
format!(
"{}:{}",
backwards_reference,
if *cascade_on_update {
"cascade"
} else {
"no cascade"
}
)
})
.map(
|BackwardReference {
reference_path,
cascade_delete,
}| {
format!(
"{}:{}",
reference_path,
if *cascade_delete {
"cascade"
} else {
"no cascade"
}
)
},
)
.collect::<Vec<_>>()
.join("|");
format!(
Expand Down
115 changes: 66 additions & 49 deletions grovedb/src/element/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! Implements serialization functions in Element
use bincode::config;
use grovedb_version::{check_grovedb_v0, error::GroveVersionError, version::GroveVersion};
use grovedb_version::{check_grovedb_v0, version::GroveVersion};

#[cfg(any(feature = "full", feature = "verify"))]
use crate::{Element, Error};
Expand Down Expand Up @@ -65,6 +65,71 @@ impl Element {
}
}

/// Wrapper type to alter [Element]'s bincode serialization for variants with
/// backward references, practically ignoring that part.
struct SerializeElementData<'a>(&'a Element);

impl bincode::Encode for SerializeElementData<'_> {
fn encode<E: bincode::enc::Encoder>(
&self,
encoder: &mut E,
) -> Result<(), bincode::error::EncodeError> {
match self.0 {
Element::Item(field_0, field_1) => {
<u32 as ::bincode::Encode>::encode(&(0u32), encoder)?;
::bincode::Encode::encode(field_0, encoder)?;
::bincode::Encode::encode(field_1, encoder)?;
Ok(())
}
Element::Reference(field_0, field_1, field_2) => {
<u32 as ::bincode::Encode>::encode(&(1u32), encoder)?;
::bincode::Encode::encode(field_0, encoder)?;
::bincode::Encode::encode(field_1, encoder)?;
::bincode::Encode::encode(field_2, encoder)?;
Ok(())
}
Element::Tree(field_0, field_1) => {
<u32 as ::bincode::Encode>::encode(&(2u32), encoder)?;
::bincode::Encode::encode(field_0, encoder)?;
::bincode::Encode::encode(field_1, encoder)?;
Ok(())
}
Element::SumItem(field_0, field_1) => {
<u32 as ::bincode::Encode>::encode(&(3u32), encoder)?;
::bincode::Encode::encode(field_0, encoder)?;
::bincode::Encode::encode(field_1, encoder)?;
Ok(())
}
Element::SumTree(field_0, field_1, field_2) => {
<u32 as ::bincode::Encode>::encode(&(4u32), encoder)?;
::bincode::Encode::encode(field_0, encoder)?;
::bincode::Encode::encode(field_1, encoder)?;
::bincode::Encode::encode(field_2, encoder)?;
Ok(())
}
Element::BidirectionalReference(field_0, _, field_2, field_3) => {
<u32 as ::bincode::Encode>::encode(&(5u32), encoder)?;
::bincode::Encode::encode(field_0, encoder)?;
::bincode::Encode::encode(field_2, encoder)?;
::bincode::Encode::encode(field_3, encoder)?;
Ok(())
}
Element::ItemWithBackwardsReferences(field_0, _, field_2) => {
<u32 as ::bincode::Encode>::encode(&(6u32), encoder)?;
::bincode::Encode::encode(field_0, encoder)?;
::bincode::Encode::encode(field_2, encoder)?;
Ok(())
}
Element::SumItemWithBackwardsReferences(field_0, _, field_2) => {
<u32 as ::bincode::Encode>::encode(&(7u32), encoder)?;
::bincode::Encode::encode(field_0, encoder)?;
::bincode::Encode::encode(field_2, encoder)?;
Ok(())
}
}
}
}

#[cfg(feature = "full")]
#[cfg(test)]
mod tests {
Expand Down Expand Up @@ -192,51 +257,3 @@ mod tests {
);
}
}

/// Wrapper type to alter [Element]'s bincode serialization for variants with
/// backward references, practically ignoring that part.
struct SerializeElementData<'a>(&'a Element);

impl bincode::Encode for SerializeElementData<'_> {
fn encode<E: bincode::enc::Encoder>(
&self,
encoder: &mut E,
) -> Result<(), bincode::error::EncodeError> {
match self.0 {
Element::Item(data, flags) | Element::ItemWithBackwardsReferences(data, _, flags) => {
<u32 as bincode::Encode>::encode(&(0u32), encoder)?;
bincode::Encode::encode(data, encoder)?;
bincode::Encode::encode(flags, encoder)?;
Ok(())
}
Element::Reference(ref_path, max_hops, flags)
| Element::BidirectionalReference(ref_path, _, max_hops, flags) => {
<u32 as bincode::Encode>::encode(&(1u32), encoder)?;
bincode::Encode::encode(ref_path, encoder)?;
bincode::Encode::encode(max_hops, encoder)?;
bincode::Encode::encode(flags, encoder)?;
Ok(())
}
Element::Tree(root_key, flags) => {
<u32 as bincode::Encode>::encode(&(2u32), encoder)?;
bincode::Encode::encode(root_key, encoder)?;
bincode::Encode::encode(flags, encoder)?;
Ok(())
}
Element::SumItem(sum_value, flags)
| Element::SumItemWithBackwardsReferences(sum_value, _, flags) => {
<u32 as bincode::Encode>::encode(&(3u32), encoder)?;
bincode::Encode::encode(sum_value, encoder)?;
bincode::Encode::encode(flags, encoder)?;
Ok(())
}
Element::SumTree(root_key, sum_value, flags) => {
<u32 as bincode::Encode>::encode(&(4u32), encoder)?;
bincode::Encode::encode(root_key, encoder)?;
bincode::Encode::encode(sum_value, encoder)?;
bincode::Encode::encode(flags, encoder)?;
Ok(())
}
}
}
}
4 changes: 4 additions & 0 deletions grovedb/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ pub enum Error {
#[error("corrupted referenced path key not found: {0}")]
CorruptedReferencePathParentLayerNotFound(String),

/// Bidirectional references rule was violated
#[error("bidirectional reference rule violation: {0}")]
BidirectionalReferenceRule(String),

/// The invalid parent layer path represents a logical error from the client
/// library
#[error("invalid parent layer path: {0}")]
Expand Down
Loading

0 comments on commit f382038

Please sign in to comment.