Skip to content

Commit b38d346

Browse files
committed
WIP: Try another approach, no luck yet
1 parent f01e5c8 commit b38d346

File tree

4 files changed

+45
-39
lines changed

4 files changed

+45
-39
lines changed

src/stored.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ pub trait Store<V> {
2121
hash_idx: Idx,
2222
) -> Result<NodeHash, Self::Error>;
2323

24-
fn get_node(&self, hash_idx: Idx) -> Result<Node<&Branch<Idx>, &Leaf<V>>, Self::Error>;
24+
fn get_node<'s>(
25+
&'s self,
26+
hash_idx: Idx,
27+
) -> Result<Node<&'s Branch<'s, Idx>, &'s Leaf<V>>, Self::Error>;
2528
}
2629

2730
impl<V, S: Store<V>> Store<V> for &S {

src/stored/merkle.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use bumpalo::Bump;
55
use ouroboros::self_referencing;
66

77
use crate::{
8-
transaction::nodes::{NodeRef, TrieRoot},
8+
transaction::nodes::{NodeRef, PrefixesBuffer, TrieRoot},
99
Branch, Leaf, PortableHash, PortableHasher, TrieError,
1010
};
1111

@@ -20,12 +20,14 @@ type Result<T, E = TrieError> = core::result::Result<T, E>;
2020
#[derive(Clone, Debug, PartialEq, Eq)]
2121
pub struct Snapshot<V> {
2222
/// The last branch is the root of the trie if it exists.
23-
branches: Box<[Branch<Idx>]>,
23+
branches: Box<[Branch<'static, Idx>]>,
2424
/// A Snapshot containing only
2525
leaves: Box<[Leaf<V>]>,
2626

2727
// we only store the hashes of the nodes that have not been visited.
2828
unvisited_nodes: Box<[NodeHash]>,
29+
30+
prefixies_buffer: PrefixesBuffer,
2931
}
3032

3133
impl<V: PortableHash> Snapshot<V> {

src/transaction.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use self::nodes::{
2222
pub struct Transaction<S, V> {
2323
pub data_store: S,
2424
current_root: TrieRoot<NodeRef<V>>,
25-
prefixes_buffer: PrefixesBuffer,
2625
}
2726

2827
impl<Db: DatabaseSet<V>, V: Clone + PortableHash> Transaction<SnapshotBuilder<Db, V>, V> {
@@ -44,7 +43,6 @@ impl<Db: DatabaseSet<V>, V: Clone + PortableHash> Transaction<SnapshotBuilder<Db
4443
left,
4544
right,
4645
mask: branch.mask,
47-
prior_word: branch.prior_word,
4846
prefix: branch.prefix.clone(),
4947
};
5048

@@ -397,6 +395,7 @@ impl<S: Store<V>, V> Transaction<S, V> {
397395
mask: new_branch.mask,
398396
prior_word: new_branch.prior_word,
399397
prefix: new_branch.prefix.clone(),
398+
prefix,
400399
}));
401400

402401
continue;
@@ -549,6 +548,7 @@ impl<Db, V: PortableHash + Clone> Transaction<SnapshotBuilder<Db, V>, V> {
549548
Transaction {
550549
current_root: builder.trie_root(),
551550
data_store: builder,
551+
prefixes_buffer: builder.prefixes_buffer,
552552
}
553553
}
554554
}
@@ -582,6 +582,7 @@ impl<V: PortableHash + Clone> Transaction<Snapshot<V>, V> {
582582
Ok(Transaction {
583583
current_root: snapshot.trie_root()?,
584584
data_store: snapshot,
585+
prefixes_buffer: snapshot.prefixes_buffer,
585586
})
586587
}
587588
}

src/transaction/nodes.rs

