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