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