+34-34
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,20 @@ pub enum Node<B, L> {
7474
/// When executing against a `SnapshotBuilder`, it's a reference to a `NodeHash`,
7575
/// which can in turn be used to retrieve the `Node`.
7676
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
77-
pub enum NodeRef<V> {
78-
ModBranch(Box<Branch<Self>>),
77+
pub enum NodeRef<'s, V> {
78+
ModBranch(Box<Branch<'s, Self>>),
7979
ModLeaf(Box<Leaf<V>>),
8080
Stored(stored::Idx),
8181
}
8282

83-
impl<V> NodeRef<V> {
83+
impl<V> NodeRef<'_, V> {
8484
#[inline(always)]
8585
pub fn temp_null_stored() -> Self {
8686
NodeRef::Stored(u32::MAX)
8787
}
8888
}
8989

90-
impl<V> fmt::Debug for NodeRef<V> {
90+
impl<V> fmt::Debug for NodeRef<'_, V> {
9191
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9292
match self {
9393
Self::ModBranch(b) => f.debug_tuple("ModBranch").field(b).finish(),
@@ -97,7 +97,7 @@ impl<V> fmt::Debug for NodeRef<V> {
9797
}
9898
}
9999

100-
impl<V> From<Box<Branch<NodeRef<V>>>> for NodeRef<V> {
100+
impl<'s, V> From<Box<Branch<'s, NodeRef<'s, V>>>> for NodeRef<'s, V> {
101101
#[inline]
102102
fn from(branch: Box<Branch<NodeRef<V>>>) -> Self {
103103
NodeRef::ModBranch(branch)
@@ -263,7 +263,7 @@ mod tests {
263263
}
264264
}
265265

266-
pub struct Prefix {
266+
pub struct PrefixBufferRef {
267267
/// This value will be 0 if the branch occurs in the first word of the hash key.
268268
/// The value is the prior word if the branches parent's word index no more than 1 less.
269269
/// If the parent's word index is more than 1 word prior,
@@ -272,7 +272,7 @@ pub struct Prefix {
272272
prior_word_or_prefix_idx: u32,
273273
}
274274

275-
impl Prefix {
275+
impl PrefixBufferRef {
276276
pub fn get_prefix<'s, 'txn: 's>(
277277
&'s self,
278278
prefixies: &'txn PrefixesBuffer,
@@ -296,7 +296,7 @@ impl Prefix {
296296
}
297297
}
298298

299-
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
299+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
300300
pub struct PrefixesBuffer {
301301
buffer: Vec<u32>,
302302
}
@@ -318,21 +318,32 @@ impl PrefixesBuffer {
318318
}
319319
}
320320

321+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
322+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
323+
pub enum PrefixCow<'a> {
324+
StartOfKey,
325+
PriorWord(u32),
326+
Segment(&'a [u32]),
327+
SegmentOwned(Box<[u32]>),
328+
}
329+
330+
/// A branch node in the trie.
331+
/// `NR` is the type of the node references.
332+
/// `PR` is the type of reference to the prefix.
321333
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
322334
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
323-
pub struct Branch<NR> {
335+
pub struct Branch<'s, NR> {
324336
pub left: NR,
325337
pub right: NR,
326338
pub mask: BranchMask,
327-
pub prefix: Prefix,
339+
pub prefix: PrefixCow<'s>,
328340
}
329341

330-
impl<NR> fmt::Debug for Branch<NR> {
342+
impl<NR> fmt::Debug for Branch<'_, NR> {
331343
#[inline]
332344
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
333345
f.debug_struct("Branch")
334346
.field("mask", &self.mask)
335-
.field("prior_word", &self.prior_word)
336347
.field("prefix", &self.prefix)
337348
.finish()
338349
}
@@ -359,7 +370,7 @@ pub enum KeyPositionAdjacent {
359370
PrefixVec(usize),
360371
}
361372

362-
impl<NR> Branch<NR> {
373+
impl<NR> Branch<NR, PrefixCow<'a>> {
363374
/// Returns the position of the key relative to the branch.
364375
#[inline(always)]
365376
pub fn key_position(&self, key_hash: &KeyHash) -> KeyPosition {
@@ -424,19 +435,7 @@ impl<NR> Branch<NR> {
424435
}
425436
}
426437

427-
impl<V> Branch<NodeRef<V>> {
428-
pub(crate) fn from_stored(branch: &Branch<stored::Idx>) -> Branch<NodeRef<V>> {
429-
Branch {
430-
left: NodeRef::Stored(branch.left),
431-
right: NodeRef::Stored(branch.right),
432-
mask: branch.mask,
433-
prior_word: branch.prior_word,
434-
// TODO remove the clone
435-
// Maybe use a AsRef<[u32]> instead of Box<[u32]>
436-
prefix: branch.prefix.clone(),
437-
}
438-
}
439-
438+
impl<V, PR> Branch<NodeRef<V>, PR> {
440439
/// A wrapper around `new_at_branch_ret` which returns nothing.
441440
/// This exists to aid compiler inlining.
442441
///
@@ -591,17 +590,19 @@ impl<V> Branch<NodeRef<V>> {
591590

592591
debug_assert!(new_leaf.key_hash.0[..word_idx] == old_leaf.as_ref().key_hash.0[..word_idx]);
593592

594-
let prior_word_idx = word_idx.saturating_sub(1);
595-
let prefix = new_leaf.key_hash.0[prefix_start_idx..prior_word_idx].into();
596-
let prior_word = if word_idx == 0 {
597-
0
598-
} else {
593+
let prefix = if word_idx == 0 {
594+
PrefixCow::StartOfKey
595+
} else if prefix_start_idx == word_idx {
596+
let prior_word_idx = word_idx - 1;
599597
debug_assert_eq!(
600598
new_leaf.key_hash.0[prior_word_idx],
601599
old_leaf.as_ref().key_hash.0[prior_word_idx]
602600
);
603-
604-
new_leaf.key_hash.0[prior_word_idx]
601+
PrefixCow::PriorWord(new_leaf.key_hash.0[prior_word_idx])
602+
} else if prefix_start_idx == word_idx - 1 {
603+
PrefixCow::PriorWord(new_leaf.key_hash.0[word_idx - 1])
604+
} else {
605+
PrefixCow::Segment(&new_leaf.key_hash.0[prefix_start_idx..word_idx])
605606
};
606607

607608
let mask = BranchMask::new(word_idx as u32, a, b);
@@ -628,7 +629,6 @@ impl<V> Branch<NodeRef<V>> {
628629
left,
629630
right,
630631
mask,
631-
prior_word,
632632
prefix,
633633
}),
634634
// TODO use an enum

0 commit comments

Comments
 (0)