Skip to content

Commit ee3ca3a

Browse files
[commonware-storage/mutable] Make mutable MMR use the memory efficient index (#680)
1 parent c281969 commit ee3ca3a

3 files changed

Lines changed: 220 additions & 58 deletions

File tree

storage/src/index/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,24 @@ mod tests {
205205
values.sort();
206206
assert_eq!(values, vec![0, 2]);
207207
}
208+
209+
#[test_traced]
210+
fn test_index_mutate_through_iterator() {
211+
let (_, context, _) = Executor::default();
212+
let mut index = Index::init(context.clone(), TwoCap);
213+
214+
index.insert(b"key", 1);
215+
index.insert(b"key", 2);
216+
index.insert(b"key", 3);
217+
218+
for value in index.get_mut(b"key") {
219+
// Mutate the value
220+
*value += 10;
221+
}
222+
223+
assert_eq!(
224+
index.get(b"key").copied().collect::<Vec<_>>(),
225+
vec![11, 13, 12]
226+
);
227+
}
208228
}

storage/src/index/storage.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,25 @@ pub struct ValueIterator<'a, V> {
1818
next: Option<&'a Record<V>>,
1919
}
2020

21+
// An iterator over all values associated with a translated key, allowing for mutation.
22+
pub struct MutableValueIterator<'a, V> {
23+
next: Option<&'a mut Record<V>>,
24+
}
25+
2126
impl<V> ValueIterator<'_, V> {
2227
/// Create a `ValueIterator` that returns no items.
2328
fn empty() -> Self {
2429
ValueIterator { next: None }
2530
}
2631
}
2732

33+
impl<V> MutableValueIterator<'_, V> {
34+
/// Create a `MutableValueIterator` that returns no items.
35+
fn empty() -> Self {
36+
MutableValueIterator { next: None }
37+
}
38+
}
39+
2840
impl<'a, V> Iterator for ValueIterator<'a, V> {
2941
type Item = &'a V;
3042

@@ -40,10 +52,29 @@ impl<'a, V> Iterator for ValueIterator<'a, V> {
4052
}
4153
}
4254

55+
impl<'a, V> Iterator for MutableValueIterator<'a, V> {
56+
type Item = &'a mut V;
57+
58+
fn next(&mut self) -> Option<Self::Item> {
59+
match self.next.take() {
60+
Some(next) => {
61+
let loc = &mut next.value;
62+
self.next = next.next.as_deref_mut();
63+
Some(loc)
64+
}
65+
None => None,
66+
}
67+
}
68+
}
69+
4370
impl<V> Record<V> {
4471
fn iter(&self) -> ValueIterator<V> {
4572
ValueIterator { next: Some(self) }
4673
}
74+
75+
fn iter_mut(&mut self) -> MutableValueIterator<V> {
76+
MutableValueIterator { next: Some(self) }
77+
}
4778
}
4879

4980
/// An index that maps translated keys to values.
@@ -113,6 +144,15 @@ impl<T: Translator, V> Index<T, V> {
113144
}
114145
}
115146

147+
/// Retrieve all values associated with a translated key, allowing for mutation.
148+
pub fn get_mut(&mut self, key: &[u8]) -> MutableValueIterator<V> {
149+
let translated_key = self.translator.transform(key);
150+
match self.map.get_mut(&translated_key) {
151+
Some(head) => head.iter_mut(),
152+
None => MutableValueIterator::empty(),
153+
}
154+
}
155+
116156
/// Remove values associated with the key that match the `prune` predicate.
117157
///
118158
/// If this function is never called, the amount of memory used by old values will grow

0 commit comments

Comments
 (0)