Skip to main content

commonware_storage/index/partitioned/
ordered.rs

1//! The ordered variant of a partitioned index.
2
3use crate::{
4    index::{
5        ordered::Index as OrderedIndex, partitioned::partition_index_and_sub_key,
6        Ordered as OrderedTrait, Unordered as UnorderedTrait,
7    },
8    translator::Translator,
9};
10use commonware_runtime::Metrics;
11
12/// A partitioned index that maps translated keys to values. The first `P` bytes of the
13/// (untranslated) key are used to determine the partition, and the translator is used by the
14/// partition-specific indices on the key after stripping this prefix. The value of `P` should be
15/// small, typically 1 or 2. Anything larger than 3 will fail to compile.
16pub struct Index<T: Translator, V: Eq + Send + Sync, const P: usize> {
17    partitions: Vec<OrderedIndex<T, V>>,
18}
19
20impl<T: Translator, V: Eq + Send + Sync, const P: usize> Index<T, V, P> {
21    /// Create a new [Index] with the given translator and metrics registry.
22    pub fn new(ctx: impl Metrics, translator: T) -> Self {
23        let partition_count = 1 << (P * 8);
24        let mut partitions = Vec::with_capacity(partition_count);
25        for i in 0..partition_count {
26            partitions.push(OrderedIndex::new(
27                ctx.with_label("partition").with_attribute("idx", i),
28                translator.clone(),
29            ));
30        }
31
32        Self { partitions }
33    }
34
35    /// Get the partition for the given key, along with the prefix-stripped key for probing it.
36    fn get_partition<'a>(&self, key: &'a [u8]) -> (&OrderedIndex<T, V>, &'a [u8]) {
37        let (i, sub_key) = partition_index_and_sub_key::<P>(key);
38
39        (&self.partitions[i], sub_key)
40    }
41
42    /// Get the mutable partition for the given key, along with the prefix-stripped key for probing
43    /// it.
44    fn get_partition_mut<'a>(&mut self, key: &'a [u8]) -> (&mut OrderedIndex<T, V>, &'a [u8]) {
45        let (i, sub_key) = partition_index_and_sub_key::<P>(key);
46
47        (&mut self.partitions[i], sub_key)
48    }
49}
50
51impl<T: Translator, V: Eq + Send + Sync, const P: usize> super::super::Factory<T>
52    for Index<T, V, P>
53{
54    fn new(ctx: impl commonware_runtime::Metrics, translator: T) -> Self {
55        Self::new(ctx, translator)
56    }
57}
58
59impl<T: Translator, V: Eq + Send + Sync, const P: usize> UnorderedTrait for Index<T, V, P> {
60    type Value = V;
61    type Cursor<'a>
62        = <OrderedIndex<T, V> as UnorderedTrait>::Cursor<'a>
63    where
64        Self: 'a;
65
66    fn get<'a>(&'a self, key: &[u8]) -> impl Iterator<Item = &'a Self::Value> + 'a
67    where
68        Self::Value: 'a,
69    {
70        let (partition, sub_key) = self.get_partition(key);
71
72        partition.get(sub_key)
73    }
74
75    fn get_mut<'a>(&'a mut self, key: &[u8]) -> Option<Self::Cursor<'a>> {
76        let (partition, sub_key) = self.get_partition_mut(key);
77
78        partition.get_mut(sub_key)
79    }
80
81    fn get_mut_or_insert<'a>(
82        &'a mut self,
83        key: &[u8],
84        value: Self::Value,
85    ) -> Option<Self::Cursor<'a>> {
86        let (partition, sub_key) = self.get_partition_mut(key);
87
88        partition.get_mut_or_insert(sub_key, value)
89    }
90
91    fn insert(&mut self, key: &[u8], value: Self::Value) {
92        let (partition, sub_key) = self.get_partition_mut(key);
93
94        partition.insert(sub_key, value);
95    }
96
97    fn insert_and_prune(
98        &mut self,
99        key: &[u8],
100        value: Self::Value,
101        predicate: impl Fn(&Self::Value) -> bool,
102    ) {
103        let (partition, sub_key) = self.get_partition_mut(key);
104
105        partition.insert_and_prune(sub_key, value, predicate);
106    }
107
108    fn prune(&mut self, key: &[u8], predicate: impl Fn(&Self::Value) -> bool) {
109        let (partition, sub_key) = self.get_partition_mut(key);
110
111        partition.prune(sub_key, predicate);
112    }
113
114    fn remove(&mut self, key: &[u8]) {
115        let (partition, sub_key) = self.get_partition_mut(key);
116
117        partition.remove(sub_key);
118    }
119
120    #[cfg(test)]
121    fn keys(&self) -> usize {
122        // Note: this is really inefficient, but it's only used for testing.
123        let mut keys = 0;
124        for partition in &self.partitions {
125            keys += partition.keys();
126        }
127
128        keys
129    }
130
131    #[cfg(test)]
132    fn items(&self) -> usize {
133        // Note: this is really inefficient, but it's only used for testing.
134        let mut items = 0;
135        for partition in &self.partitions {
136            items += partition.items();
137        }
138
139        items
140    }
141
142    #[cfg(test)]
143    fn pruned(&self) -> usize {
144        // Note: this is really inefficient, but it's only used for testing.
145        let mut pruned = 0;
146        for partition in &self.partitions {
147            pruned += partition.pruned();
148        }
149
150        pruned
151    }
152}
153
154impl<T: Translator, V: Eq + Send + Sync, const P: usize> OrderedTrait for Index<T, V, P> {
155    type Iterator<'a>
156        = <OrderedIndex<T, V> as OrderedTrait>::Iterator<'a>
157    where
158        Self: 'a;
159
160    fn prev_translated_key<'a>(&'a self, key: &[u8]) -> Option<(Self::Iterator<'a>, bool)>
161    where
162        Self::Value: 'a,
163    {
164        let (partition_index, sub_key) = partition_index_and_sub_key::<P>(key);
165        {
166            let partition = &self.partitions[partition_index];
167            let iter = partition.prev_translated_key_no_cycle(sub_key);
168            if let Some(iter) = iter {
169                return Some((iter, false));
170            }
171        }
172
173        for partition in self.partitions[..partition_index].iter().rev() {
174            let iter = partition.last_translated_key();
175            if let Some(iter) = iter {
176                return Some((iter, false));
177            }
178        }
179
180        self.last_translated_key().map(|iter| (iter, true))
181    }
182
183    fn next_translated_key<'a>(&'a self, key: &[u8]) -> Option<(Self::Iterator<'a>, bool)>
184    where
185        Self::Value: 'a,
186    {
187        let (partition_index, sub_key) = partition_index_and_sub_key::<P>(key);
188        {
189            let partition = &self.partitions[partition_index];
190            let iter = partition.next_translated_key_no_cycle(sub_key);
191            if let Some(iter) = iter {
192                return Some((iter, false));
193            }
194        }
195
196        for partition in self.partitions[partition_index + 1..].iter() {
197            let iter = partition.first_translated_key();
198            if let Some(iter) = iter {
199                return Some((iter, false));
200            }
201        }
202
203        self.first_translated_key().map(|iter| (iter, true))
204    }
205
206    fn first_translated_key<'a>(&'a self) -> Option<Self::Iterator<'a>>
207    where
208        Self::Value: 'a,
209    {
210        for partition in &self.partitions {
211            let iter = partition.first_translated_key();
212            if iter.is_none() {
213                continue;
214            }
215            return iter;
216        }
217
218        None
219    }
220
221    fn last_translated_key<'a>(&'a self) -> Option<Self::Iterator<'a>>
222    where
223        Self::Value: 'a,
224    {
225        for partition in self.partitions.iter().rev() {
226            let iter = partition.last_translated_key();
227            if iter.is_none() {
228                continue;
229            }
230            return iter;
231        }
232
233        None
234    }
235}
236
237#[cfg(test)]
238mod tests {
239    use super::*;
240    use crate::translator::OneCap;
241    use commonware_macros::test_traced;
242    use commonware_runtime::{deterministic, Runner};
243    use commonware_utils::hex;
244
245    #[test_traced]
246    fn test_ordered_trait_empty_index() {
247        let runner = deterministic::Runner::default();
248        runner.start(|context| async move {
249            let index = Index::<_, u64, 1>::new(context, OneCap);
250
251            assert!(index.first_translated_key().is_none());
252            assert!(index.last_translated_key().is_none());
253            assert!(index.prev_translated_key(b"key").is_none());
254            assert!(index.next_translated_key(b"key").is_none());
255        });
256    }
257
258    #[test_traced]
259    fn test_ordered_trait_single_key() {
260        let runner = deterministic::Runner::default();
261        runner.start(|context| async move {
262            let mut index = Index::<_, u64, 1>::new(context, OneCap);
263            let key = b"\x0a\xff";
264
265            index.insert(key, 42u64);
266
267            let mut first = index.first_translated_key().unwrap();
268            assert_eq!(first.next(), Some(&42));
269            assert!(first.next().is_none());
270
271            let mut last = index.last_translated_key().unwrap();
272            assert_eq!(last.next(), Some(&42));
273            assert!(last.next().is_none());
274
275            let (mut iter, wrapped) = index.prev_translated_key(key).unwrap();
276            assert!(wrapped);
277            assert_eq!(iter.next(), Some(&42));
278            assert!(iter.next().is_none());
279            let (mut iter, wrapped) = index.next_translated_key(key).unwrap();
280            assert!(wrapped);
281            assert_eq!(iter.next(), Some(&42));
282            assert!(iter.next().is_none());
283
284            let (mut next, wrapped) = index.next_translated_key(b"\x00").unwrap();
285            assert!(!wrapped);
286            assert_eq!(next.next(), Some(&42));
287            assert!(next.next().is_none());
288
289            let (mut prev, wrapped) = index.prev_translated_key(b"\xff\x00").unwrap();
290            assert!(!wrapped);
291            assert_eq!(prev.next(), Some(&42));
292            assert!(prev.next().is_none());
293        });
294    }
295
296    #[test_traced]
297    fn test_ordered_trait_all_keys() {
298        let runner = deterministic::Runner::default();
299        runner.start(|context| async move {
300            let mut index = Index::<_, u64, 1>::new(context, OneCap);
301            // Insert a key for every possible prefix + 1-cap
302            for b1 in 0..=255u8 {
303                for b2 in 0..=255u8 {
304                    let key = [b1, b2];
305                    index.insert(&key, (b1 as u64) << 8 | b2 as u64);
306                }
307            }
308
309            // Insert some longer keys to test conflicts.
310            for b1 in (0..=255u8).rev() {
311                for b2 in 0..=255u8 {
312                    let key = [b1, b2, 0xff];
313                    index.insert(&key, u64::MAX);
314                }
315            }
316
317            let first_translated_key = index.first_translated_key().unwrap().next().unwrap();
318            assert_eq!(*first_translated_key, 0);
319
320            let last_translated_key = index.last_translated_key().unwrap().next().unwrap();
321            assert_eq!(*last_translated_key, (255u64 << 8) | 255);
322
323            let last = [255u8, 255u8];
324            let (mut iter, wrapped) = index.next_translated_key(&last).unwrap();
325            assert!(wrapped);
326            assert_eq!(iter.next(), Some(first_translated_key));
327
328            for b1 in 0..=255u8 {
329                for b2 in 0..=255u8 {
330                    let key = [b1, b2];
331                    if !(b1 == 255 && b2 == 255) {
332                        let (mut iter, _) = index.next_translated_key(&key).unwrap();
333                        let next = *iter.next().unwrap();
334                        assert_eq!(next, ((b1 as u64) << 8 | b2 as u64) + 1);
335                        let next = *iter.next().unwrap();
336                        assert_eq!(next, u64::MAX);
337                        assert!(iter.next().is_none());
338                    }
339                    if !(b1 == 0 && b2 == 0) {
340                        let (mut iter, _) = index.prev_translated_key(&key).unwrap();
341                        let prev = *iter.next().unwrap();
342                        assert_eq!(prev, ((b1 as u64) << 8 | b2 as u64) - 1);
343                        let prev = *iter.next().unwrap();
344                        assert_eq!(prev, u64::MAX);
345                        assert!(iter.next().is_none());
346                    }
347                }
348            }
349        });
350    }
351
352    #[test_traced]
353    fn test_ordered_trait_multiple_keys() {
354        let runner = deterministic::Runner::default();
355        runner.start(|context| async move {
356            let mut index = Index::<_, u64, 1>::new(context, OneCap);
357            assert_eq!(index.keys(), 0);
358
359            let k1 = &hex!("0x0b02AA"); // translated key 0b02
360            let k2 = &hex!("0x1c04CC"); // translated key 1c04
361            let k2_collides = &hex!("0x1c0411");
362            let k3 = &hex!("0x2d06EE"); // translated key 2d06
363            index.insert(k1, 1);
364            index.insert(k2, 21);
365            index.insert(k2_collides, 22);
366            index.insert(k3, 3);
367            assert_eq!(index.keys(), 3);
368
369            // First translated key is 0b.
370            let mut iter = index.first_translated_key().unwrap();
371            assert_eq!(iter.next(), Some(&1));
372            assert_eq!(iter.next(), None);
373
374            // Next translated key to 0x00 is 0b02.
375            let (mut iter, wrapped) = index.next_translated_key(&[0x00]).unwrap();
376            assert!(!wrapped);
377            assert_eq!(iter.next(), Some(&1));
378            assert_eq!(iter.next(), None);
379
380            // Next translated key to 0x0b02 is 1c.
381            let (mut iter, wrapped) = index.next_translated_key(&hex!("0x0b02F2")).unwrap();
382            assert!(!wrapped);
383            assert_eq!(iter.next(), Some(&21));
384            assert_eq!(iter.next(), Some(&22));
385            assert_eq!(iter.next(), None);
386
387            // Next translated key to 0x1b is 1c.
388            let (mut iter, wrapped) = index.next_translated_key(&hex!("0x1b010203")).unwrap();
389            assert!(!wrapped);
390            assert_eq!(iter.next(), Some(&21));
391            assert_eq!(iter.next(), Some(&22));
392            assert_eq!(iter.next(), None);
393
394            // Next translated key to 0x2a is 2d.
395            let (mut iter, wrapped) = index.next_translated_key(&hex!("0x2a01020304")).unwrap();
396            assert!(!wrapped);
397            assert_eq!(iter.next(), Some(&3));
398            assert_eq!(iter.next(), None);
399
400            // Next translated key to 0x2d is 0b.
401            let (mut iter, wrapped) = index.next_translated_key(k3).unwrap();
402            assert!(wrapped);
403            assert_eq!(iter.next(), Some(&1));
404            assert_eq!(iter.next(), None);
405
406            // Another cycle around case.
407            let (mut iter, wrapped) = index.next_translated_key(&hex!("0x2eFF")).unwrap();
408            assert!(wrapped);
409            assert_eq!(iter.next(), Some(&1));
410            assert_eq!(iter.next(), None);
411
412            // Previous translated key is the last key due to cycling.
413            let (mut iter, wrapped) = index.prev_translated_key(k1).unwrap();
414            assert!(wrapped);
415            assert_eq!(iter.next(), Some(&3));
416            assert_eq!(iter.next(), None);
417
418            // Previous translated key is 0b.
419            let (mut iter, wrapped) = index.prev_translated_key(&hex!("0x0c0102")).unwrap();
420            assert!(!wrapped);
421            assert_eq!(iter.next(), Some(&1));
422            assert_eq!(iter.next(), None);
423
424            // Previous translated key is 1c.
425            let (mut iter, wrapped) = index.prev_translated_key(&hex!("0x1d0102")).unwrap();
426            assert!(!wrapped);
427            assert_eq!(iter.next(), Some(&21));
428            assert_eq!(iter.next(), Some(&22));
429            assert_eq!(iter.next(), None);
430
431            // Previous translated key is 2d.
432            let (mut iter, wrapped) = index.prev_translated_key(&hex!("0xCC0102")).unwrap();
433            assert!(!wrapped);
434            assert_eq!(iter.next(), Some(&3));
435            assert_eq!(iter.next(), None);
436
437            // Last translated key is 2d.
438            let mut iter = index.last_translated_key().unwrap();
439            assert_eq!(iter.next(), Some(&3));
440            assert_eq!(iter.next(), None);
441        });
442    }
443}