fxfs/lsm_tree/
cache.rs

1// Copyright 2023 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
5use super::types::{Key, Value};
6use std::fmt;
7
8pub trait ObjectCachePlaceholder<V: Value>: Send + Sync {
9    /// Consumes itself in delivering the cache value for which the placeholder was reserved.
10    /// Passing None for value should not be inserted into the cache, but interpreted as an
11    /// incomplete search.
12    fn complete(self: Box<Self>, value: Option<&V>);
13}
14
15/// Possible results for a cache `lookup_or_reserve()`
16pub enum ObjectCacheResult<'a, V: Value> {
17    /// Contains the value successfully retrieved from the cache.
18    Value(V),
19    /// The object was not found in the cache, so this placeholder can be used to insert the
20    /// calculated result.
21    Placeholder(Box<dyn ObjectCachePlaceholder<V> + 'a>),
22    /// Returned for items that are not wanted to be inserted into the cache.
23    NoCache,
24}
25
26impl<'a, V: Value> fmt::Debug for ObjectCacheResult<'a, V> {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        let (name, contents) = match self {
29            Self::Value(v) => ("Value", Some(format!("{:?}", v))),
30            Self::NoCache => ("NoCache", None),
31            Self::Placeholder(_) => ("Placeholder", None),
32        };
33        if contents.is_some() {
34            f.debug_struct("ObjectCacheResult").field(name, &contents.unwrap()).finish()
35        } else {
36            f.debug_struct("ObjectCacheResult").field(name, &"").finish()
37        }
38    }
39}
40
41pub trait ObjectCache<K: Key, V: Value>: Send + Sync {
42    /// Looks up a key in the cache and may return a cached value for it. See `ObjectCacheResult`.
43    fn lookup_or_reserve<'a>(&'a self, key: &K) -> ObjectCacheResult<'_, V>;
44
45    /// Removes key from cache if `value` is None, invalidates the results of placeholders that have
46    /// not been resolved. When `value` is provided then the value may be inserted, and may replace
47    /// an existing value.
48    fn invalidate(&self, key: K, value: Option<V>);
49}
50
51/// A cache that will always return NoCache in lookups, and does no actual work.
52pub struct NullCache {}
53
54impl<K: Key, V: Value> ObjectCache<K, V> for NullCache {
55    fn lookup_or_reserve(&self, _key: &K) -> ObjectCacheResult<'_, V> {
56        ObjectCacheResult::NoCache
57    }
58
59    fn invalidate(&self, _key: K, _value: Option<V>) {}
60}