1mod bloom_filter;
18pub mod cache;
19pub mod merge;
20pub mod persistent_layer;
21pub mod skip_list_layer;
22pub mod types;
23
24#[cfg(any(test, fuzz))]
25pub mod testing;
26
27use crate::drop_event::DropEvent;
28use crate::log::*;
29use crate::metrics::DurationMeasureScope;
30use crate::object_handle::{LayerObject, WriteBytes};
31use crate::object_store::ObjectStore;
32use crate::serialized_types::{LATEST_VERSION, Version};
33
34use anyhow::Error;
35use cache::{ObjectCache, ObjectCacheResult};
36
37use fuchsia_inspect::HistogramProperty;
38use fuchsia_sync::RwLock;
39use fxfs_crypto::Crypt;
40use persistent_layer::{PersistentLayer, PersistentLayerWriter};
41use skip_list_layer::SkipListLayer;
42use std::fmt;
43use std::ops::Bound;
44use std::sync::atomic::{AtomicUsize, Ordering};
45use std::sync::{Arc, Mutex};
46use storage_units::BlockSize;
47use types::{
48 Existence, Item, ItemRef, Key, Layer, LayerIterator, LayerKey, LayerWriter, MaybeContainsKey,
49 MergeType, MergeableKey, OrdLowerBound, Value,
50};
51
52pub use merge::Query;
53
54const SKIP_LIST_LAYER_ITEMS: usize = 512;
55
56pub use persistent_layer::{
58 LayerHeader as PersistentLayerHeader, LayerHeaderV39 as PersistentLayerHeaderV39,
59 LayerInfo as PersistentLayerInfo, LayerInfoV39 as PersistentLayerInfoV39, SyncPersistentLayer,
60 layer_from_handle, open_layers,
61};
62
63pub async fn layers_from_handles<K: Key, V: Value>(
64 handles: impl IntoIterator<Item = impl LayerObject + 'static>,
65) -> Result<Vec<Arc<dyn Layer<K, V>>>, Error> {
66 let mut layers = Vec::new();
67 for handle in handles {
68 layers.push(PersistentLayer::open(handle).await?);
69 }
70 Ok(layers)
71}
72
73#[derive(Eq, PartialEq, Debug)]
74pub enum Operation {
75 Insert,
76 ReplaceOrInsert,
77 MergeInto,
78}
79
80pub type MutationCallback<K, V> = Option<Box<dyn Fn(Operation, &Item<K, V>) + Send + Sync>>;
81
82struct Inner<K, V> {
83 mutable_layer: Arc<SkipListLayer<K, V>>,
84 layers: Vec<Arc<dyn Layer<K, V>>>,
85 mutation_callback: MutationCallback<K, V>,
86}
87
88pub const LOG2_HISTOGRAM_BUCKETS: usize = 32;
89
90pub struct CompactionCounters {
92 pub compactions: u64,
94 pub compaction_bytes_written: u64,
96 pub compaction_time_ns: u64,
98 pub total_layers_added: u64,
100 pub max_layer_count: u64,
102 pub layer_size_histogram: [u64; LOG2_HISTOGRAM_BUCKETS],
104}
105
106impl Default for CompactionCounters {
107 fn default() -> Self {
108 Self {
109 compactions: 0,
110 compaction_bytes_written: 0,
111 compaction_time_ns: 0,
112 total_layers_added: 0,
113 max_layer_count: 0,
114 layer_size_histogram: [0; LOG2_HISTOGRAM_BUCKETS],
115 }
116 }
117}
118
119pub struct TreeCounters {
121 pub num_seeks: AtomicUsize,
123 pub layer_files_total: AtomicUsize,
126 pub layer_files_skipped: AtomicUsize,
128 pub bloom_filter_false_positives: AtomicUsize,
133 pub bloom_filter_negatives: AtomicUsize,
137 pub excessive_hash_partitions: AtomicUsize,
139 pub compaction: Mutex<CompactionCounters>,
141}
142
143impl Default for TreeCounters {
144 fn default() -> Self {
145 Self {
146 num_seeks: AtomicUsize::new(0),
147 layer_files_total: AtomicUsize::new(0),
148 layer_files_skipped: AtomicUsize::new(0),
149 bloom_filter_false_positives: AtomicUsize::new(0),
150 bloom_filter_negatives: AtomicUsize::new(0),
151 excessive_hash_partitions: AtomicUsize::new(0),
152 compaction: Mutex::new(CompactionCounters::default()),
153 }
154 }
155}
156
157#[fxfs_trace::trace]
159pub async fn compact_with_iterator<K: Key, V: Value, W: WriteBytes + Send>(
160 mut iterator: impl LayerIterator<K, V>,
161 num_items: usize,
162 writer: W,
163 block_size: BlockSize,
164 mut yielder: Option<impl Yielder>,
165) -> Result<u64, Error> {
166 let mut writer = PersistentLayerWriter::<W, K, V>::new(writer, num_items, block_size).await?;
167 while let Some(item_ref) = iterator.get() {
168 debug!(item_ref:?; "compact: writing");
169 writer.write(item_ref).await?;
170 iterator.advance().await?;
171 if let Some(y) = yielder.as_mut() {
172 y.yield_now().await;
173 }
174 }
175 writer.complete().await
176}
177
178pub struct LSMTree<K, V> {
182 data: RwLock<Inner<K, V>>,
183 merge_fn: merge::MergeFn<K, V>,
184 cache: Option<Box<dyn ObjectCache<K, V>>>,
185 counters: Arc<TreeCounters>,
186}
187
188#[fxfs_trace::trace]
189impl<'tree, K: MergeableKey, V: Value> LSMTree<K, V> {
190 pub fn new(merge_fn: merge::MergeFn<K, V>, cache: Option<Box<dyn ObjectCache<K, V>>>) -> Self {
192 let counters = TreeCounters::default();
193 counters.compaction.lock().unwrap().max_layer_count = 1;
194 LSMTree {
195 data: RwLock::new(Inner {
196 mutable_layer: Self::new_mutable_layer(),
197 layers: Vec::new(),
198 mutation_callback: None,
199 }),
200 merge_fn,
201 cache,
202 counters: Arc::new(counters),
203 }
204 }
205
206 pub async fn open(
208 merge_fn: merge::MergeFn<K, V>,
209 handles: impl IntoIterator<Item = impl LayerObject + 'static>,
210 cache: Option<Box<dyn ObjectCache<K, V>>>,
211 ) -> Result<Self, Error> {
212 let layers = layers_from_handles(handles).await?;
213 let max_layer_count = layers.len() as u64 + 1;
214 let counters = TreeCounters::default();
215 counters.compaction.lock().unwrap().max_layer_count = max_layer_count;
216 Ok(LSMTree {
217 data: RwLock::new(Inner {
218 mutable_layer: Self::new_mutable_layer(),
219 layers,
220 mutation_callback: None,
221 }),
222 merge_fn,
223 cache,
224 counters: Arc::new(counters),
225 })
226 }
227
228 pub fn set_layers(&self, layers: Vec<Arc<dyn Layer<K, V>>>) {
230 let mut data = self.data.write();
231 data.layers = layers;
232 let layer_count = data.layers.len() + 1;
233 let mut counters = self.counters.compaction.lock().unwrap();
234 counters.max_layer_count = std::cmp::max(counters.max_layer_count, layer_count as u64);
235 }
236
237 pub async fn append_layers(
243 &self,
244 store: &Arc<ObjectStore>,
245 object_ids: impl IntoIterator<Item = u64>,
246 crypt: Option<Arc<dyn Crypt>>,
247 ) -> Result<u64, Error> {
248 let (layers, total_size) = open_layers(store, object_ids, crypt).await?;
249 self.append_open_layers(layers);
250 Ok(total_size)
251 }
252
253 pub fn append_open_layers(&self, mut layers: Vec<Arc<dyn Layer<K, V>>>) {
255 let mut data = self.data.write();
256 data.layers.append(&mut layers);
257 let layer_count = data.layers.len() + 1;
258 let mut counters = self.counters.compaction.lock().unwrap();
259 counters.max_layer_count = std::cmp::max(counters.max_layer_count, layer_count as u64);
260 }
261
262 pub fn reset_immutable_layers(&self) {
264 self.data.write().layers = Vec::new();
265 }
266
267 pub fn seal(&self) {
269 let mut data = self.data.write();
272 let layer = std::mem::replace(&mut data.mutable_layer, Self::new_mutable_layer());
273 data.layers.insert(0, layer);
274 let layer_count = data.layers.len() + 1;
275 let mut counters = self.counters.compaction.lock().unwrap();
276 counters.max_layer_count = std::cmp::max(counters.max_layer_count, layer_count as u64);
277 counters.total_layers_added += 1;
278 }
279
280 pub fn reset(&self) {
282 let mut data = self.data.write();
283 data.layers = Vec::new();
284 data.mutable_layer = Self::new_mutable_layer();
285 }
286
287 pub fn clear_cache(&self) {
289 if let Some(cache) = &self.cache {
290 cache.clear();
291 }
292 for layer in self.immutable_layer_set().layers {
293 layer.clear_cached_data();
294 }
295 }
296
297 pub fn cache_len(&self) -> usize {
298 self.cache.as_ref().map_or(0, |c| c.len())
299 }
300
301 pub fn report_compaction_metrics(
302 &self,
303 bytes_written: u64,
304 duration: std::time::Duration,
305 layer_count: usize,
306 ) {
307 let mut counters = self.counters.compaction.lock().unwrap();
308 counters.compactions += 1;
309 counters.compaction_bytes_written += bytes_written;
310 counters.compaction_time_ns += duration.as_nanos() as u64;
311
312 let bucket = if bytes_written == 0 {
313 0
314 } else {
315 std::cmp::min(LOG2_HISTOGRAM_BUCKETS - 1, 63 - bytes_written.leading_zeros() as usize)
316 };
317 counters.layer_size_histogram[bucket] += 1;
318
319 crate::metrics::lsm_tree_metrics().compaction_layer_stack_depth.insert(layer_count as u64);
320 }
321
322 pub fn compaction_bytes_written(&self) -> u64 {
323 self.counters.compaction.lock().unwrap().compaction_bytes_written
324 }
325
326 #[cfg(test)]
327 pub fn counters(&self) -> &TreeCounters {
328 &self.counters
329 }
330
331 pub fn empty_layer_set(&self) -> LayerSet<K, V> {
333 LayerSet { layers: Vec::new(), merge_fn: self.merge_fn, counters: self.counters.clone() }
334 }
335
336 pub fn add_all_layers_to_layer_set(&self, layer_set: &mut LayerSet<K, V>) {
338 let data = self.data.read();
339 layer_set.layers.reserve_exact(data.layers.len() + 1);
340 layer_set
341 .layers
342 .push(LockedLayer::from(data.mutable_layer.clone() as Arc<dyn Layer<K, V>>));
343 for layer in &data.layers {
344 layer_set.layers.push(layer.clone().into());
345 }
346 }
347
348 pub fn layer_set(&self) -> LayerSet<K, V> {
351 let mut layer_set = self.empty_layer_set();
352 self.add_all_layers_to_layer_set(&mut layer_set);
353 layer_set
354 }
355
356 pub fn immutable_layer_set(&self) -> LayerSet<K, V> {
360 let data = self.data.read();
361 let mut layers = Vec::with_capacity(data.layers.len());
362 for layer in &data.layers {
363 layers.push(layer.clone().into());
364 }
365 LayerSet { layers, merge_fn: self.merge_fn, counters: self.counters.clone() }
366 }
367
368 pub fn immutable_layer_count(&self) -> usize {
370 self.data.read().layers.len()
371 }
372
373 pub fn insert(&self, item: Item<K, V>) -> Result<(), Error> {
376 let _measure = DurationMeasureScope::new(&crate::metrics::lsm_tree_metrics().insert);
377
378 let item_dup = if self.is_cacheable(&item.key) { Some(item.clone()) } else { None };
379
380 {
381 let data = self.data.read();
383 if let Some(mutation_callback) = data.mutation_callback.as_ref() {
384 mutation_callback(Operation::Insert, &item);
385 }
386 data.mutable_layer.insert(item)?;
387 }
388
389 if let Some(item) = item_dup {
390 let val = if item.value == V::DELETED_MARKER { None } else { Some(item.value) };
391 self.invalidate_cache(&item.key, val);
392 }
393 Ok(())
394 }
395
396 pub fn replace_or_insert(&self, item: Item<K, V>) {
398 let _measure =
399 DurationMeasureScope::new(&crate::metrics::lsm_tree_metrics().replace_or_insert);
400
401 let item_dup = if self.is_cacheable(&item.key) { Some(item.clone()) } else { None };
402
403 {
404 let data = self.data.read();
406 if let Some(mutation_callback) = data.mutation_callback.as_ref() {
407 mutation_callback(Operation::ReplaceOrInsert, &item);
408 }
409 data.mutable_layer.replace_or_insert(item);
410 }
411
412 if let Some(item) = item_dup {
413 let val = if item.value == V::DELETED_MARKER { None } else { Some(item.value) };
414 self.invalidate_cache(&item.key, val);
415 }
416 }
417
418 pub fn merge_into(&self, item: Item<K, V>, lower_bound: &K) {
420 let _measure = DurationMeasureScope::new(&crate::metrics::lsm_tree_metrics().merge_into);
421
422 let key = if self.is_cacheable(&item.key) { Some(item.key.clone()) } else { None };
423 {
424 let data = self.data.read();
426 if let Some(mutation_callback) = data.mutation_callback.as_ref() {
427 mutation_callback(Operation::MergeInto, &item);
428 }
429 data.mutable_layer.merge_into(item, lower_bound, self.merge_fn);
430 }
431
432 if let Some(key) = key {
433 self.invalidate_cache(&key, None);
434 }
435 }
436
437 #[inline(always)]
443 fn is_cacheable(&self, key: &K) -> bool {
444 if let Some(cache) = &self.cache { cache.is_cacheable(key) } else { false }
445 }
446
447 #[inline(always)]
452 fn invalidate_cache(&self, key: &K, value: Option<V>) {
453 if let Some(cache) = &self.cache {
454 cache.invalidate(key, value);
455 }
456 }
457
458 pub async fn find_map<R, F>(&self, search_key: &K, f: F) -> Result<Option<R>, Error>
464 where
465 K: Eq,
466 F: FnOnce(ItemRef<'_, K, V>) -> R,
467 {
468 let _measure = DurationMeasureScope::new(&crate::metrics::lsm_tree_metrics().find);
469 let mut token = if let Some(cache) = &self.cache {
473 match cache.lookup_or_reserve(search_key) {
474 ObjectCacheResult::Value(value) => {
475 if *value == V::DELETED_MARKER {
476 return Ok(None);
477 } else {
478 return Ok(Some(f(ItemRef { key: search_key, value: &value })));
479 }
480 }
481 ObjectCacheResult::Placeholder(token) => Some(token),
482 ObjectCacheResult::NoCache => None,
483 }
484 } else {
485 None
486 };
487 let layer_set = self.layer_set();
488 let result = layer_set
489 .find_map(search_key, |item_ref| {
490 if let Some(token) = token.take() {
491 token.complete(Some(item_ref.value));
492 }
493 f(item_ref)
494 })
495 .await?;
496 Ok(result)
497 }
498
499 pub fn find(
504 &self,
505 search_key: &K,
506 ) -> impl Future<Output = Result<Option<Item<K, V>>, Error>> + Send
507 where
508 K: Eq,
509 {
510 self.find_map(search_key, |item| Item { key: item.key.clone(), value: item.value.clone() })
511 }
512
513 pub fn find_value(
518 &self,
519 search_key: &K,
520 ) -> impl Future<Output = Result<Option<V>, Error>> + Send
521 where
522 K: Eq,
523 {
524 self.find_map(search_key, |item| item.value.clone())
525 }
526
527 pub async fn exists(&self, search_key: &K) -> Result<bool, Error>
531 where
532 K: Eq,
533 {
534 Ok(self.find_map(search_key, |_| ()).await?.is_some())
535 }
536
537 pub fn mutable_layer(&self) -> Arc<SkipListLayer<K, V>> {
538 self.data.read().mutable_layer.clone()
539 }
540
541 pub fn set_mutation_callback(&self, mutation_callback: MutationCallback<K, V>) {
545 self.data.write().mutation_callback = mutation_callback;
546 }
547
548 pub fn get_earliest_version(&self) -> Version {
550 let mut earliest_version = LATEST_VERSION;
551 for layer in self.layer_set().layers {
552 let layer_version = layer.get_version();
553 if layer_version < earliest_version {
554 earliest_version = layer_version;
555 }
556 }
557 return earliest_version;
558 }
559
560 pub fn new_mutable_layer() -> Arc<SkipListLayer<K, V>> {
562 SkipListLayer::new(SKIP_LIST_LAYER_ITEMS)
563 }
564
565 pub fn set_mutable_layer(&self, layer: Arc<SkipListLayer<K, V>>) {
567 self.data.write().mutable_layer = layer;
568 }
569
570 pub fn record_inspect_data(&self, root: &fuchsia_inspect::Node) {
572 let layer_set = self.layer_set();
573 root.record_child("layers", move |node| {
574 let mut index = 0;
575 for layer in layer_set.layers {
576 node.record_child(format!("{index}"), move |node| {
577 layer.1.record_inspect_data(node)
578 });
579 index += 1;
580 }
581 });
582 {
583 let counters = self.counters.compaction.lock().unwrap();
584 root.record_uint("num_seeks", self.counters.num_seeks.load(Ordering::Relaxed) as u64);
585 root.record_double("bloom_filter_success_percent", {
586 let layer_files_total = self.counters.layer_files_total.load(Ordering::Relaxed);
587 let layer_files_skipped = self.counters.layer_files_skipped.load(Ordering::Relaxed);
588 if layer_files_total == 0 {
589 0.0
590 } else {
591 (layer_files_skipped as f64 * 100.0) / (layer_files_total as f64)
592 }
593 });
594 root.record_double("bloom_filter_false_positive_percent", {
601 let false_positives =
602 self.counters.bloom_filter_false_positives.load(Ordering::Relaxed);
603 let negatives = self.counters.bloom_filter_negatives.load(Ordering::Relaxed);
604 let total_negatives = false_positives + negatives;
605 if total_negatives == 0 {
606 0.0
607 } else {
608 (false_positives as f64 * 100.0) / (total_negatives as f64)
609 }
610 });
611 root.record_uint(
612 "excessive_hash_partitions",
613 self.counters.excessive_hash_partitions.load(Ordering::Relaxed) as u64,
614 );
615 root.record_uint("compactions", counters.compactions);
616 root.record_uint("compaction_bytes_written", counters.compaction_bytes_written);
617 root.record_uint("compaction_time_ns", counters.compaction_time_ns);
618 root.record_uint("total_layers_added", counters.total_layers_added);
619 root.record_uint("max_layer_count", counters.max_layer_count);
620
621 let layer_sizes = root.create_uint_exponential_histogram(
622 "layer_size_histogram_log2",
623 fuchsia_inspect::ExponentialHistogramParams {
624 floor: 1,
625 initial_step: 1,
626 step_multiplier: 2,
627 buckets: LOG2_HISTOGRAM_BUCKETS,
628 },
629 );
630 for (i, count) in counters.layer_size_histogram.iter().enumerate() {
631 layer_sizes.insert_multiple(1u64 << i, *count as usize);
632 }
633 root.record(layer_sizes);
634 }
635 }
636}
637
638pub struct LockedLayer<K, V>(Arc<DropEvent>, Arc<dyn Layer<K, V>>);
641
642impl<K, V> LockedLayer<K, V> {
643 pub async fn close_layer(self) {
644 let layer = self.1;
645 std::mem::drop(self.0);
646 layer.close().await;
647 }
648}
649
650impl<K, V> From<Arc<dyn Layer<K, V>>> for LockedLayer<K, V> {
651 fn from(layer: Arc<dyn Layer<K, V>>) -> Self {
652 let event = layer.lock().unwrap();
653 Self(event, layer)
654 }
655}
656
657impl<K, V> std::ops::Deref for LockedLayer<K, V> {
658 type Target = Arc<dyn Layer<K, V>>;
659
660 fn deref(&self) -> &Self::Target {
661 &self.1
662 }
663}
664
665impl<K, V> AsRef<dyn Layer<K, V>> for LockedLayer<K, V> {
666 fn as_ref(&self) -> &(dyn Layer<K, V> + 'static) {
667 self.1.as_ref()
668 }
669}
670
671pub struct LayerSet<K, V> {
674 pub layers: Vec<LockedLayer<K, V>>,
675 merge_fn: merge::MergeFn<K, V>,
676 counters: Arc<TreeCounters>,
677}
678
679impl<K: Key + LayerKey + OrdLowerBound, V: Value> LayerSet<K, V> {
680 pub fn sum_len(&self) -> usize {
681 let mut size = 0;
682 for layer in &self.layers {
683 size += layer.len()
684 }
685 size
686 }
687
688 pub fn merger(&self) -> merge::Merger<'_, K, V> {
689 merge::Merger::new(
690 self.layers.iter().map(|x| x.as_ref()),
691 self.merge_fn,
692 self.counters.clone(),
693 )
694 }
695
696 pub async fn find_map<R, F>(&self, search_key: &K, f: F) -> Result<Option<R>, Error>
702 where
703 K: Eq,
704 F: FnOnce(ItemRef<'_, K, V>) -> R,
705 {
706 if search_key.merge_type() == MergeType::OptimizedMerge {
707 self.counters.num_seeks.fetch_add(1, Ordering::Relaxed);
708 for layer in &self.layers {
709 self.counters.layer_files_total.fetch_add(1, Ordering::Relaxed);
710 if layer.maybe_contains_key(search_key) == MaybeContainsKey::False {
711 self.counters.layer_files_skipped.fetch_add(1, Ordering::Relaxed);
712 self.counters.bloom_filter_negatives.fetch_add(1, Ordering::Relaxed);
713 continue;
714 }
715 let iter = layer.seek(Bound::Included(search_key)).await?;
716 let found = iter.get().filter(|item_ref| item_ref.key == search_key);
717 if layer.has_bloom_filter() && found.is_none() {
718 self.counters.bloom_filter_false_positives.fetch_add(1, Ordering::Relaxed);
719 }
720 if let Some(item_ref) = found {
721 if *item_ref.value == V::DELETED_MARKER {
722 return Ok(None);
723 } else {
724 return Ok(Some(f(item_ref)));
725 }
726 }
727 }
728 return Ok(None);
729 }
730
731 let mut merger = self.merger();
732 Ok(match merger.query(Query::Point(search_key)).await?.get() {
733 Some(item_ref)
734 if item_ref.key == search_key && *item_ref.value != V::DELETED_MARKER =>
735 {
736 Some(f(item_ref))
737 }
738 _ => None,
739 })
740 }
741
742 pub async fn key_exists(&self, key: &K) -> Result<Existence, Error> {
744 for l in &self.layers {
745 match l.key_exists(key).await? {
746 e @ (Existence::Exists | Existence::MaybeExists) => return Ok(e),
747 _ => {}
748 }
749 }
750 Ok(Existence::Missing)
751 }
752}
753
754impl<K, V> fmt::Debug for LayerSet<K, V> {
755 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
756 fmt.debug_list()
757 .entries(self.layers.iter().map(|l| {
758 if let Some(handle) = l.handle() {
759 format!("{}", handle.object_id())
760 } else {
761 format!("{:?}", Arc::as_ptr(l))
762 }
763 }))
764 .finish()
765 }
766}
767
768pub trait Yielder: Send {
770 fn yield_now(&mut self) -> impl Future<Output = ()> + Send;
771}
772
773#[cfg(test)]
774mod tests {
775 use super::{LSMTree, Yielder, compact_with_iterator};
776 use crate::drop_event::DropEvent;
777 use crate::lsm_tree::cache::{ObjectCache, ObjectCachePlaceholder, ObjectCacheResult};
778 use crate::lsm_tree::merge::{ItemOp, MergeLayerIterator, MergeResult};
779 use crate::lsm_tree::types::{
780 BoxedLayerIterator, Existence, Item, ItemRef, Key, Layer, LayerIterator, MaybeContainsKey,
781 Value,
782 };
783 use crate::lsm_tree::{Query, layers_from_handles};
784 use crate::object_handle::ObjectHandle;
785 use crate::serialized_types::{LATEST_VERSION, Version};
786 use crate::testing::fake_object::{FakeObject, FakeObjectHandle};
787 use crate::testing::writer::Writer;
788 use anyhow::{Error, anyhow};
789 use async_trait::async_trait;
790
791 use fuchsia_inspect::hierarchy::{DiagnosticsHierarchy, Property};
792 use fuchsia_inspect::{Inspector, reader};
793 use fuchsia_sync::{Mutex, MutexGuard};
794 use futures::future::BoxFuture;
795 use rand::rng;
796 use rand::seq::SliceRandom as _;
797 use std::sync::Arc;
798 use std::sync::atomic::Ordering;
799 use test_util::assert_near;
800
801 use super::testing::TestKey;
802
803 fn emit_left_merge_fn(
804 _left: &MergeLayerIterator<'_, TestKey, u64>,
805 _right: &MergeLayerIterator<'_, TestKey, u64>,
806 ) -> MergeResult<TestKey, u64> {
807 MergeResult::EmitLeft
808 }
809
810 fn emit_left_i32_merge_fn(
811 _left: &MergeLayerIterator<'_, i32, u64>,
812 _right: &MergeLayerIterator<'_, i32, u64>,
813 ) -> MergeResult<i32, u64> {
814 MergeResult::EmitLeft
815 }
816
817 fn merge_sum_i32(
818 left: &MergeLayerIterator<'_, i32, u64>,
819 right: &MergeLayerIterator<'_, i32, u64>,
820 ) -> MergeResult<i32, u64> {
821 if left.key() == right.key() {
822 MergeResult::Other {
823 emit: None,
824 left: ItemOp::Discard,
825 right: ItemOp::Replace(
826 Item::new(*left.key(), *left.value() + *right.value()).boxed(),
827 ),
828 }
829 } else {
830 MergeResult::EmitLeft
831 }
832 }
833
834 impl Value for u64 {
835 const DELETED_MARKER: Self = 0;
836 }
837
838 struct NoOpYielder;
839 impl Yielder for NoOpYielder {
840 async fn yield_now(&mut self) {}
841 }
842
843 #[fuchsia::test]
844 async fn test_iteration() {
845 let tree = LSMTree::new(emit_left_merge_fn, None);
846 let items = [Item::new(TestKey(1..1), 1), Item::new(TestKey(2..2), 2)];
847 tree.insert(items[0].clone()).expect("insert error");
848 tree.insert(items[1].clone()).expect("insert error");
849 let layers = tree.layer_set();
850 let mut merger = layers.merger();
851 let mut iter = merger.query(Query::FullScan).await.expect("seek failed");
852 let ItemRef { key, value, .. } = iter.get().expect("missing item");
853 assert_eq!((key, value), (&items[0].key, &items[0].value));
854 iter.advance().await.expect("advance failed");
855 let ItemRef { key, value, .. } = iter.get().expect("missing item");
856 assert_eq!((key, value), (&items[1].key, &items[1].value));
857 iter.advance().await.expect("advance failed");
858 assert!(iter.get().is_none());
859 }
860
861 #[fuchsia::test]
862 async fn test_compact() {
863 let tree = LSMTree::new(emit_left_merge_fn, None);
864 let items = [
865 Item::new(TestKey(1..1), 1),
866 Item::new(TestKey(2..2), 2),
867 Item::new(TestKey(3..3), 3),
868 Item::new(TestKey(4..4), 4),
869 ];
870 tree.insert(items[0].clone()).expect("insert error");
871 tree.insert(items[1].clone()).expect("insert error");
872 tree.seal();
873 tree.insert(items[2].clone()).expect("insert error");
874 tree.insert(items[3].clone()).expect("insert error");
875 tree.seal();
876 let object = Arc::new(FakeObject::new());
877 let handle = FakeObjectHandle::new(object.clone());
878 {
879 let layer_set = tree.immutable_layer_set();
880 let mut merger = layer_set.merger();
881 let iter = merger.query(Query::FullScan).await.expect("create merger");
882 compact_with_iterator(
883 iter,
884 items.len(),
885 Writer::new(&handle).await,
886 handle.block_size(),
887 Option::<NoOpYielder>::None,
888 )
889 .await
890 .expect("compact failed");
891 }
892 tree.set_layers(layers_from_handles([handle]).await.expect("layers_from_handles failed"));
893 let handle = FakeObjectHandle::new(object.clone());
894 let tree = LSMTree::open(emit_left_merge_fn, [handle], None).await.expect("open failed");
895
896 let layers = tree.layer_set();
897 let mut merger = layers.merger();
898 let mut iter = merger.query(Query::FullScan).await.expect("seek failed");
899 for i in 1..5 {
900 let ItemRef { key, value, .. } = iter.get().expect("missing item");
901 assert_eq!((key, value), (&TestKey(i..i), &i));
902 iter.advance().await.expect("advance failed");
903 }
904 assert!(iter.get().is_none());
905 }
906
907 #[fuchsia::test]
908 async fn test_find() {
909 let items = [
910 Item::new(TestKey(1..1), 1),
911 Item::new(TestKey(2..2), 2),
912 Item::new(TestKey(3..3), 3),
913 Item::new(TestKey(4..4), 4),
914 ];
915 let tree = LSMTree::new(emit_left_merge_fn, None);
916 tree.insert(items[0].clone()).expect("insert error");
917 tree.insert(items[1].clone()).expect("insert error");
918 tree.seal();
919 tree.insert(items[2].clone()).expect("insert error");
920 tree.insert(items[3].clone()).expect("insert error");
921
922 let item = tree.find(&items[1].key).await.expect("find failed").expect("not found");
923 assert_eq!(item, items[1]);
924 assert!(tree.find(&TestKey(100..100)).await.expect("find failed").is_none());
925
926 assert_eq!(tree.find_value(&items[2].key).await.expect("find_value failed"), Some(3));
927 assert_eq!(tree.find_value(&TestKey(100..100)).await.expect("find_value failed"), None);
928
929 assert!(tree.exists(&items[0].key).await.expect("exists failed"));
930 assert!(!tree.exists(&TestKey(100..100)).await.expect("exists failed"));
931
932 assert_eq!(
933 tree.find_map(&items[3].key, |item| item.value * 10).await.expect("find_map failed"),
934 Some(40)
935 );
936 assert_eq!(
937 tree.find_map(&TestKey(100..100), |item| item.value * 10)
938 .await
939 .expect("find_map failed"),
940 None
941 );
942 }
943
944 #[fuchsia::test]
945 async fn test_find_no_return_deleted_values() {
946 let items = [Item::new(TestKey(1..1), 1), Item::new(TestKey(2..2), u64::DELETED_MARKER)];
947 let tree = LSMTree::new(emit_left_merge_fn, None);
948 tree.insert(items[0].clone()).expect("insert error");
949 tree.insert(items[1].clone()).expect("insert error");
950
951 let item = tree.find(&items[0].key).await.expect("find failed").expect("not found");
952 assert_eq!(item, items[0]);
953 assert_eq!(tree.find_value(&items[0].key).await.expect("find_value failed"), Some(1));
954 assert_eq!(
955 tree.find_map(&items[0].key, |item| *item.value).await.expect("find_map failed"),
956 Some(1)
957 );
958 assert!(tree.exists(&items[0].key).await.expect("exists failed"));
959
960 assert!(tree.find(&items[1].key).await.expect("find failed").is_none());
961 assert!(tree.find_value(&items[1].key).await.expect("find_value failed").is_none());
962 assert!(tree.find_map(&items[1].key, |_| ()).await.expect("find_map failed").is_none());
963 assert!(!tree.exists(&items[1].key).await.expect("exists failed"));
964 }
965
966 #[fuchsia::test]
967 async fn test_find_full_merge() {
968 let tree = LSMTree::new(emit_left_i32_merge_fn, None);
969 let items = [
970 Item::new(1, 10),
971 Item::new(2, 20),
972 Item::new(3, 30),
973 Item::new(4, u64::DELETED_MARKER),
974 ];
975 for item in &items {
976 tree.insert(item.clone()).expect("insert error");
977 }
978
979 assert_eq!(tree.find(&1).await.expect("find failed"), Some(items[0].clone()));
980 assert_eq!(tree.find_value(&2).await.expect("find_value failed"), Some(20));
981 assert!(tree.exists(&3).await.expect("exists failed"));
982 assert_eq!(
983 tree.find_map(&3, |item| *item.value * 2).await.expect("find_map failed"),
984 Some(60)
985 );
986
987 assert_eq!(tree.find(&99).await.expect("find failed"), None);
989 assert_eq!(tree.find_value(&99).await.expect("find_value failed"), None);
990 assert!(!tree.exists(&99).await.expect("exists failed"));
991 assert_eq!(tree.find_map(&99, |_| ()).await.expect("find_map failed"), None);
992
993 assert_eq!(tree.find(&4).await.expect("find failed"), None);
995 assert_eq!(tree.find_value(&4).await.expect("find_value failed"), None);
996 assert!(!tree.exists(&4).await.expect("exists failed"));
997 assert_eq!(tree.find_map(&4, |_| ()).await.expect("find_map failed"), None);
998 }
999
1000 #[fuchsia::test]
1001 async fn test_find_full_merge_multi_layer() {
1002 let tree = LSMTree::new(merge_sum_i32, None);
1003
1004 tree.insert(Item::new(1, 100)).expect("insert error");
1006 tree.insert(Item::new(2, 200)).expect("insert error");
1007 tree.insert(Item::new(3, 300)).expect("insert error");
1008
1009 tree.seal();
1010
1011 tree.insert(Item::new(1, 50)).expect("insert error");
1015 tree.insert(Item::new(4, 40)).expect("insert error");
1016
1017 assert_eq!(tree.find_value(&1).await.expect("find_value failed"), Some(150));
1019 assert_eq!(tree.find(&1).await.expect("find failed"), Some(Item::new(1, 150)));
1020 assert!(tree.exists(&1).await.expect("exists failed"));
1021 assert_eq!(
1022 tree.find_map(&1, |item| *item.value * 2).await.expect("find_map failed"),
1023 Some(300)
1024 );
1025
1026 assert_eq!(tree.find_value(&2).await.expect("find_value failed"), Some(200));
1028 assert!(tree.exists(&2).await.expect("exists failed"));
1029
1030 assert_eq!(tree.find_value(&3).await.expect("find_value failed"), Some(300));
1032 assert!(tree.exists(&3).await.expect("exists failed"));
1033
1034 assert_eq!(tree.find_value(&4).await.expect("find_value failed"), Some(40));
1036 assert!(tree.exists(&4).await.expect("exists failed"));
1037
1038 assert_eq!(tree.find_value(&5).await.expect("find_value failed"), None);
1040 assert!(!tree.exists(&5).await.expect("exists failed"));
1041 }
1042
1043 #[fuchsia::test]
1044 async fn test_find_optimized_merge_multi_layer() {
1045 let tree = LSMTree::new(emit_left_merge_fn, None);
1046
1047 tree.insert(Item::new(TestKey(1..1), 10)).expect("insert error");
1049 tree.insert(Item::new(TestKey(2..2), 20)).expect("insert error");
1050 tree.insert(Item::new(TestKey(3..3), 30)).expect("insert error");
1051
1052 tree.seal();
1053
1054 tree.insert(Item::new(TestKey(2..2), 25)).expect("insert error");
1059 tree.insert(Item::new(TestKey(3..3), u64::DELETED_MARKER)).expect("insert error");
1060 tree.insert(Item::new(TestKey(4..4), 40)).expect("insert error");
1061
1062 assert_eq!(tree.find_value(&TestKey(1..1)).await.expect("find_value failed"), Some(10));
1064 assert!(tree.exists(&TestKey(1..1)).await.expect("exists failed"));
1065
1066 assert_eq!(tree.find_value(&TestKey(2..2)).await.expect("find_value failed"), Some(25));
1068 assert!(tree.exists(&TestKey(2..2)).await.expect("exists failed"));
1069
1070 assert_eq!(tree.find(&TestKey(3..3)).await.expect("find failed"), None);
1072 assert_eq!(tree.find_value(&TestKey(3..3)).await.expect("find_value failed"), None);
1073 assert!(!tree.exists(&TestKey(3..3)).await.expect("exists failed"));
1074 assert_eq!(tree.find_map(&TestKey(3..3), |_| ()).await.expect("find_map failed"), None);
1075
1076 assert_eq!(tree.find_value(&TestKey(4..4)).await.expect("find_value failed"), Some(40));
1078 assert!(tree.exists(&TestKey(4..4)).await.expect("exists failed"));
1079
1080 assert_eq!(tree.find_value(&TestKey(5..5)).await.expect("find_value failed"), None);
1082 assert!(!tree.exists(&TestKey(5..5)).await.expect("exists failed"));
1083 }
1084
1085 #[fuchsia::test]
1086 async fn test_find_bloom_filter_rejection() {
1087 struct BloomFilterMockLayer {
1088 drop_event: Mutex<Option<Arc<DropEvent>>>,
1089 }
1090
1091 impl BloomFilterMockLayer {
1092 fn new() -> Self {
1093 Self { drop_event: Mutex::new(Some(Arc::new(DropEvent::new()))) }
1094 }
1095 }
1096
1097 #[async_trait]
1098 impl<K: Key, V: Value> Layer<K, V> for BloomFilterMockLayer {
1099 async fn seek(
1100 &self,
1101 _bound: std::ops::Bound<&K>,
1102 ) -> Result<BoxedLayerIterator<'_, K, V>, Error> {
1103 panic!("seek should not be called on layer skipped by bloom filter");
1104 }
1105
1106 fn lock(&self) -> Option<Arc<DropEvent>> {
1107 self.drop_event.lock().clone()
1108 }
1109
1110 fn len(&self) -> usize {
1111 0
1112 }
1113
1114 async fn close(&self) {}
1115
1116 fn get_version(&self) -> Version {
1117 LATEST_VERSION
1118 }
1119
1120 fn maybe_contains_key(&self, _key: &K) -> MaybeContainsKey {
1121 MaybeContainsKey::False
1122 }
1123
1124 async fn key_exists(&self, _key: &K) -> Result<Existence, Error> {
1125 unimplemented!()
1126 }
1127 }
1128
1129 let tree = LSMTree::new(emit_left_merge_fn, None);
1130 let layer: Arc<dyn Layer<TestKey, u64>> = Arc::new(BloomFilterMockLayer::new());
1131 tree.set_layers(vec![layer]);
1132
1133 let skipped_before = tree.counters.layer_files_skipped.load(Ordering::Relaxed);
1134 let total_before = tree.counters.layer_files_total.load(Ordering::Relaxed);
1135
1136 assert_eq!(tree.find_value(&TestKey(1..1)).await.expect("find failed"), None);
1139 assert!(!tree.exists(&TestKey(1..1)).await.expect("exists failed"));
1140
1141 let skipped_after = tree.counters.layer_files_skipped.load(Ordering::Relaxed);
1142 let total_after = tree.counters.layer_files_total.load(Ordering::Relaxed);
1143
1144 assert_eq!(skipped_after - skipped_before, 2);
1147 assert_eq!(total_after - total_before, 4);
1148 }
1149
1150 #[fuchsia::test]
1151 async fn test_bloom_filter_false_positive_metrics() {
1152 struct MockBloomLayerIterator {
1153 item: Option<Item<TestKey, u64>>,
1154 }
1155
1156 impl LayerIterator<TestKey, u64> for MockBloomLayerIterator {
1157 async fn advance(&mut self) -> Result<(), Error> {
1158 self.item = None;
1159 Ok(())
1160 }
1161
1162 fn advance_dyn<'a>(
1163 &'a mut self,
1164 ) -> Result<Option<BoxFuture<'a, Result<(), Error>>>, Error> {
1165 self.item = None;
1166 Ok(None)
1167 }
1168
1169 fn get(&self) -> Option<ItemRef<'_, TestKey, u64>> {
1170 self.item.as_ref().map(|item| item.as_item_ref())
1171 }
1172 }
1173
1174 struct MockBloomLayer {
1175 drop_event: Mutex<Option<Arc<DropEvent>>>,
1176 items: Vec<Item<TestKey, u64>>,
1177 key_rejected_prefix: u64,
1178 }
1179
1180 impl MockBloomLayer {
1181 fn new(items: Vec<Item<TestKey, u64>>, key_rejected_prefix: u64) -> Self {
1182 Self {
1183 drop_event: Mutex::new(Some(Arc::new(DropEvent::new()))),
1184 items,
1185 key_rejected_prefix,
1186 }
1187 }
1188 }
1189
1190 #[async_trait]
1191 impl Layer<TestKey, u64> for MockBloomLayer {
1192 async fn seek(
1193 &self,
1194 bound: std::ops::Bound<&TestKey>,
1195 ) -> Result<BoxedLayerIterator<'_, TestKey, u64>, Error> {
1196 let item = match bound {
1197 std::ops::Bound::Included(k) => {
1198 self.items.iter().find(|i| i.key.0.start >= k.0.start).cloned()
1199 }
1200 _ => None,
1201 };
1202 Ok(Box::new(MockBloomLayerIterator { item }))
1203 }
1204
1205 fn lock(&self) -> Option<Arc<DropEvent>> {
1206 self.drop_event.lock().clone()
1207 }
1208
1209 fn len(&self) -> usize {
1210 self.items.len()
1211 }
1212
1213 async fn close(&self) {}
1214
1215 fn get_version(&self) -> Version {
1216 LATEST_VERSION
1217 }
1218
1219 fn has_bloom_filter(&self) -> bool {
1220 true
1221 }
1222
1223 fn maybe_contains_key(&self, key: &TestKey) -> MaybeContainsKey {
1224 if key.0.start >= self.key_rejected_prefix {
1225 MaybeContainsKey::False
1226 } else {
1227 MaybeContainsKey::Maybe
1228 }
1229 }
1230
1231 async fn key_exists(&self, _key: &TestKey) -> Result<Existence, Error> {
1232 unimplemented!()
1233 }
1234 }
1235
1236 let items = vec![
1237 Item::new(TestKey(10..10), 42),
1238 Item::new(TestKey(20..20), u64::DELETED_MARKER),
1239 Item::new(TestKey(30..30), 100),
1240 ];
1241 let layer = Arc::new(MockBloomLayer::new(items, 90));
1243 let tree = LSMTree::new(emit_left_merge_fn, None);
1244 tree.set_layers(vec![layer.clone()]);
1245
1246 let get_fpr = |hierarchy: &DiagnosticsHierarchy| match hierarchy
1247 .get_property("bloom_filter_false_positive_percent")
1248 {
1249 Some(Property::Double(_, val)) => *val,
1250 other => panic!("Unexpected property: {other:?}"),
1251 };
1252 let get_success_percent = |hierarchy: &DiagnosticsHierarchy| match hierarchy
1253 .get_property("bloom_filter_success_percent")
1254 {
1255 Some(Property::Double(_, val)) => *val,
1256 other => panic!("Unexpected property: {other:?}"),
1257 };
1258
1259 let inspector = Inspector::default();
1261 tree.record_inspect_data(inspector.root());
1262 let hierarchy = reader::read(&inspector).await.unwrap();
1263 assert_near!(get_fpr(&hierarchy), 0.0, 1e-6);
1264 assert_near!(get_success_percent(&hierarchy), 0.0, 1e-6);
1265
1266 assert_eq!(tree.find_value(&TestKey(10..10)).await.expect("find failed"), Some(42));
1268 assert_eq!(tree.counters.bloom_filter_false_positives.load(Ordering::Relaxed), 0);
1269 assert_eq!(tree.counters.bloom_filter_negatives.load(Ordering::Relaxed), 0);
1270
1271 assert_eq!(tree.find_value(&TestKey(20..20)).await.expect("find failed"), None);
1273 assert_eq!(tree.counters.bloom_filter_false_positives.load(Ordering::Relaxed), 0);
1274 assert_eq!(tree.counters.bloom_filter_negatives.load(Ordering::Relaxed), 0);
1275
1276 assert_eq!(tree.find_value(&TestKey(25..25)).await.expect("find failed"), None);
1279 assert_eq!(tree.counters.bloom_filter_false_positives.load(Ordering::Relaxed), 1);
1280 assert_eq!(tree.counters.bloom_filter_negatives.load(Ordering::Relaxed), 0);
1281
1282 let inspector = Inspector::default();
1283 tree.record_inspect_data(inspector.root());
1284 let hierarchy = reader::read(&inspector).await.unwrap();
1285 assert_near!(get_fpr(&hierarchy), 100.0, 1e-6);
1286 assert_near!(get_success_percent(&hierarchy), 0.0, 1e-6);
1287
1288 assert_eq!(tree.find_value(&TestKey(90..90)).await.expect("find failed"), None);
1292 assert_eq!(tree.counters.bloom_filter_false_positives.load(Ordering::Relaxed), 1);
1293 assert_eq!(tree.counters.bloom_filter_negatives.load(Ordering::Relaxed), 1);
1294
1295 let inspector = Inspector::default();
1296 tree.record_inspect_data(inspector.root());
1297 let hierarchy = reader::read(&inspector).await.unwrap();
1298 assert_near!(get_fpr(&hierarchy), 50.0, 1e-6);
1299 assert_near!(get_success_percent(&hierarchy), 12.5, 1e-6);
1300
1301 assert_eq!(tree.find_value(&TestKey(91..91)).await.expect("find failed"), None);
1305 assert_eq!(tree.find_value(&TestKey(92..92)).await.expect("find failed"), None);
1306 assert_eq!(tree.counters.bloom_filter_false_positives.load(Ordering::Relaxed), 1);
1307 assert_eq!(tree.counters.bloom_filter_negatives.load(Ordering::Relaxed), 3);
1308
1309 let inspector = Inspector::default();
1310 tree.record_inspect_data(inspector.root());
1311 let hierarchy = reader::read(&inspector).await.unwrap();
1312 assert_near!(get_fpr(&hierarchy), 25.0, 1e-6);
1313 assert_near!(get_success_percent(&hierarchy), 25.0, 1e-6);
1314 }
1315
1316 #[fuchsia::test]
1317 async fn test_empty_seal() {
1318 let tree = LSMTree::new(emit_left_merge_fn, None);
1319 tree.seal();
1320 let item = Item::new(TestKey(1..1), 1);
1321 tree.insert(item.clone()).expect("insert error");
1322 let object = Arc::new(FakeObject::new());
1323 let handle = FakeObjectHandle::new(object.clone());
1324 {
1325 let layer_set = tree.immutable_layer_set();
1326 let mut merger = layer_set.merger();
1327 let iter = merger.query(Query::FullScan).await.expect("create merger");
1328 compact_with_iterator(
1329 iter,
1330 0,
1331 Writer::new(&handle).await,
1332 handle.block_size(),
1333 Option::<NoOpYielder>::None,
1334 )
1335 .await
1336 .expect("compact failed");
1337 }
1338 tree.set_layers(layers_from_handles([handle]).await.expect("layers_from_handles failed"));
1339 let found_item = tree.find(&item.key).await.expect("find failed").expect("not found");
1340 assert_eq!(found_item, item);
1341 assert!(!tree.exists(&TestKey(2..2)).await.expect("find failed"));
1342 }
1343
1344 #[fuchsia::test]
1345 async fn test_filter() {
1346 let items = [
1347 Item::new(TestKey(1..1), 1),
1348 Item::new(TestKey(2..2), 2),
1349 Item::new(TestKey(3..3), 3),
1350 Item::new(TestKey(4..4), 4),
1351 ];
1352 let tree = LSMTree::new(emit_left_merge_fn, None);
1353 tree.insert(items[0].clone()).expect("insert error");
1354 tree.insert(items[1].clone()).expect("insert error");
1355 tree.insert(items[2].clone()).expect("insert error");
1356 tree.insert(items[3].clone()).expect("insert error");
1357
1358 let layers = tree.layer_set();
1359 let mut merger = layers.merger();
1360
1361 let mut iter = merger
1363 .query(Query::FullScan)
1364 .await
1365 .expect("seek failed")
1366 .filter(|item: ItemRef<'_, TestKey, u64>| item.key.0.start % 2 == 0)
1367 .await
1368 .expect("filter failed");
1369
1370 assert_eq!(iter.get(), Some(items[1].as_item_ref()));
1371 iter.advance().await.expect("advance failed");
1372 assert_eq!(iter.get(), Some(items[3].as_item_ref()));
1373 iter.advance().await.expect("advance failed");
1374 assert!(iter.get().is_none());
1375 }
1376
1377 #[fuchsia::test]
1378 async fn test_insert_order_agnostic() {
1379 let items = [
1380 Item::new(TestKey(1..1), 1),
1381 Item::new(TestKey(2..2), 2),
1382 Item::new(TestKey(3..3), 3),
1383 Item::new(TestKey(4..4), 4),
1384 Item::new(TestKey(5..5), 5),
1385 Item::new(TestKey(6..6), 6),
1386 ];
1387 let a = LSMTree::new(emit_left_merge_fn, None);
1388 for item in &items {
1389 a.insert(item.clone()).expect("insert error");
1390 }
1391 let b = LSMTree::new(emit_left_merge_fn, None);
1392 let mut shuffled = items.clone();
1393 shuffled.shuffle(&mut rng());
1394 for item in &shuffled {
1395 b.insert(item.clone()).expect("insert error");
1396 }
1397 let layers = a.layer_set();
1398 let mut merger = layers.merger();
1399 let mut iter_a = merger.query(Query::FullScan).await.expect("seek failed");
1400 let layers = b.layer_set();
1401 let mut merger = layers.merger();
1402 let mut iter_b = merger.query(Query::FullScan).await.expect("seek failed");
1403
1404 for item in items {
1405 assert_eq!(Some(item.as_item_ref()), iter_a.get());
1406 assert_eq!(Some(item.as_item_ref()), iter_b.get());
1407 iter_a.advance().await.expect("advance failed");
1408 iter_b.advance().await.expect("advance failed");
1409 }
1410 assert!(iter_a.get().is_none());
1411 assert!(iter_b.get().is_none());
1412 }
1413
1414 enum AuditCacheResult<V> {
1415 Value(V),
1416 NoCache,
1417 }
1418
1419 struct AuditCacheInner<V: Value> {
1420 lookups: u64,
1421 completions: u64,
1422 invalidations: u64,
1423 drops: u64,
1424 result: Option<AuditCacheResult<V>>,
1425 is_cacheable: bool,
1426 }
1427
1428 impl<V: Value> AuditCacheInner<V> {
1429 fn stats(&self) -> (u64, u64, u64, u64) {
1430 (self.lookups, self.completions, self.invalidations, self.drops)
1431 }
1432 }
1433
1434 struct AuditCache<V: Value> {
1435 inner: Arc<Mutex<AuditCacheInner<V>>>,
1436 }
1437
1438 impl<V: Value> AuditCache<V> {
1439 fn new() -> Self {
1440 Self {
1441 inner: Arc::new(Mutex::new(AuditCacheInner {
1442 lookups: 0,
1443 completions: 0,
1444 invalidations: 0,
1445 drops: 0,
1446 result: None,
1447 is_cacheable: true,
1448 })),
1449 }
1450 }
1451 }
1452
1453 struct AuditPlaceholder<V: Value> {
1454 inner: Arc<Mutex<AuditCacheInner<V>>>,
1455 completed: Mutex<bool>,
1456 }
1457
1458 impl<V: Value> ObjectCachePlaceholder<V> for AuditPlaceholder<V> {
1459 fn complete(self: Box<Self>, _: Option<&V>) {
1460 self.inner.lock().completions += 1;
1461 *self.completed.lock() = true;
1462 }
1463 }
1464
1465 impl<V: Value> Drop for AuditPlaceholder<V> {
1466 fn drop(&mut self) {
1467 if !*self.completed.lock() {
1468 self.inner.lock().drops += 1;
1469 }
1470 }
1471 }
1472
1473 impl<K: Key + std::cmp::PartialEq, V: Value> ObjectCache<K, V> for AuditCache<V> {
1474 fn lookup_or_reserve(&self, _key: &K) -> ObjectCacheResult<'_, V> {
1475 {
1476 let mut inner = self.inner.lock();
1477 inner.lookups += 1;
1478 match MutexGuard::try_map_or_err(inner, |inner| match &mut inner.result {
1479 Some(AuditCacheResult::Value(value)) => Ok(value),
1480 Some(AuditCacheResult::NoCache) => Err(false),
1481 None => Err(true),
1482 }) {
1483 Ok(guard) => {
1484 return ObjectCacheResult::Value(guard);
1485 }
1486 Err((_, false)) => {
1487 return ObjectCacheResult::NoCache;
1488 }
1489 Err((_, true)) => {}
1490 }
1491 }
1492 ObjectCacheResult::Placeholder(Box::new(AuditPlaceholder {
1493 inner: self.inner.clone(),
1494 completed: Mutex::new(false),
1495 }))
1496 }
1497
1498 fn is_cacheable(&self, _key: &K) -> bool {
1499 self.inner.lock().is_cacheable
1500 }
1501
1502 fn invalidate(&self, _key: &K, _value: Option<V>) {
1503 self.inner.lock().invalidations += 1;
1504 }
1505
1506 fn clear(&self) {
1507 self.inner.lock().result = None;
1508 }
1509 }
1510
1511 #[fuchsia::test]
1512 async fn test_cache_handling() {
1513 let item = Item::new(TestKey(1..1), 1);
1514 let cache = Box::new(AuditCache::new());
1515 let inner = cache.inner.clone();
1516 let a = LSMTree::new(emit_left_merge_fn, Some(cache));
1517
1518 assert_eq!(inner.lock().stats(), (0, 0, 0, 0));
1520
1521 assert!(!a.exists(&item.key).await.expect("Failed find"));
1523 assert_eq!(inner.lock().stats(), (1, 0, 0, 1));
1524
1525 let _ = a.insert(item.clone());
1527 assert_eq!(inner.lock().stats(), (1, 0, 1, 1));
1528
1529 assert_eq!(
1531 a.find(&item.key).await.expect("Failed find").expect("Item should be found.").value,
1532 item.value
1533 );
1534 assert_eq!(inner.lock().stats(), (2, 1, 1, 1));
1535
1536 let item2 = Item::new(TestKey(2..2), 2);
1538 let _ = a.insert(item2.clone());
1539 assert_eq!(a.find_value(&item2.key).await.expect("Failed find_value"), Some(item2.value));
1540 assert_eq!(inner.lock().stats(), (3, 2, 2, 1));
1541
1542 let item3 = Item::new(TestKey(3..3), 3);
1544 let _ = a.insert(item3.clone());
1545 assert!(a.exists(&item3.key).await.expect("Failed exists"));
1546 assert_eq!(inner.lock().stats(), (4, 3, 3, 1));
1547
1548 let item4 = Item::new(TestKey(4..4), 4);
1550 let _ = a.insert(item4.clone());
1551 assert_eq!(
1552 a.find_map(&item4.key, |item| item.value * 2).await.expect("Failed find_map"),
1553 Some(8)
1554 );
1555 assert_eq!(inner.lock().stats(), (5, 4, 4, 1));
1556
1557 a.replace_or_insert(item.clone());
1559 assert_eq!(inner.lock().stats(), (5, 4, 5, 1));
1560 }
1561
1562 #[fuchsia::test]
1563 async fn test_cache_hit() {
1564 let item = Item::new(TestKey(1..1), 1);
1565 let cache = Box::new(AuditCache::new());
1566 let inner = cache.inner.clone();
1567 let a = LSMTree::new(emit_left_merge_fn, Some(cache));
1568
1569 assert_eq!(inner.lock().stats(), (0, 0, 0, 0));
1571
1572 let _ = a.insert(item.clone());
1574 assert_eq!(inner.lock().stats(), (0, 0, 1, 0));
1575
1576 inner.lock().result = Some(AuditCacheResult::Value(item.value.clone()));
1578
1579 assert_eq!(
1581 a.find_value(&item.key).await.expect("Failed find").expect("Item should be found."),
1582 item.value
1583 );
1584 assert_eq!(inner.lock().stats(), (1, 0, 1, 0));
1585 }
1586
1587 #[fuchsia::test]
1588 async fn test_cache_hit_deleted_marker() {
1589 let item = Item::new(TestKey(1..1), 1);
1590 let cache = Box::new(AuditCache::new());
1591 let inner = cache.inner.clone();
1592 let a = LSMTree::new(emit_left_merge_fn, Some(cache));
1593
1594 assert_eq!(inner.lock().stats(), (0, 0, 0, 0));
1596
1597 let _ = a.insert(item.clone());
1599 assert_eq!(inner.lock().stats(), (0, 0, 1, 0));
1600
1601 inner.lock().result = Some(AuditCacheResult::Value(u64::DELETED_MARKER));
1603
1604 assert_eq!(a.find_value(&item.key).await.expect("Failed find_value"), None);
1606 assert_eq!(inner.lock().stats(), (1, 0, 1, 0));
1607
1608 inner.lock().result = Some(AuditCacheResult::Value(u64::DELETED_MARKER));
1610 assert!(!a.exists(&item.key).await.expect("Failed exists"));
1611 assert_eq!(inner.lock().stats(), (2, 0, 1, 0));
1612
1613 inner.lock().result = Some(AuditCacheResult::Value(u64::DELETED_MARKER));
1615 assert!(a.find(&item.key).await.expect("Failed find").is_none());
1616 assert_eq!(inner.lock().stats(), (3, 0, 1, 0));
1617
1618 inner.lock().result = Some(AuditCacheResult::Value(u64::DELETED_MARKER));
1620 assert!(a.find_map(&item.key, |_| ()).await.expect("Failed find_map").is_none());
1621 assert_eq!(inner.lock().stats(), (4, 0, 1, 0));
1622 }
1623
1624 #[fuchsia::test]
1625 async fn test_cache_says_uncacheable() {
1626 let item = Item::new(TestKey(1..1), 1);
1627 let cache = Box::new(AuditCache::new());
1628 let inner = cache.inner.clone();
1629 let a = LSMTree::new(emit_left_merge_fn, Some(cache));
1630 let _ = a.insert(item.clone());
1631
1632 assert_eq!(inner.lock().stats(), (0, 0, 1, 0));
1634
1635 inner.lock().result = Some(AuditCacheResult::NoCache);
1637
1638 assert_eq!(
1640 a.find_value(&item.key).await.expect("Failed find").expect("Should find item"),
1641 item.value
1642 );
1643 assert_eq!(inner.lock().stats(), (1, 0, 1, 0));
1644 }
1645
1646 #[fuchsia::test]
1647 async fn test_uncacheable_key_skips_invalidation() {
1648 let item = Item::new(TestKey(1..1), 1);
1649 let cache = Box::new(AuditCache::new());
1650 cache.inner.lock().is_cacheable = false;
1651 let inner = cache.inner.clone();
1652 let a = LSMTree::new(emit_left_merge_fn, Some(cache));
1653
1654 a.insert(item.clone()).expect("insert failed");
1656 assert_eq!(inner.lock().stats(), (0, 0, 0, 0));
1657
1658 a.replace_or_insert(item.clone());
1660 assert_eq!(inner.lock().stats(), (0, 0, 0, 0));
1661
1662 a.merge_into(item.clone(), &TestKey(1..1));
1664 assert_eq!(inner.lock().stats(), (0, 0, 0, 0));
1665 }
1666
1667 struct FailLayer {
1668 drop_event: Mutex<Option<Arc<DropEvent>>>,
1669 }
1670
1671 impl FailLayer {
1672 fn new() -> Self {
1673 Self { drop_event: Mutex::new(Some(Arc::new(DropEvent::new()))) }
1674 }
1675 }
1676
1677 #[async_trait]
1678 impl<K: Key, V: Value> Layer<K, V> for FailLayer {
1679 async fn seek(
1680 &self,
1681 _bound: std::ops::Bound<&K>,
1682 ) -> Result<BoxedLayerIterator<'_, K, V>, Error> {
1683 Err(anyhow!("Purposely failed seek"))
1684 }
1685
1686 fn lock(&self) -> Option<Arc<DropEvent>> {
1687 self.drop_event.lock().clone()
1688 }
1689
1690 fn len(&self) -> usize {
1691 0
1692 }
1693
1694 async fn close(&self) {
1695 let listener = match std::mem::replace(&mut (*self.drop_event.lock()), None) {
1696 Some(drop_event) => drop_event.listen(),
1697 None => return,
1698 };
1699 listener.await;
1700 }
1701
1702 fn get_version(&self) -> Version {
1703 LATEST_VERSION
1704 }
1705
1706 async fn key_exists(&self, _key: &K) -> Result<Existence, Error> {
1707 unimplemented!();
1708 }
1709 }
1710
1711 struct MockLayer {
1712 exists_result: Existence,
1713 drop_event: Mutex<Option<Arc<DropEvent>>>,
1714 cleared: std::sync::atomic::AtomicBool,
1715 }
1716
1717 impl MockLayer {
1718 fn new(exists_result: Existence) -> Self {
1719 Self {
1720 exists_result,
1721 drop_event: Mutex::new(Some(Arc::new(DropEvent::new()))),
1722 cleared: std::sync::atomic::AtomicBool::new(false),
1723 }
1724 }
1725 }
1726
1727 #[async_trait]
1728 impl<K: Key, V: Value> Layer<K, V> for MockLayer {
1729 async fn seek(
1730 &self,
1731 _bound: std::ops::Bound<&K>,
1732 ) -> Result<BoxedLayerIterator<'_, K, V>, Error> {
1733 unimplemented!()
1734 }
1735
1736 fn clear_cached_data(&self) {
1737 self.cleared.store(true, Ordering::Relaxed);
1738 }
1739
1740 fn lock(&self) -> Option<Arc<DropEvent>> {
1741 self.drop_event.lock().clone()
1742 }
1743
1744 fn len(&self) -> usize {
1745 0
1746 }
1747
1748 async fn close(&self) {
1749 let listener = match std::mem::replace(&mut (*self.drop_event.lock()), None) {
1750 Some(drop_event) => drop_event.listen(),
1751 None => return,
1752 };
1753 listener.await;
1754 }
1755
1756 fn get_version(&self) -> Version {
1757 LATEST_VERSION
1758 }
1759
1760 async fn key_exists(&self, _key: &K) -> Result<Existence, Error> {
1761 Ok(self.exists_result)
1762 }
1763 }
1764
1765 #[fuchsia::test]
1766 async fn test_clear_cache() {
1767 let item = Item::new(TestKey(1..1), 1);
1768 let cache = Box::new(AuditCache::new());
1769 let inner = cache.inner.clone();
1770 let tree = LSMTree::new(emit_left_merge_fn, Some(cache));
1771
1772 let layer1 = Arc::new(MockLayer::new(Existence::MaybeExists));
1773 let layer2 = Arc::new(MockLayer::new(Existence::MaybeExists));
1774 tree.set_layers(vec![
1775 layer1.clone() as Arc<dyn Layer<TestKey, u64>>,
1776 layer2.clone() as Arc<dyn Layer<TestKey, u64>>,
1777 ]);
1778
1779 inner.lock().result = Some(AuditCacheResult::Value(item.value));
1780 assert_eq!(tree.find_value(&item.key).await.expect("find_value failed"), Some(item.value));
1781 assert!(!layer1.cleared.load(Ordering::Relaxed));
1782 assert!(!layer2.cleared.load(Ordering::Relaxed));
1783
1784 tree.clear_cache();
1785
1786 assert!(inner.lock().result.is_none());
1787 assert!(layer1.cleared.load(Ordering::Relaxed));
1788 assert!(layer2.cleared.load(Ordering::Relaxed));
1789 }
1790
1791 #[fuchsia::test]
1792 async fn test_layer_set_key_exists() {
1793 use super::LockedLayer;
1794
1795 let tree = LSMTree::new(emit_left_merge_fn, None);
1796 let mut layer_set = tree.empty_layer_set();
1797
1798 assert_eq!(
1800 layer_set.key_exists(&TestKey(0..1)).await.expect("key_exists failed"),
1801 Existence::Missing
1802 );
1803
1804 layer_set.layers.push(LockedLayer::from(
1806 Arc::new(MockLayer::new(Existence::Missing)) as Arc<dyn Layer<TestKey, u64>>
1807 ));
1808 assert_eq!(
1809 layer_set.key_exists(&TestKey(0..1)).await.expect("key_exists failed"),
1810 Existence::Missing
1811 );
1812
1813 layer_set.layers.push(LockedLayer::from(
1815 Arc::new(MockLayer::new(Existence::MaybeExists)) as Arc<dyn Layer<TestKey, u64>>
1816 ));
1817 assert_eq!(
1818 layer_set.key_exists(&TestKey(0..1)).await.expect("key_exists failed"),
1819 Existence::MaybeExists
1820 );
1821
1822 layer_set.layers.insert(
1824 0,
1825 LockedLayer::from(
1826 Arc::new(MockLayer::new(Existence::Exists)) as Arc<dyn Layer<TestKey, u64>>
1827 ),
1828 );
1829 assert_eq!(
1830 layer_set.key_exists(&TestKey(0..1)).await.expect("key_exists failed"),
1831 Existence::Exists
1832 );
1833 }
1834
1835 #[fuchsia::test]
1836 async fn test_failed_lookup() {
1837 let cache = Box::new(AuditCache::new());
1838 let inner = cache.inner.clone();
1839 let a = LSMTree::new(emit_left_merge_fn, Some(cache));
1840 a.set_layers(vec![Arc::new(FailLayer::new())]);
1841
1842 assert_eq!(inner.lock().stats(), (0, 0, 0, 0));
1844
1845 assert!(a.find(&TestKey(1..1)).await.is_err());
1847 assert_eq!(inner.lock().stats(), (1, 0, 0, 1));
1848 }
1849}
1850
1851#[cfg(fuzz)]
1852mod fuzz {
1853 use crate::lsm_tree::types::{Item, Value};
1854 use crate::serialized_types::{
1855 LATEST_VERSION, Version, Versioned, VersionedLatest, versioned_type,
1856 };
1857 use arbitrary::Arbitrary;
1858
1859 use fuzz::fuzz;
1860
1861 use super::testing::TestKey;
1862
1863 impl Versioned for u64 {}
1864 versioned_type! { 1.. => u64 }
1865
1866 impl Value for u64 {
1867 const DELETED_MARKER: Self = 0;
1868 }
1869
1870 #[allow(dead_code)]
1874 #[derive(Arbitrary)]
1875 enum FuzzAction {
1876 Insert(Item<TestKey, u64>),
1877 ReplaceOrInsert(Item<TestKey, u64>),
1878 MergeInto(Item<TestKey, u64>, TestKey),
1879 Find(TestKey),
1880 Seal,
1881 }
1882
1883 #[fuzz]
1884 fn fuzz_lsm_tree_actions(actions: Vec<FuzzAction>) {
1885 use super::LSMTree;
1886 use crate::lsm_tree::merge::{MergeLayerIterator, MergeResult};
1887 use futures::executor::block_on;
1888
1889 fn emit_left_merge_fn(
1890 _left: &MergeLayerIterator<'_, TestKey, u64>,
1891 _right: &MergeLayerIterator<'_, TestKey, u64>,
1892 ) -> MergeResult<TestKey, u64> {
1893 MergeResult::EmitLeft
1894 }
1895
1896 let tree = LSMTree::new(emit_left_merge_fn, None);
1897 for action in actions {
1898 match action {
1899 FuzzAction::Insert(item) => {
1900 let _ = tree.insert(item);
1901 }
1902 FuzzAction::ReplaceOrInsert(item) => {
1903 tree.replace_or_insert(item);
1904 }
1905 FuzzAction::Find(key) => {
1906 block_on(tree.find(&key)).expect("find failed");
1907 }
1908 FuzzAction::MergeInto(item, bound) => tree.merge_into(item, &bound),
1909 FuzzAction::Seal => tree.seal(),
1910 };
1911 }
1912 }
1913}