Skip to main content

fxfs/lsm_tree/
skip_list_layer.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// There are a great many optimisations that could be considered to improve performance and maybe
6// memory usage.
7
8use crate::drop_event::DropEvent;
9use crate::log::*;
10use crate::lsm_tree::merge::{self, MergeFn};
11use crate::lsm_tree::types::{
12    BoxedLayerIterator, Existence, Item, ItemRef, Key, Layer, LayerIterator, LayerIteratorMut,
13    LayerValue, OrdLowerBound, OrdUpperBound,
14};
15use crate::serialized_types::{LATEST_VERSION, Version};
16use anyhow::{Error, bail};
17use async_trait::async_trait;
18use fuchsia_sync::{Mutex, MutexGuard};
19use futures::future::BoxFuture;
20use std::cmp::{Ordering, min};
21use std::collections::BTreeMap;
22use std::ops::Bound;
23use std::ptr::NonNull;
24use std::sync::Arc;
25use std::sync::atomic::{self, AtomicPtr, AtomicU32};
26
27// Each skip list node contains a variable sized pointer list. The head pointers also exist in the
28// form of a pointer list. Index 0 in the pointer list is the chain with the most elements i.e.
29// contains every element in the list.
30struct PointerList<K, V>(Box<[AtomicPtr<SkipListNode<K, V>>]>);
31
32impl<K, V> PointerList<K, V> {
33    fn new(count: usize) -> PointerList<K, V> {
34        PointerList((0..count).map(|_| AtomicPtr::new(std::ptr::null_mut())).collect())
35    }
36
37    fn len(&self) -> usize {
38        self.0.len()
39    }
40
41    // Extracts the pointer at the given index.
42    fn get(&self, index: usize) -> Option<NonNull<SkipListNode<K, V>>> {
43        NonNull::new(self.0[index].load(atomic::Ordering::SeqCst))
44    }
45
46    // Sets the pointer at the given index.
47    fn set(&self, index: usize, node: Option<NonNull<SkipListNode<K, V>>>) {
48        self.0[index]
49            .store(node.map_or(std::ptr::null_mut(), |n| n.as_ptr()), atomic::Ordering::SeqCst);
50    }
51}
52
53struct SkipListNode<K, V> {
54    item: Item<K, V>,
55    pointers: PointerList<K, V>,
56}
57
58pub struct SkipListLayer<K, V> {
59    // These are the head pointers for the list.
60    pointers: PointerList<K, V>,
61
62    inner: Mutex<Inner<K, V>>,
63
64    // Writes are locked using this lock.
65    write_lock: Mutex<()>,
66
67    // The number of nodes that have been allocated.  This is only used for debugging purposes.
68    allocated: AtomicU32,
69
70    close_event: Mutex<Option<Arc<DropEvent>>>,
71}
72
73// The writer needs to synchronize with the readers and this is done by keeping track of read
74// counts.  We could, in theory, remove the mutex and make the read counts atomic (and thus make
75// reads truly lock free) but it's simpler and easier to reason about with a mutex and what matters
76// most is that we avoid using a futures::lock::Mutex for readers because that can be blocked for
77// relatively long periods of time.
78struct Inner<K, V> {
79    // After a write, if there are nodes that need to be freed, and existing readers, the epoch
80    // changes and new readers will be in a new epoch.  When all the old readers finish, the nodes
81    // can be freed.
82    epoch: u64,
83
84    // The number of readers on the current epoch.
85    current_count: u64,
86
87    // A list of nodes to be freed once the read counts have reached zero.
88    erase_lists: BTreeMap<u64, EpochEraseList<K, V>>,
89
90    // The number of items in the skip-list.
91    item_count: usize,
92}
93
94// After a mutation that involves erasing nodes, we must keep the nodes alive until there are no
95// more readers in any of the epochs prior to the mutation.  To deal with this, we track the number
96// of outstanding readers in each epoch so that when the count reaches zero, we know it is safe to
97// free the nodes.
98struct EpochEraseList<K, V> {
99    // The number of readers still associated with this epoch.  When this reaches zero, the list can
100    // be freed once all previous epochs have been freed.
101    count: u64,
102    // We represent the list by storing the head and tail of the list which each node chained to the
103    // next.
104    start: NonNull<SkipListNode<K, V>>,
105    end: Option<NonNull<SkipListNode<K, V>>>,
106}
107
108// SAFETY: Required because of `erase_lists` which holds pointers.
109unsafe impl<K, V> Send for Inner<K, V> {}
110
111impl<K, V> Inner<K, V> {
112    fn new() -> Self {
113        Inner { epoch: 0, current_count: 0, erase_lists: BTreeMap::new(), item_count: 0 }
114    }
115    fn free_erase_list(
116        &mut self,
117        owner: &SkipListLayer<K, V>,
118        start: NonNull<SkipListNode<K, V>>,
119        end: Option<NonNull<SkipListNode<K, V>>>,
120    ) {
121        let mut node = start;
122        loop {
123            // SAFETY: This node has no more references.
124            let next = unsafe { owner.free_node(node) };
125            if next == end {
126                break;
127            }
128            node = next.unwrap();
129        }
130    }
131}
132
133impl<K, V> SkipListLayer<K, V> {
134    pub fn new(max_item_count: usize) -> Arc<SkipListLayer<K, V>> {
135        Arc::new(SkipListLayer {
136            pointers: PointerList::new((usize::BITS - max_item_count.leading_zeros()) as usize),
137            inner: Mutex::new(Inner::new()),
138            write_lock: Mutex::new(()),
139            allocated: AtomicU32::new(0),
140            close_event: Mutex::new(Some(Arc::new(DropEvent::new()))),
141        })
142    }
143
144    pub fn len(&self) -> usize {
145        self.inner.lock().item_count
146    }
147
148    fn alloc_node(&self, item: Item<K, V>, pointer_count: usize) -> Box<SkipListNode<K, V>> {
149        self.allocated.fetch_add(1, atomic::Ordering::Relaxed);
150        Box::new(SkipListNode { item, pointers: PointerList::new(pointer_count) })
151    }
152
153    // Frees and then returns the next node in the chain.
154    //
155    // # Safety
156    //
157    // The node must have no other references.
158    unsafe fn free_node(
159        &self,
160        node: NonNull<SkipListNode<K, V>>,
161    ) -> Option<NonNull<SkipListNode<K, V>>> {
162        self.allocated.fetch_sub(1, atomic::Ordering::Relaxed);
163        unsafe { Box::from_raw(node.as_ptr()).pointers.get(0) }
164    }
165}
166
167impl<K: Eq + Key + OrdLowerBound, V: LayerValue> SkipListLayer<K, V> {
168    // Erases the given item. Does nothing if the item doesn't exist.
169    pub fn erase(&self, key: &K)
170    where
171        K: std::cmp::Eq,
172    {
173        let mut iter = SkipListLayerIterMut::new(self, Bound::Included(key));
174        if let Some(ItemRef { key: k, .. }) = iter.get() {
175            if k == key {
176                iter.erase();
177            } else {
178                warn!("Attempt to erase key not present!");
179            }
180        }
181        iter.commit();
182    }
183
184    /// Inserts the given item.
185    pub fn insert(&self, item: Item<K, V>) -> Result<(), Error> {
186        let mut iter = SkipListLayerIterMut::new(self, Bound::Included(&item.key));
187        if let Some(found_item) = iter.get() {
188            if found_item.key == &item.key {
189                bail!("Attempted to insert an existing key");
190            }
191        }
192        iter.insert(item);
193        Ok(())
194    }
195
196    /// Replaces or inserts the given item.
197    pub fn replace_or_insert(&self, item: Item<K, V>) {
198        let mut iter = SkipListLayerIterMut::new(self, Bound::Included(&item.key));
199        if let Some(found_item) = iter.get() {
200            if found_item.key == &item.key {
201                iter.erase();
202            }
203        }
204        iter.insert(item);
205    }
206
207    /// Merges the item into the layer.
208    pub fn merge_into(&self, item: Item<K, V>, lower_bound: &K, merge_fn: MergeFn<K, V>) {
209        merge::merge_into(
210            Box::new(SkipListLayerIterMut::new(self, Bound::Included(lower_bound))),
211            item,
212            merge_fn,
213        )
214        .unwrap();
215    }
216}
217
218impl<K: OrdUpperBound, V> SkipListLayer<K, V> {
219    /// Searches for a key. Bound::Excluded is not supported. Bound::Unbounded positions the
220    /// iterator on the first item in the layer.
221    ///
222    /// This is an inherent version of the `Layer::seek` trait method which avoids returning a
223    /// boxed future and boxed iterator.
224    pub fn seek<'a>(&'a self, bound: Bound<&K>) -> SkipListLayerIter<'a, K, V> {
225        SkipListLayerIter::new(self, bound)
226    }
227}
228
229// We have to manually manage memory.
230impl<K, V> Drop for SkipListLayer<K, V> {
231    fn drop(&mut self) {
232        let mut next = self.pointers.get(0);
233        while let Some(node) = next {
234            // SAFETY: The node has no more references.
235            next = unsafe { self.free_node(node) };
236        }
237        assert_eq!(self.allocated.load(atomic::Ordering::Relaxed), 0);
238    }
239}
240
241#[async_trait]
242impl<K: Key, V: LayerValue> Layer<K, V> for SkipListLayer<K, V> {
243    async fn seek<'a>(
244        &'a self,
245        bound: std::ops::Bound<&K>,
246    ) -> Result<BoxedLayerIterator<'a, K, V>, Error> {
247        Ok(Box::new(SkipListLayer::seek(self, bound)))
248    }
249
250    fn lock(&self) -> Option<Arc<DropEvent>> {
251        self.close_event.lock().clone()
252    }
253
254    fn len(&self) -> usize {
255        self.inner.lock().item_count
256    }
257
258    async fn close(&self) {
259        let listener = self.close_event.lock().take().expect("close already called").listen();
260        listener.await;
261    }
262
263    fn get_version(&self) -> Version {
264        // The SkipListLayer is stored in RAM and written to disk as a SimplePersistentLayer
265        // Hence, the SkipListLayer is always at the latest version
266        return LATEST_VERSION;
267    }
268
269    fn record_inspect_data(self: Arc<Self>, node: &fuchsia_inspect::Node) {
270        node.record_bool("persistent", false);
271        node.record_uint("num_items", self.inner.lock().item_count as u64);
272    }
273
274    async fn key_exists(&self, key: &K) -> Result<Existence, Error> {
275        let iter = SkipListLayer::seek(self, Bound::Included(key));
276        Ok(iter.get().map_or(Existence::Missing, |i| {
277            if i.key.cmp_upper_bound(key).is_eq() { Existence::Exists } else { Existence::Missing }
278        }))
279    }
280}
281
282// -- SkipListLayerIter --
283
284pub struct SkipListLayerIter<'a, K, V> {
285    skip_list: &'a SkipListLayer<K, V>,
286
287    // The epoch for this reader.
288    epoch: u64,
289
290    // The current node.
291    node: Option<NonNull<SkipListNode<K, V>>>,
292}
293
294// SAFETY: We need this for `node` which is safe to pass across threads.
295unsafe impl<K, V> Send for SkipListLayerIter<'_, K, V> {}
296unsafe impl<K, V> Sync for SkipListLayerIter<'_, K, V> {}
297
298impl<'a, K: OrdUpperBound, V> SkipListLayerIter<'a, K, V> {
299    fn new(skip_list: &'a SkipListLayer<K, V>, bound: Bound<&K>) -> Self {
300        let epoch = {
301            let mut inner = skip_list.inner.lock();
302            inner.current_count += 1;
303            inner.epoch
304        };
305        let (included, key) = match bound {
306            Bound::Unbounded => {
307                return SkipListLayerIter { skip_list, epoch, node: skip_list.pointers.get(0) };
308            }
309            Bound::Included(key) => (true, key),
310            Bound::Excluded(key) => (false, key),
311        };
312        let mut last_pointers = &skip_list.pointers;
313
314        // Some care needs to be taken here because new elements can be inserted atomically, so it
315        // is important that the node we return in the iterator is the same node that we performed
316        // the last comparison on.
317        let mut node = None;
318        for index in (0..skip_list.pointers.len()).rev() {
319            // Keep iterating along this level until we encounter a key that's >= our search key.
320            loop {
321                node = last_pointers.get(index);
322                if let Some(node) = node {
323                    // SAFETY: `node` should be valid; we took a reference to the epoch above.
324                    let node = unsafe { node.as_ref() };
325                    match &node.item.key.cmp_upper_bound(key) {
326                        Ordering::Equal if included => break,
327                        Ordering::Greater => break,
328                        _ => {}
329                    }
330                    last_pointers = &node.pointers;
331                } else {
332                    break;
333                }
334            }
335        }
336        SkipListLayerIter { skip_list, epoch, node }
337    }
338}
339
340impl<K, V> Drop for SkipListLayerIter<'_, K, V> {
341    fn drop(&mut self) {
342        let mut inner = self.skip_list.inner.lock();
343        if self.epoch == inner.epoch {
344            inner.current_count -= 1;
345        } else {
346            if let Some(erase_list) = inner.erase_lists.get_mut(&self.epoch) {
347                erase_list.count -= 1;
348                if erase_list.count == 0 {
349                    while let Some(entry) = inner.erase_lists.first_entry() {
350                        if entry.get().count == 0 {
351                            let EpochEraseList { start, end, .. } = entry.remove_entry().1;
352                            inner.free_erase_list(self.skip_list, start, end);
353                        } else {
354                            break;
355                        }
356                    }
357                }
358            }
359        }
360    }
361}
362
363impl<K: Key, V: LayerValue> LayerIterator<K, V> for SkipListLayerIter<'_, K, V> {
364    async fn advance(&mut self) -> Result<(), Error> {
365        let _ = self.advance_dyn()?;
366        Ok(())
367    }
368
369    fn advance_dyn<'a>(&'a mut self) -> Result<Option<BoxFuture<'a, Result<(), Error>>>, Error> {
370        match self.node {
371            None => {}
372            Some(node) => {
373                self.node = {
374                    // SAFETY: `node` should be valid; we took a reference to the epoch in `new`.
375                    unsafe { node.as_ref() }.pointers.get(0)
376                }
377            }
378        }
379        Ok(None)
380    }
381
382    fn get(&self) -> Option<ItemRef<'_, K, V>> {
383        // SAFETY: `node` should be valid; we took a reference to the epoch in `new`.
384        self.node.map(|node| unsafe { node.as_ref() }.item.as_item_ref())
385    }
386}
387
388type PointerListRefArray<'a, K, V> = Box<[&'a PointerList<K, V>]>;
389
390// -- SkipListLayerIterMut --
391
392// This works by building an insertion chain.  When that chain is committed, it is done atomically
393// so that readers are not interrupted.  When the existing readers are finished, it is then safe to
394// release memory for any nodes that might have been erased.  In the case that we are only erasing
395// elements, there will be no insertion chain, in which case we just atomically remove the elements
396// from the chain.
397pub struct SkipListLayerIterMut<'a, K: Key, V: LayerValue> {
398    skip_list: &'a SkipListLayer<K, V>,
399
400    // Since this is a mutable iterator, we need to keep pointers to all the nodes that precede the
401    // current position at every level, so that we can update them when inserting or erasing
402    // elements.
403    prev_pointers: PointerListRefArray<'a, K, V>,
404
405    // When we first insert or erase an element, we take a copy of prev_pointers so that
406    // we know which pointers need to be updated when we commit.
407    insertion_point: Option<PointerListRefArray<'a, K, V>>,
408
409    // These are the nodes that we should point to when we commit.
410    insertion_nodes: PointerList<K, V>,
411
412    // Only one write can proceed at a time.  We only need a place to keep the mutex guard, which is
413    // why Rust thinks this is unused.
414    #[allow(dead_code)]
415    write_guard: MutexGuard<'a, ()>,
416
417    // The change in item count as a result of this mutation.
418    item_delta: isize,
419}
420
421impl<'a, K: Key, V: LayerValue> SkipListLayerIterMut<'a, K, V> {
422    pub fn new(skip_list: &'a SkipListLayer<K, V>, bound: std::ops::Bound<&K>) -> Self {
423        let write_guard = skip_list.write_lock.lock();
424        let len = skip_list.pointers.len();
425
426        // Start by setting all the previous pointers to the head.
427        //
428        // To understand how the previous pointers work, imagine the list looks something like the
429        // following:
430        //
431        // 2  |--->|
432        // 1  |--->|--|------->|
433        // 0  |--->|--|--|--|->|
434        //  HEAD   A  B  C  D  E  F
435        //
436        // Now imagine that the iterator is pointing at element D. In that case, the previous
437        // pointers will point at C for index 0, B for index 1 and A for index 2. With that
438        // information, it will be possible to insert an element immediately prior to D and
439        // correctly update as many pointers as required (remember a new element will be given a
440        // random number of levels).
441        let mut prev_pointers = vec![&skip_list.pointers; len].into_boxed_slice();
442        match bound {
443            Bound::Unbounded => {}
444            Bound::Included(key) => {
445                let pointers = &mut prev_pointers;
446                for index in (0..len).rev() {
447                    while let Some(node) = pointers[index].get(index) {
448                        // Keep iterating along this level until we encounter a key that's >= our
449                        // search key.
450
451                        // SAFETY: `node` should be valid; a write guard was taken above so nodes
452                        // in the current epoch cannot be erased.
453                        let node = unsafe { node.as_ref() };
454
455                        match node.item.key.cmp_upper_bound(key) {
456                            Ordering::Equal | Ordering::Greater => break,
457                            Ordering::Less => {}
458                        }
459                        pointers[index] = &node.pointers;
460                    }
461                    if index > 0 {
462                        pointers[index - 1] = pointers[index];
463                    }
464                }
465            }
466            Bound::Excluded(_) => panic!("Excluded bounds not supported"),
467        }
468        SkipListLayerIterMut {
469            skip_list,
470            prev_pointers,
471            insertion_point: None,
472            insertion_nodes: PointerList::new(len),
473            write_guard,
474            item_delta: 0,
475        }
476    }
477}
478
479impl<K: Key, V: LayerValue> Drop for SkipListLayerIterMut<'_, K, V> {
480    fn drop(&mut self) {
481        self.commit();
482    }
483}
484
485impl<K: Key, V: LayerValue> LayerIteratorMut<K, V> for SkipListLayerIterMut<'_, K, V> {
486    fn advance(&mut self) {
487        if self.insertion_point.is_some() {
488            if let Some(item) = self.get() {
489                // Copy the current item into the insertion chain.
490                let copy = item.cloned();
491                self.insert(copy);
492                self.erase();
493            }
494        } else {
495            let pointers = &mut self.prev_pointers;
496            if let Some(next) = pointers[0].get(0) {
497                // SAFETY: `node` should be valid; a write guard was taken above so nodes
498                // in the current epoch cannot be erased.
499                let next = unsafe { next.as_ref() };
500                for i in 0..next.pointers.len() {
501                    pointers[i] = &next.pointers;
502                }
503            }
504        }
505    }
506
507    fn get(&self) -> Option<ItemRef<'_, K, V>> {
508        // SAFETY: `node` should be valid; a write guard was taken above so nodes in the current
509        // epoch cannot be erased.
510        self.prev_pointers[0].get(0).map(|node| unsafe { node.as_ref() }.item.as_item_ref())
511    }
512
513    fn insert(&mut self, item: Item<K, V>) {
514        use rand::RngExt as _;
515        let mut rng = rand::rng();
516        let max_pointers = self.skip_list.pointers.len();
517        // This chooses a random number of pointers such that each level has half the number of
518        // pointers of the previous one.
519        let pointer_count = min(1 + rng.random::<u32>().trailing_zeros() as usize, max_pointers);
520        let node = Box::leak(self.skip_list.alloc_node(item, pointer_count));
521        if self.insertion_point.is_none() {
522            self.insertion_point = Some(self.prev_pointers.clone());
523        }
524        let node_ptr = node.into();
525        for i in 0..pointer_count {
526            let pointers = self.prev_pointers[i];
527            node.pointers.set(i, pointers.get(i));
528            if self.insertion_nodes.get(i).is_none() {
529                // If there's no insertion node at this level, record this node as the node to
530                // switch in when we commit.
531                self.insertion_nodes.set(i, Some(node_ptr));
532            } else {
533                // There's already an insertion node at this level which means that it's part of the
534                // insertion chain, so we can just update the pointers now.
535                pointers.set(i, Some(node_ptr));
536            }
537            // The iterator should point at the node following the new node i.e. the existing node.
538            self.prev_pointers[i] = &node.pointers;
539        }
540        self.item_delta += 1;
541    }
542
543    fn erase(&mut self) {
544        let pointers = &mut self.prev_pointers;
545        if let Some(next) = pointers[0].get(0) {
546            // SAFETY: `next` should be valid; a write guard was taken above so nodes in the current
547            // epoch cannot be erased.
548            let next = unsafe { next.as_ref() };
549            if self.insertion_point.is_none() {
550                self.insertion_point = Some(pointers.clone());
551            }
552            if self.insertion_nodes.get(0).is_none() {
553                // If there's no insertion node, then just update the iterator position to point to
554                // the next node, and then when we commit, it'll get erased.
555                pointers[0] = &next.pointers;
556            } else {
557                // There's an insertion node, so the current element must be part of the insertion
558                // chain and so we can update the pointers immediately.  There will be another node
559                // that isn't part of the insertion chain that will still point at this node, but it
560                // will disappear when we commit.
561                pointers[0].set(0, next.pointers.get(0));
562            }
563            // Fix up all the pointers except the bottom one. Readers will still find this node,
564            // just not as efficiently.
565            for i in 1..next.pointers.len() {
566                pointers[i].set(i, next.pointers.get(i));
567            }
568        }
569        self.item_delta -= 1;
570    }
571
572    // Commits the changes.  Note that this doesn't wait for readers to finish; any barrier that be
573    // required should be handled by the caller.
574    fn commit(&mut self) {
575        // Splice the changes into the list.
576        let prev_pointers = match self.insertion_point.take() {
577            Some(prev_pointers) => prev_pointers,
578            None => return,
579        };
580
581        // Keep track of the first node that we might need to erase later.
582        let maybe_erase = prev_pointers[0].get(0);
583
584        // If there are no insertion nodes, then it means that we're only erasing nodes.
585        if self.insertion_nodes.get(0).is_none() {
586            // Erase all elements between the insertion point and the current element. The
587            // pointers for levels > 0 should already have been done, so it's only level 0 we
588            // need to worry about.
589            prev_pointers[0].set(0, self.prev_pointers[0].get(0));
590        } else {
591            // Switch the pointers over so that the insertion chain is spliced in.  This is safe
592            // so long as the bottom pointer is done first because that guarantees the new nodes
593            // will be found, just maybe not as efficiently.
594            for i in 0..self.insertion_nodes.len() {
595                if let Some(node) = self.insertion_nodes.get(i) {
596                    prev_pointers[i].set(i, Some(node));
597                }
598            }
599        }
600
601        // Switch the epoch so that we can track when existing readers have finished.
602        let mut inner = self.skip_list.inner.lock();
603        inner.item_count = inner.item_count.checked_add_signed(self.item_delta).unwrap();
604        if let Some(start) = maybe_erase {
605            let end = self.prev_pointers[0].get(0);
606            if maybe_erase != end {
607                if inner.current_count > 0 || !inner.erase_lists.is_empty() {
608                    let count = std::mem::take(&mut inner.current_count);
609                    let epoch = inner.epoch;
610                    inner.erase_lists.insert(epoch, EpochEraseList { count, start, end });
611                    inner.epoch = inner.epoch.wrapping_add(1);
612                } else {
613                    inner.free_erase_list(self.skip_list, start, end);
614                }
615            }
616        }
617    }
618}
619
620#[cfg(test)]
621mod tests {
622    use super::{SkipListLayer, SkipListLayerIterMut};
623    use crate::lsm_tree::merge::ItemOp::{Discard, Replace};
624    use crate::lsm_tree::merge::{MergeLayerIterator, MergeResult};
625    use crate::lsm_tree::skip_list_layer::SkipListLayerIter;
626    use crate::lsm_tree::types::{
627        DefaultOrdLowerBound, DefaultOrdUpperBound, Existence, FuzzyHash, Item, ItemRef, Layer,
628        LayerIterator, LayerIteratorMut, SortByU64,
629    };
630    use crate::serialized_types::{
631        LATEST_VERSION, Version, Versioned, VersionedLatest, versioned_type,
632    };
633    use assert_matches::assert_matches;
634    use fprint::TypeFingerprint;
635    use fuchsia_async as fasync;
636    use futures::future::join_all;
637    use futures::{FutureExt as _, join};
638    use fxfs_macros::{FuzzyHash, SerializeKey};
639    use std::hash::Hash;
640    use std::ops::Bound;
641    use std::time::{Duration, Instant};
642
643    #[derive(
644        Clone,
645        Eq,
646        Debug,
647        Hash,
648        FuzzyHash,
649        PartialEq,
650        PartialOrd,
651        Ord,
652        serde::Serialize,
653        serde::Deserialize,
654        TypeFingerprint,
655        Versioned,
656        SerializeKey,
657    )]
658    struct TestKey(u64);
659
660    versioned_type! { 1.. => TestKey }
661
662    impl SortByU64 for TestKey {
663        fn get_leading_u64(&self) -> u64 {
664            self.0
665        }
666    }
667
668    impl DefaultOrdLowerBound for TestKey {}
669    impl DefaultOrdUpperBound for TestKey {}
670
671    #[fuchsia::test]
672    async fn test_key_exists() {
673        let skip_list = SkipListLayer::new(100);
674        skip_list.insert(Item::new(TestKey(1), 1)).expect("insert error");
675        skip_list.insert(Item::new(TestKey(3), 3)).expect("insert error");
676
677        assert_eq!(
678            skip_list.key_exists(&TestKey(0)).await.expect("key_exists failed"),
679            Existence::Missing
680        );
681        assert_eq!(
682            skip_list.key_exists(&TestKey(1)).await.expect("key_exists failed"),
683            Existence::Exists
684        );
685        assert_eq!(
686            skip_list.key_exists(&TestKey(2)).await.expect("key_exists failed"),
687            Existence::Missing
688        );
689        assert_eq!(
690            skip_list.key_exists(&TestKey(3)).await.expect("key_exists failed"),
691            Existence::Exists
692        );
693        assert_eq!(
694            skip_list.key_exists(&TestKey(4)).await.expect("key_exists failed"),
695            Existence::Missing
696        );
697    }
698
699    #[fuchsia::test]
700    async fn test_iteration() {
701        // Insert two items and make sure we can iterate back in the correct order.
702        let skip_list = SkipListLayer::new(100);
703        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2)];
704        skip_list.insert(items[1].clone()).expect("insert error");
705        skip_list.insert(items[0].clone()).expect("insert error");
706        let mut iter = skip_list.seek(Bound::Unbounded);
707        let ItemRef { key, value, .. } = iter.get().expect("missing item");
708        assert_eq!((key, value), (&items[0].key, &items[0].value));
709        iter.advance().await.unwrap();
710        let ItemRef { key, value, .. } = iter.get().expect("missing item");
711        assert_eq!((key, value), (&items[1].key, &items[1].value));
712        iter.advance().await.unwrap();
713        assert!(iter.get().is_none());
714    }
715
716    #[fuchsia::test]
717    async fn test_seek_exact() {
718        // Seek for an exact match.
719        let skip_list = SkipListLayer::new(100);
720        for i in (0..100).rev() {
721            skip_list.insert(Item::new(TestKey(i), i)).expect("insert error");
722        }
723        let mut iter = skip_list.seek(Bound::Included(&TestKey(57)));
724        let ItemRef { key, value, .. } = iter.get().expect("missing item");
725        assert_eq!((key, value), (&TestKey(57), &57));
726
727        // And check the next item is correct.
728        iter.advance().await.unwrap();
729        let ItemRef { key, value, .. } = iter.get().expect("missing item");
730        assert_eq!((key, value), (&TestKey(58), &58));
731    }
732
733    #[fuchsia::test]
734    async fn test_seek_lower_bound() {
735        // Seek for a non-exact match.
736        let skip_list = SkipListLayer::new(100);
737        for i in (0..100).rev() {
738            skip_list.insert(Item::new(TestKey(i * 3), i * 3)).expect("insert error");
739        }
740        let mut expected_index = 57 * 3;
741        let mut iter = skip_list.seek(Bound::Included(&TestKey(expected_index - 1)));
742        let ItemRef { key, value, .. } = iter.get().expect("missing item");
743        assert_eq!((key, value), (&TestKey(expected_index), &expected_index));
744
745        // And check the next item is correct.
746        expected_index += 3;
747        iter.advance().await.unwrap();
748        let ItemRef { key, value, .. } = iter.get().expect("missing item");
749        assert_eq!((key, value), (&TestKey(expected_index), &expected_index));
750    }
751
752    #[fuchsia::test]
753    async fn test_replace_or_insert_replaces() {
754        let skip_list = SkipListLayer::new(100);
755        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2)];
756        skip_list.insert(items[1].clone()).expect("insert error");
757        skip_list.insert(items[0].clone()).expect("insert error");
758        let replacement_value = 3;
759        skip_list.replace_or_insert(Item::new(items[1].key.clone(), replacement_value));
760
761        let mut iter = skip_list.seek(Bound::Unbounded);
762        let ItemRef { key, value, .. } = iter.get().expect("missing item");
763        assert_eq!((key, value), (&items[0].key, &items[0].value));
764        iter.advance().await.unwrap();
765        let ItemRef { key, value, .. } = iter.get().expect("missing item");
766        assert_eq!((key, value), (&items[1].key, &replacement_value));
767        iter.advance().await.unwrap();
768        assert!(iter.get().is_none());
769    }
770
771    #[fuchsia::test]
772    async fn test_replace_or_insert_inserts() {
773        let skip_list = SkipListLayer::new(100);
774        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2), Item::new(TestKey(3), 3)];
775        skip_list.insert(items[2].clone()).expect("insert error");
776        skip_list.insert(items[0].clone()).expect("insert error");
777        skip_list.replace_or_insert(items[1].clone());
778
779        let mut iter = skip_list.seek(Bound::Unbounded);
780        let ItemRef { key, value, .. } = iter.get().expect("missing item");
781        assert_eq!((key, value), (&items[0].key, &items[0].value));
782        iter.advance().await.unwrap();
783        let ItemRef { key, value, .. } = iter.get().expect("missing item");
784        assert_eq!((key, value), (&items[1].key, &items[1].value));
785        iter.advance().await.unwrap();
786        let ItemRef { key, value, .. } = iter.get().expect("missing item");
787        assert_eq!((key, value), (&items[2].key, &items[2].value));
788        iter.advance().await.unwrap();
789        assert!(iter.get().is_none());
790    }
791
792    #[fuchsia::test]
793    async fn test_erase() {
794        let skip_list = SkipListLayer::new(100);
795        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2)];
796        skip_list.insert(items[1].clone()).expect("insert error");
797        skip_list.insert(items[0].clone()).expect("insert error");
798
799        assert_eq!(skip_list.len(), 2);
800
801        skip_list.erase(&items[1].key);
802
803        assert_eq!(skip_list.len(), 1);
804
805        {
806            let mut iter = skip_list.seek(Bound::Unbounded);
807            let ItemRef { key, value, .. } = iter.get().expect("missing item");
808            assert_eq!((key, value), (&items[0].key, &items[0].value));
809            iter.advance().await.unwrap();
810            assert!(iter.get().is_none());
811        }
812
813        skip_list.erase(&items[0].key);
814
815        assert_eq!(skip_list.len(), 0);
816
817        {
818            let iter = skip_list.seek(Bound::Unbounded);
819            assert!(iter.get().is_none());
820        }
821    }
822
823    // This test ends up being flaky on CQ. It is left here as it might be useful in case
824    // significant changes are made.
825    #[fuchsia::test]
826    #[ignore]
827    async fn test_seek_is_log_n_complexity() {
828        // Keep doubling up the number of items until it takes about 500ms to search and then go
829        // back and measure something that should, in theory, take about half that time.
830        let mut n = 100;
831        let mut loops = 0;
832        const TARGET_TIME: Duration = Duration::from_millis(500);
833        let time = loop {
834            let skip_list = SkipListLayer::new(n as usize);
835            for i in 0..n {
836                skip_list.insert(Item::new(TestKey(i), i)).expect("insert error");
837            }
838            let start = Instant::now();
839            for i in 0..n {
840                skip_list.seek(Bound::Included(&TestKey(i)));
841            }
842            let elapsed = Instant::now() - start;
843            if elapsed > TARGET_TIME {
844                break elapsed;
845            }
846            n *= 2;
847            loops += 1;
848        };
849
850        let seek_count = n;
851        n >>= loops / 2; // This should, in theory, result in 50% seek time.
852        let skip_list = SkipListLayer::new(n as usize);
853        for i in 0..n {
854            skip_list.insert(Item::new(TestKey(i), i)).expect("insert error");
855        }
856        let start = Instant::now();
857        for i in 0..seek_count {
858            skip_list.seek(Bound::Included(&TestKey(i)));
859        }
860        let elapsed = Instant::now() - start;
861
862        eprintln!(
863            "{} items: {}ms, {} items: {}ms",
864            seek_count,
865            time.as_millis(),
866            n,
867            elapsed.as_millis()
868        );
869
870        // Experimental results show that typically we do a bit better than log(n), but here we just
871        // check that the time we just measured is above 25% of the time we first measured, the
872        // theory suggests it should be around 50%.
873        assert!(elapsed * 4 > time);
874    }
875
876    #[fuchsia::test]
877    async fn test_large_number_of_items() {
878        let item_count = 1000;
879        let skip_list = SkipListLayer::new(1000);
880        for i in 1..item_count {
881            skip_list.insert(Item::new(TestKey(i), 1)).expect("insert error");
882        }
883        let mut iter = skip_list.seek(Bound::Included(&TestKey(item_count - 10)));
884        for i in item_count - 10..item_count {
885            assert_eq!(iter.get().expect("missing item").key, &TestKey(i));
886            iter.advance().await.unwrap();
887        }
888        assert!(iter.get().is_none());
889    }
890
891    #[fuchsia::test]
892    async fn test_multiple_readers_allowed() {
893        let skip_list = SkipListLayer::new(100);
894        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2)];
895        skip_list.insert(items[1].clone()).expect("insert error");
896        skip_list.insert(items[0].clone()).expect("insert error");
897
898        // Create the first iterator and check the first item.
899        let mut iter = skip_list.seek(Bound::Unbounded);
900        let ItemRef { key, value, .. } = iter.get().expect("missing item");
901        assert_eq!((key, value), (&items[0].key, &items[0].value));
902
903        // Create a second iterator and check the first item.
904        let iter2 = skip_list.seek(Bound::Unbounded);
905        let ItemRef { key, value, .. } = iter2.get().expect("missing item");
906        assert_eq!((key, value), (&items[0].key, &items[0].value));
907
908        // Now go back to the first iterator and check the second item.
909        iter.advance().await.unwrap();
910        let ItemRef { key, value, .. } = iter.get().expect("missing item");
911        assert_eq!((key, value), (&items[1].key, &items[1].value));
912    }
913
914    fn merge(
915        left: &'_ MergeLayerIterator<'_, TestKey, i32>,
916        right: &'_ MergeLayerIterator<'_, TestKey, i32>,
917    ) -> MergeResult<TestKey, i32> {
918        MergeResult::Other {
919            emit: None,
920            left: Replace(Item::new((*left.key()).clone(), *left.value() + *right.value()).boxed()),
921            right: Discard,
922        }
923    }
924
925    #[fuchsia::test]
926    async fn test_merge_into() {
927        let skip_list = SkipListLayer::new(100);
928        skip_list.insert(Item::new(TestKey(1), 1)).expect("insert error");
929
930        skip_list.merge_into(Item::new(TestKey(2), 2), &TestKey(1), merge);
931
932        let mut iter = skip_list.seek(Bound::Unbounded);
933        let ItemRef { key, value, .. } = iter.get().expect("missing item");
934        assert_eq!((key, value), (&TestKey(1), &3));
935        iter.advance().await.unwrap();
936        assert!(iter.get().is_none());
937    }
938
939    #[fuchsia::test]
940    async fn test_two_inserts() {
941        let skip_list = SkipListLayer::new(100);
942        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2)];
943        {
944            let mut iter = SkipListLayerIterMut::new(&skip_list, std::ops::Bound::Unbounded);
945            iter.insert(items[0].clone());
946            iter.insert(items[1].clone());
947        }
948
949        let mut iter = skip_list.seek(Bound::Unbounded);
950        let ItemRef { key, value, .. } = iter.get().expect("missing item");
951        assert_eq!((key, value), (&items[0].key, &items[0].value));
952        iter.advance().await.unwrap();
953        let ItemRef { key, value, .. } = iter.get().expect("missing item");
954        assert_eq!((key, value), (&items[1].key, &items[1].value));
955    }
956
957    #[fuchsia::test]
958    async fn test_erase_after_insert() {
959        let skip_list = SkipListLayer::new(100);
960        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2)];
961        skip_list.insert(items[1].clone()).expect("insert error");
962        {
963            let mut iter = SkipListLayerIterMut::new(&skip_list, std::ops::Bound::Unbounded);
964            iter.insert(items[0].clone());
965            iter.erase();
966        }
967
968        let mut iter = skip_list.seek(Bound::Unbounded);
969        let ItemRef { key, value, .. } = iter.get().expect("missing item");
970        assert_eq!((key, value), (&items[0].key, &items[0].value));
971        iter.advance().await.unwrap();
972        assert!(iter.get().is_none());
973    }
974
975    #[fuchsia::test]
976    async fn test_insert_after_erase() {
977        let skip_list = SkipListLayer::new(100);
978        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2)];
979        skip_list.insert(items[1].clone()).expect("insert error");
980        {
981            let mut iter = SkipListLayerIterMut::new(&skip_list, std::ops::Bound::Unbounded);
982            iter.erase();
983            iter.insert(items[0].clone());
984        }
985
986        let mut iter = skip_list.seek(Bound::Unbounded);
987        let ItemRef { key, value, .. } = iter.get().expect("missing item");
988        assert_eq!((key, value), (&items[0].key, &items[0].value));
989        iter.advance().await.unwrap();
990        assert!(iter.get().is_none());
991    }
992
993    #[fuchsia::test]
994    async fn test_insert_erase_insert() {
995        let skip_list = SkipListLayer::new(100);
996        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2), Item::new(TestKey(3), 3)];
997        skip_list.insert(items[0].clone()).expect("insert error");
998        {
999            let mut iter = SkipListLayerIterMut::new(&skip_list, std::ops::Bound::Unbounded);
1000            iter.insert(items[1].clone());
1001            iter.erase();
1002            iter.insert(items[2].clone());
1003        }
1004
1005        let mut iter = skip_list.seek(Bound::Unbounded);
1006        let ItemRef { key, value, .. } = iter.get().expect("missing item");
1007        assert_eq!((key, value), (&items[1].key, &items[1].value));
1008        iter.advance().await.unwrap();
1009        let ItemRef { key, value, .. } = iter.get().expect("missing item");
1010        assert_eq!((key, value), (&items[2].key, &items[2].value));
1011    }
1012
1013    #[fuchsia::test]
1014    async fn test_two_erase_erases() {
1015        let skip_list = SkipListLayer::new(100);
1016        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2), Item::new(TestKey(3), 3)];
1017        skip_list.insert(items[0].clone()).expect("insert error");
1018        skip_list.insert(items[1].clone()).expect("insert error");
1019        skip_list.insert(items[2].clone()).expect("insert error");
1020        {
1021            let mut iter = SkipListLayerIterMut::new(&skip_list, std::ops::Bound::Unbounded);
1022            iter.erase();
1023            iter.erase();
1024        }
1025
1026        let mut iter = skip_list.seek(Bound::Unbounded);
1027        let ItemRef { key, value, .. } = iter.get().expect("missing item");
1028        assert_eq!((key, value), (&items[2].key, &items[2].value));
1029        iter.advance().await.unwrap();
1030        assert!(iter.get().is_none());
1031    }
1032
1033    #[fuchsia::test]
1034    async fn test_readers_not_blocked_by_writers() {
1035        let skip_list = SkipListLayer::new(100);
1036        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2)];
1037        skip_list.insert(items[1].clone()).expect("insert error");
1038
1039        let mut iter = skip_list.seek(Bound::Unbounded);
1040        let ItemRef { key, value, .. } = iter.get().expect("missing item");
1041        assert_eq!((key, value), (&items[1].key, &items[1].value));
1042
1043        let mut iter2 = skip_list.seek(Bound::Unbounded);
1044        let ItemRef { key, value, .. } = iter2.get().expect("missing item");
1045        assert_eq!((key, value), (&items[1].key, &items[1].value));
1046
1047        join!(async { skip_list.insert(items[0].clone()).expect("insert error") }, async {
1048            loop {
1049                let iter = skip_list.seek(Bound::Unbounded);
1050                let ItemRef { key, .. } = iter.get().expect("missing item");
1051                if key == &items[0].key {
1052                    break;
1053                }
1054            }
1055            iter.advance().await.unwrap();
1056            assert!(iter.get().is_none());
1057            std::mem::drop(iter);
1058            iter2.advance().await.unwrap();
1059            assert!(iter2.get().is_none());
1060            std::mem::drop(iter2);
1061        });
1062    }
1063
1064    #[fuchsia::test(threads = 20)]
1065    async fn test_many_readers_and_writers() {
1066        let skip_list = SkipListLayer::new(100);
1067        join_all(
1068            (0..10)
1069                .map(|i| {
1070                    let skip_list_clone = skip_list.clone();
1071                    fasync::Task::spawn(async move {
1072                        for j in 0..10 {
1073                            skip_list_clone
1074                                .insert(Item::new(TestKey(i * 100 + j), i))
1075                                .expect("insert error");
1076                        }
1077                    })
1078                })
1079                .chain((0..10).map(|_| {
1080                    let skip_list_clone = skip_list.clone();
1081                    fasync::Task::spawn(async move {
1082                        for _ in 0..300 {
1083                            let mut iter = skip_list_clone.seek(Bound::Unbounded);
1084                            let mut last_item: Option<TestKey> = None;
1085                            while let Some(item) = iter.get() {
1086                                if let Some(last) = last_item {
1087                                    assert!(item.key > &last);
1088                                }
1089                                last_item = Some(item.key.clone());
1090                                iter.advance().await.expect("advance failed");
1091                            }
1092                        }
1093                    })
1094                })),
1095        )
1096        .await;
1097    }
1098
1099    #[fuchsia::test]
1100    async fn test_insert_advance_erase() {
1101        let skip_list = SkipListLayer::new(100);
1102        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2), Item::new(TestKey(3), 3)];
1103        skip_list.insert(items[1].clone()).expect("insert error");
1104        skip_list.insert(items[2].clone()).expect("insert error");
1105
1106        assert_eq!(skip_list.len(), 2);
1107
1108        {
1109            let mut iter = SkipListLayerIterMut::new(&skip_list, std::ops::Bound::Unbounded);
1110            iter.insert(items[0].clone());
1111            iter.advance();
1112            iter.erase();
1113        }
1114
1115        assert_eq!(skip_list.len(), 2);
1116
1117        let mut iter = skip_list.seek(Bound::Unbounded);
1118        let ItemRef { key, value, .. } = iter.get().expect("missing item");
1119        assert_eq!((key, value), (&items[0].key, &items[0].value));
1120        iter.advance().await.unwrap();
1121        let ItemRef { key, value, .. } = iter.get().expect("missing item");
1122        assert_eq!((key, value), (&items[1].key, &items[1].value));
1123        iter.advance().await.unwrap();
1124        assert!(iter.get().is_none());
1125    }
1126
1127    #[fuchsia::test]
1128    async fn test_seek_excluded() {
1129        let skip_list = SkipListLayer::new(100);
1130        let items = [Item::new(TestKey(1), 1), Item::new(TestKey(2), 2)];
1131        skip_list.insert(items[0].clone()).expect("insert error");
1132        skip_list.insert(items[1].clone()).expect("insert error");
1133        let iter = skip_list.seek(Bound::Excluded(&items[0].key));
1134        let ItemRef { key, value, .. } = iter.get().expect("missing item");
1135        assert_eq!((key, value), (&items[1].key, &items[1].value));
1136    }
1137
1138    #[fuchsia::test]
1139    fn test_insert_race() {
1140        for _ in 0..1000 {
1141            let skip_list = SkipListLayer::new(100);
1142            skip_list.insert(Item::new(TestKey(2), 2)).expect("insert error");
1143
1144            let skip_list_clone = skip_list.clone();
1145            let thread1 = std::thread::spawn(move || {
1146                skip_list_clone.insert(Item::new(TestKey(1), 1)).expect("insert error")
1147            });
1148            let thread2 = std::thread::spawn(move || {
1149                let iter = SkipListLayerIter::new(&skip_list, Bound::Included(&TestKey(2)));
1150                match iter.get() {
1151                    Some(ItemRef { key: TestKey(2), .. }) => {}
1152                    result => assert!(false, "{:?}", result),
1153                }
1154            });
1155            thread1.join().unwrap();
1156            thread2.join().unwrap();
1157        }
1158    }
1159
1160    #[fuchsia::test]
1161    fn test_replace_or_insert_multi_thread() {
1162        let skip_list = SkipListLayer::new(100);
1163        skip_list.insert(Item::new(TestKey(1), 1)).expect("insert error");
1164        skip_list.insert(Item::new(TestKey(2), 2)).expect("insert error");
1165        skip_list.insert(Item::new(TestKey(3), 3)).expect("insert error");
1166        skip_list.insert(Item::new(TestKey(4), 4)).expect("insert error");
1167
1168        // Set up a number of threads that are repeatedly replacing the '3' key.
1169        let mut threads = Vec::new();
1170        for i in 0..200 {
1171            let skip_list_clone = skip_list.clone();
1172            threads.push(std::thread::spawn(move || {
1173                skip_list_clone.replace_or_insert(Item::new(TestKey(3), i));
1174            }));
1175        }
1176
1177        // Have one thread repeatedly checking the list.
1178        let _checker_thread = std::thread::spawn(move || {
1179            loop {
1180                let mut iter = SkipListLayerIter::new(&skip_list, Bound::Included(&TestKey(2)));
1181                assert_matches!(iter.get(), Some(ItemRef { key: TestKey(2), .. }));
1182                iter.advance().now_or_never().unwrap().unwrap();
1183                assert_matches!(iter.get(), Some(ItemRef { key: TestKey(3), .. }));
1184                iter.advance().now_or_never().unwrap().unwrap();
1185                assert_matches!(iter.get(), Some(ItemRef { key: TestKey(4), .. }));
1186            }
1187        });
1188
1189        for thread in threads {
1190            thread.join().unwrap();
1191        }
1192    }
1193}