Coverage Report

Created: 2025-01-30 02:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/nativelink-util/src/evicting_map.rs
Line
Count
Source
1
// Copyright 2024 The NativeLink Authors. All rights reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
use std::borrow::Borrow;
16
use std::cmp::Eq;
17
use std::collections::BTreeSet;
18
use std::fmt::Debug;
19
use std::future::Future;
20
use std::hash::Hash;
21
use std::ops::RangeBounds;
22
use std::sync::Arc;
23
24
use async_lock::Mutex;
25
use lru::LruCache;
26
use nativelink_config::stores::EvictionPolicy;
27
use nativelink_metric::MetricsComponent;
28
use serde::{Deserialize, Serialize};
29
use tracing::{event, Level};
30
31
use crate::instant_wrapper::InstantWrapper;
32
use crate::metrics_utils::{Counter, CounterWithTime};
33
34
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
35
pub struct SerializedLRU<K> {
36
    pub data: Vec<(K, i32)>,
37
    pub anchor_time: u64,
38
}
39
40
#[derive(Debug)]
41
struct EvictionItem<T: LenEntry + Debug> {
42
    seconds_since_anchor: i32,
43
    data: T,
44
}
45
46
pub trait LenEntry: 'static {
47
    /// Length of referenced data.
48
    fn len(&self) -> u64;
49
50
    /// Returns `true` if `self` has zero length.
51
    fn is_empty(&self) -> bool;
52
53
    /// Called when an entry is touched.  On failure, will remove the entry
54
    /// from the map.
55
    #[inline]
56
4.62k
    fn touch(&self) -> impl Future<Output = bool> + Send {
57
4.62k
        std::future::ready(true)
58
4.62k
    }
59
60
    /// This will be called when object is removed from map.
61
    /// Note: There may still be a reference to it held somewhere else, which
62
    /// is why it can't be mutable. This is a good place to mark the item
63
    /// to be deleted and then in the Drop call actually do the deleting.
64
    /// This will ensure nowhere else in the program still holds a reference
65
    /// to this object.
66
    /// You should not rely only on the Drop trait. Doing so might result in the
67
    /// program safely shutting down and calling the Drop method on each object,
68
    /// which if you are deleting items you may not want to do.
69
    /// It is undefined behavior to have `unref()` called more than once.
70
    /// During the execution of `unref()` no items can be added or removed to/from
71
    /// the `EvictionMap` globally (including inside `unref()`).
72
    #[inline]
73
34
    fn unref(&self) -> impl Future<Output = ()> + Send {
74
34
        std::future::ready(())
75
34
    }
76
}
77
78
impl<T: LenEntry + Send + Sync> LenEntry for Arc<T> {
79
    #[inline]
80
238
    fn len(&self) -> u64 {
81
238
        T::len(self.as_ref())
82
238
    }
83
84
    #[inline]
85
0
    fn is_empty(&self) -> bool {
86
0
        T::is_empty(self.as_ref())
87
0
    }
88
89
    #[inline]
90
132
    async fn touch(&self) -> bool {
91
132
        self.as_ref().touch().await
92
132
    }
93
94
    #[inline]
95
20
    async fn unref(&self) {
96
20
        self.as_ref().unref().await;
97
20
    }
98
}
99
100
#[derive(MetricsComponent)]
101
struct State<K: Ord + Hash + Eq + Clone + Debug + Send, T: LenEntry + Debug + Send> {
102
    lru: LruCache<K, EvictionItem<T>>,
103
    btree: Option<BTreeSet<K>>,
104
    #[metric(help = "Total size of all items in the store")]
105
    sum_store_size: u64,
106
107
    #[metric(help = "Number of bytes evicted from the store")]
108
    evicted_bytes: Counter,
109
    #[metric(help = "Number of items evicted from the store")]
110
    evicted_items: CounterWithTime,
111
    #[metric(help = "Number of bytes replaced in the store")]
112
    replaced_bytes: Counter,
113
    #[metric(help = "Number of items replaced in the store")]
114
    replaced_items: CounterWithTime,
115
    #[metric(help = "Number of bytes inserted into the store since it was created")]
116
    lifetime_inserted_bytes: Counter,
117
}
118
119
impl<K: Ord + Hash + Eq + Clone + Debug + Send + Sync, T: LenEntry + Debug + Sync + Send>
120
    State<K, T>
121
{
122
    /// Removes an item from the cache.
123
53
    async fn remove<Q>(&mut self, key: &Q, eviction_item: &EvictionItem<T>, replaced: bool)
124
53
    where
125
53
        K: Borrow<Q>,
126
53
        Q: Ord + Hash + Eq + Debug + Sync,
127
53
    {
128
53
        if let Some(
btree0
) = &mut self.btree {
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 9]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [Folded - Ignored]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 6]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 1]
  Branch (128:16): [True: 0, False: 1]
  Branch (128:16): [True: 0, False: 14]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 1]
  Branch (128:16): [True: 0, False: 2]
  Branch (128:16): [True: 0, False: 1]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 1]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 1]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 1]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 1]
  Branch (128:16): [True: 0, False: 5]
  Branch (128:16): [True: 0, False: 2]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [Folded - Ignored]
  Branch (128:16): [True: 0, False: 6]
  Branch (128:16): [True: 0, False: 0]
  Branch (128:16): [True: 0, False: 1]
129
0
            btree.remove(key.borrow());
130
53
        }
131
53
        self.sum_store_size -= eviction_item.data.len();
132
53
        if replaced {
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 8, False: 1]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [Folded - Ignored]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 6]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 1]
  Branch (132:12): [True: 1, False: 0]
  Branch (132:12): [True: 0, False: 14]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 1]
  Branch (132:12): [True: 0, False: 2]
  Branch (132:12): [True: 0, False: 1]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 1]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 1, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 1, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 1]
  Branch (132:12): [True: 5, False: 0]
  Branch (132:12): [True: 0, False: 2]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [Folded - Ignored]
  Branch (132:12): [True: 6, False: 0]
  Branch (132:12): [True: 0, False: 0]
  Branch (132:12): [True: 0, False: 1]
133
22
            self.replaced_items.inc();
134
22
            self.replaced_bytes.add(eviction_item.data.len());
135
31
        } else {
136
31
            self.evicted_items.inc();
137
31
            self.evicted_bytes.add(eviction_item.data.len());
138
31
        }
139
        // Note: See comment in `unref()` requring global lock of insert/remove.
140
53
        eviction_item.data.unref().await;
141
53
    }
142
143
    /// Inserts a new item into the cache. If the key already exists, the old item is returned.
144
5.85k
    async fn put(&mut self, key: K, eviction_item: EvictionItem<T>) -> Option<T> {
145
        // If we are maintaining a btree index, we need to update it.
146
5.85k
        if let Some(
btree0
) = &mut self.btree {
  Branch (146:16): [True: 0, False: 0]
  Branch (146:16): [True: 0, False: 5.71k]
  Branch (146:16): [True: 0, False: 0]
  Branch (146:16): [True: 0, False: 0]
  Branch (146:16): [Folded - Ignored]
  Branch (146:16): [True: 0, False: 2]
  Branch (146:16): [True: 0, False: 27]
  Branch (146:16): [True: 0, False: 3]
  Branch (146:16): [True: 0, False: 5]
  Branch (146:16): [True: 0, False: 2]
  Branch (146:16): [True: 0, False: 2]
  Branch (146:16): [True: 0, False: 2]
  Branch (146:16): [True: 0, False: 2]
  Branch (146:16): [True: 0, False: 1]
  Branch (146:16): [True: 0, False: 22]
  Branch (146:16): [True: 0, False: 0]
  Branch (146:16): [Folded - Ignored]
  Branch (146:16): [True: 0, False: 49]
  Branch (146:16): [True: 0, False: 27]
147
0
            btree.insert(key.clone());
148
5.85k
        }
149
5.85k
        if let Some(
old_item22
) = self.lru.put(key.clone(), eviction_item) {
  Branch (149:16): [True: 0, False: 0]
  Branch (149:16): [True: 8, False: 5.70k]
  Branch (149:16): [True: 0, False: 0]
  Branch (149:16): [True: 0, False: 0]
  Branch (149:16): [Folded - Ignored]
  Branch (149:16): [True: 1, False: 1]
  Branch (149:16): [True: 0, False: 27]
  Branch (149:16): [True: 0, False: 3]
  Branch (149:16): [True: 0, False: 5]
  Branch (149:16): [True: 0, False: 2]
  Branch (149:16): [True: 0, False: 2]
  Branch (149:16): [True: 1, False: 1]
  Branch (149:16): [True: 1, False: 1]
  Branch (149:16): [True: 0, False: 1]
  Branch (149:16): [True: 5, False: 17]
  Branch (149:16): [True: 0, False: 0]
  Branch (149:16): [Folded - Ignored]
  Branch (149:16): [True: 6, False: 43]
  Branch (149:16): [True: 0, False: 27]
150
22
            self.remove(&key, &old_item, true).await;
151
22
            return Some(old_item.data);
152
5.83k
        }
153
5.83k
        None
154
5.85k
    }
155
}
156
157
#[derive(MetricsComponent)]
158
pub struct EvictingMap<
159
    K: Ord + Hash + Eq + Clone + Debug + Send,
160
    T: LenEntry + Debug + Send,
161
    I: InstantWrapper,
162
> {
163
    #[metric]
164
    state: Mutex<State<K, T>>,
165
    anchor_time: I,
166
    #[metric(help = "Maximum size of the store in bytes")]
167
    max_bytes: u64,
168
    #[metric(help = "Number of bytes to evict when the store is full")]
169
    evict_bytes: u64,
170
    #[metric(help = "Maximum number of seconds to keep an item in the store")]
171
    max_seconds: i32,
172
    #[metric(help = "Maximum number of items to keep in the store")]
173
    max_count: u64,
174
}
175
176
impl<K, T, I> EvictingMap<K, T, I>
177
where
178
    K: Ord + Hash + Eq + Clone + Debug + Send + Sync,
179
    T: LenEntry + Debug + Clone + Send + Sync,
180
    I: InstantWrapper,
181
{
182
373
    pub fn new(config: &EvictionPolicy, anchor_time: I) -> Self {
183
373
        EvictingMap {
184
373
            // We use unbounded because if we use the bounded version we can't call the delete
185
373
            // function on the LenEntry properly.
186
373
            state: Mutex::new(State {
187
373
                lru: LruCache::unbounded(),
188
373
                btree: None,
189
373
                sum_store_size: 0,
190
373
                evicted_bytes: Counter::default(),
191
373
                evicted_items: CounterWithTime::default(),
192
373
                replaced_bytes: Counter::default(),
193
373
                replaced_items: CounterWithTime::default(),
194
373
                lifetime_inserted_bytes: Counter::default(),
195
373
            }),
196
373
            anchor_time,
197
373
            max_bytes: config.max_bytes as u64,
198
373
            evict_bytes: config.evict_bytes as u64,
199
373
            max_seconds: config.max_seconds as i32,
200
373
            max_count: config.max_count,
201
373
        }
202
373
    }
203
204
0
    pub async fn enable_filtering(&self) {
205
0
        let mut state = self.state.lock().await;
206
0
        if state.btree.is_none() {
  Branch (206:12): [Folded - Ignored]
  Branch (206:12): [Folded - Ignored]
207
0
            Self::rebuild_btree_index(&mut state);
208
0
        }
209
0
    }
210
211
2
    fn rebuild_btree_index(state: &mut State<K, T>) {
212
6
        state.btree = Some(state.lru.iter().map(|(k, _)| k).cloned().collect());
213
2
    }
214
215
    /// Run the `handler` function on each key-value pair that matches the `prefix_range`
216
    /// and return the number of items that were processed.
217
    /// The `handler` function should return `true` to continue processing the next item
218
    /// or `false` to stop processing.
219
11
    pub async fn range<F, Q>(&self, prefix_range: impl RangeBounds<Q> + Send, mut handler: F) -> u64
220
11
    where
221
11
        F: FnMut(&K, &T) -> bool + Send,
222
11
        K: Borrow<Q> + Ord,
223
11
        Q: Ord + Hash + Eq + Debug + Sync,
224
11
    {
225
11
        let mut state = self.state.lock().await;
226
11
        let btree = if let Some(
ref btree9
) = state.btree {
  Branch (226:28): [True: 6, False: 1]
  Branch (226:28): [Folded - Ignored]
  Branch (226:28): [True: 1, False: 0]
  Branch (226:28): [True: 2, False: 0]
  Branch (226:28): [True: 0, False: 1]
  Branch (226:28): [Folded - Ignored]
227
9
            btree
228
        } else {
229
2
            Self::rebuild_btree_index(&mut state);
230
2
            state.btree.as_ref().unwrap()
231
        };
232
11
        let mut continue_count = 0;
233
22
        for key in 
btree.range(prefix_range)11
{
234
22
            let value = &state.lru.peek(key.borrow()).unwrap().data;
235
22
            let should_continue = handler(key, value);
236
22
            if !should_continue {
  Branch (236:16): [True: 0, False: 13]
  Branch (236:16): [Folded - Ignored]
  Branch (236:16): [True: 0, False: 1]
  Branch (236:16): [True: 0, False: 5]
  Branch (236:16): [True: 0, False: 3]
  Branch (236:16): [Folded - Ignored]
237
0
                break;
238
22
            }
239
22
            continue_count += 1;
240
        }
241
11
        continue_count
242
11
    }
243
244
    /// Returns the number of key-value pairs that are currently in the the cache.
245
    /// Function is not for production code paths.
246
30
    pub async fn len_for_test(&self) -> usize {
247
30
        self.state.lock().await.lru.len()
248
30
    }
249
250
11.0k
    fn should_evict(
251
11.0k
        &self,
252
11.0k
        lru_len: usize,
253
11.0k
        peek_entry: &EvictionItem<T>,
254
11.0k
        sum_store_size: u64,
255
11.0k
        max_bytes: u64,
256
11.0k
    ) -> bool {
257
11.0k
        let is_over_size = max_bytes != 0 && 
sum_store_size >= max_bytes231
;
  Branch (257:28): [True: 0, False: 0]
  Branch (257:28): [True: 0, False: 0]
  Branch (257:28): [True: 100, False: 10.1k]
  Branch (257:28): [True: 0, False: 0]
  Branch (257:28): [Folded - Ignored]
  Branch (257:28): [True: 0, False: 6]
  Branch (257:28): [True: 0, False: 1]
  Branch (257:28): [True: 0, False: 3]
  Branch (257:28): [True: 30, False: 31]
  Branch (257:28): [True: 0, False: 3]
  Branch (257:28): [True: 0, False: 1]
  Branch (257:28): [True: 4, False: 1]
  Branch (257:28): [True: 3, False: 5]
  Branch (257:28): [True: 3, False: 0]
  Branch (257:28): [True: 0, False: 4]
  Branch (257:28): [True: 0, False: 2]
  Branch (257:28): [True: 0, False: 3]
  Branch (257:28): [True: 0, False: 2]
  Branch (257:28): [True: 3, False: 33]
  Branch (257:28): [True: 0, False: 0]
  Branch (257:28): [True: 0, False: 4]
  Branch (257:28): [Folded - Ignored]
  Branch (257:28): [True: 34, False: 69]
  Branch (257:28): [True: 54, False: 531]
258
259
11.0k
        let evict_older_than_seconds =
260
11.0k
            (self.anchor_time.elapsed().as_secs() as i32) - self.max_seconds;
261
11.0k
        let old_item_exists =
262
11.0k
            self.max_seconds != 0 && 
peek_entry.seconds_since_anchor < evict_older_than_seconds618
;
  Branch (262:13): [True: 0, False: 0]
  Branch (262:13): [True: 0, False: 0]
  Branch (262:13): [True: 0, False: 10.2k]
  Branch (262:13): [True: 0, False: 0]
  Branch (262:13): [Folded - Ignored]
  Branch (262:13): [True: 0, False: 6]
  Branch (262:13): [True: 0, False: 1]
  Branch (262:13): [True: 0, False: 3]
  Branch (262:13): [True: 28, False: 33]
  Branch (262:13): [True: 0, False: 3]
  Branch (262:13): [True: 0, False: 1]
  Branch (262:13): [True: 5, False: 0]
  Branch (262:13): [True: 0, False: 8]
  Branch (262:13): [True: 0, False: 3]
  Branch (262:13): [True: 0, False: 4]
  Branch (262:13): [True: 0, False: 2]
  Branch (262:13): [True: 0, False: 3]
  Branch (262:13): [True: 0, False: 2]
  Branch (262:13): [True: 0, False: 36]
  Branch (262:13): [True: 0, False: 0]
  Branch (262:13): [True: 0, False: 4]
  Branch (262:13): [Folded - Ignored]
  Branch (262:13): [True: 0, False: 103]
  Branch (262:13): [True: 585, False: 0]
263
264
11.0k
        let is_over_count = self.max_count != 0 && 
(lru_len as u64) > self.max_count52
;
  Branch (264:29): [True: 0, False: 0]
  Branch (264:29): [True: 0, False: 0]
  Branch (264:29): [True: 32, False: 10.2k]
  Branch (264:29): [True: 0, False: 0]
  Branch (264:29): [Folded - Ignored]
  Branch (264:29): [True: 0, False: 6]
  Branch (264:29): [True: 0, False: 1]
  Branch (264:29): [True: 3, False: 0]
  Branch (264:29): [True: 8, False: 53]
  Branch (264:29): [True: 0, False: 3]
  Branch (264:29): [True: 0, False: 1]
  Branch (264:29): [True: 0, False: 5]
  Branch (264:29): [True: 0, False: 8]
  Branch (264:29): [True: 0, False: 3]
  Branch (264:29): [True: 4, False: 0]
  Branch (264:29): [True: 2, False: 0]
  Branch (264:29): [True: 3, False: 0]
  Branch (264:29): [True: 0, False: 2]
  Branch (264:29): [True: 0, False: 36]
  Branch (264:29): [True: 0, False: 0]
  Branch (264:29): [True: 0, False: 4]
  Branch (264:29): [Folded - Ignored]
  Branch (264:29): [True: 0, False: 103]
  Branch (264:29): [True: 0, False: 585]
265
266
11.0k
        is_over_size || 
old_item_exists11.0k
||
is_over_count11.0k
  Branch (266:9): [True: 0, False: 0]
  Branch (266:25): [True: 0, False: 0]
  Branch (266:9): [True: 0, False: 0]
  Branch (266:25): [True: 0, False: 0]
  Branch (266:9): [True: 0, False: 10.2k]
  Branch (266:25): [True: 0, False: 10.2k]
  Branch (266:9): [True: 0, False: 0]
  Branch (266:25): [True: 0, False: 0]
  Branch (266:9): [Folded - Ignored]
  Branch (266:25): [Folded - Ignored]
  Branch (266:9): [True: 0, False: 6]
  Branch (266:25): [True: 0, False: 6]
  Branch (266:9): [True: 0, False: 1]
  Branch (266:25): [True: 0, False: 1]
  Branch (266:9): [True: 0, False: 3]
  Branch (266:25): [True: 0, False: 3]
  Branch (266:9): [True: 6, False: 55]
  Branch (266:25): [True: 7, False: 48]
  Branch (266:9): [True: 0, False: 3]
  Branch (266:25): [True: 0, False: 3]
  Branch (266:9): [True: 0, False: 1]
  Branch (266:25): [True: 0, False: 1]
  Branch (266:9): [True: 0, False: 5]
  Branch (266:25): [True: 1, False: 4]
  Branch (266:9): [True: 0, False: 8]
  Branch (266:25): [True: 0, False: 8]
  Branch (266:9): [True: 1, False: 2]
  Branch (266:25): [True: 0, False: 2]
  Branch (266:9): [True: 0, False: 4]
  Branch (266:25): [True: 0, False: 4]
  Branch (266:9): [True: 0, False: 2]
  Branch (266:25): [True: 0, False: 2]
  Branch (266:9): [True: 0, False: 3]
  Branch (266:25): [True: 0, False: 3]
  Branch (266:9): [True: 0, False: 2]
  Branch (266:25): [True: 0, False: 2]
  Branch (266:9): [True: 0, False: 36]
  Branch (266:25): [True: 0, False: 36]
  Branch (266:9): [True: 0, False: 0]
  Branch (266:25): [True: 0, False: 0]
  Branch (266:9): [True: 0, False: 4]
  Branch (266:25): [True: 0, False: 4]
  Branch (266:9): [Folded - Ignored]
  Branch (266:25): [Folded - Ignored]
  Branch (266:9): [True: 0, False: 103]
  Branch (266:25): [True: 0, False: 103]
  Branch (266:9): [True: 0, False: 585]
  Branch (266:25): [True: 1, False: 584]
267
11.0k
    }
268
269
10.8k
    async fn evict_items(&self, state: &mut State<K, T>) {
270
10.8k
        let Some((_, 
mut peek_entry10.8k
)) = state.lru.peek_lru() else {
  Branch (270:13): [True: 0, False: 0]
  Branch (270:13): [True: 10.1k, False: 4]
  Branch (270:13): [True: 0, False: 0]
  Branch (270:13): [True: 0, False: 0]
  Branch (270:13): [Folded - Ignored]
  Branch (270:13): [True: 6, False: 0]
  Branch (270:13): [True: 1, False: 0]
  Branch (270:13): [True: 3, False: 0]
  Branch (270:13): [True: 34, False: 0]
  Branch (270:13): [True: 3, False: 0]
  Branch (270:13): [True: 1, False: 0]
  Branch (270:13): [True: 1, False: 0]
  Branch (270:13): [True: 5, False: 0]
  Branch (270:13): [True: 2, False: 0]
  Branch (270:13): [True: 3, False: 0]
  Branch (270:13): [True: 2, False: 0]
  Branch (270:13): [True: 3, False: 0]
  Branch (270:13): [True: 2, False: 0]
  Branch (270:13): [True: 33, False: 0]
  Branch (270:13): [True: 0, False: 0]
  Branch (270:13): [True: 4, False: 0]
  Branch (270:13): [Folded - Ignored]
  Branch (270:13): [True: 69, False: 0]
  Branch (270:13): [True: 530, False: 0]
271
4
            return;
272
        };
273
274
10.8k
        let max_bytes = if self.max_bytes != 0
  Branch (274:28): [True: 0, False: 0]
  Branch (274:28): [True: 0, False: 10.1k]
  Branch (274:28): [True: 0, False: 0]
  Branch (274:28): [True: 0, False: 0]
  Branch (274:28): [Folded - Ignored]
  Branch (274:28): [True: 0, False: 6]
  Branch (274:28): [True: 0, False: 1]
  Branch (274:28): [True: 0, False: 3]
  Branch (274:28): [True: 8, False: 26]
  Branch (274:28): [True: 0, False: 3]
  Branch (274:28): [True: 0, False: 1]
  Branch (274:28): [True: 0, False: 1]
  Branch (274:28): [True: 0, False: 5]
  Branch (274:28): [True: 2, False: 0]
  Branch (274:28): [True: 0, False: 3]
  Branch (274:28): [True: 0, False: 2]
  Branch (274:28): [True: 0, False: 3]
  Branch (274:28): [True: 0, False: 2]
  Branch (274:28): [True: 0, False: 33]
  Branch (274:28): [True: 0, False: 0]
  Branch (274:28): [True: 0, False: 4]
  Branch (274:28): [Folded - Ignored]
  Branch (274:28): [True: 0, False: 69]
  Branch (274:28): [True: 0, False: 530]
275
10
            && self.evict_bytes != 0
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [Folded - Ignored]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 4, False: 4]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 2]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [Folded - Ignored]
  Branch (275:16): [True: 0, False: 0]
  Branch (275:16): [True: 0, False: 0]
276
4
            && self.should_evict(
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [Folded - Ignored]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 1, False: 3]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [Folded - Ignored]
  Branch (276:16): [True: 0, False: 0]
  Branch (276:16): [True: 0, False: 0]
277
4
                state.lru.len(),
278
4
                peek_entry,
279
4
                state.sum_store_size,
280
4
                self.max_bytes,
281
4
            ) {
282
1
            if self.max_bytes > self.evict_bytes {
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [Folded - Ignored]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 1, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [Folded - Ignored]
  Branch (282:16): [True: 0, False: 0]
  Branch (282:16): [True: 0, False: 0]
283
1
                self.max_bytes - self.evict_bytes
284
            } else {
285
0
                0
286
            }
287
        } else {
288
10.8k
            self.max_bytes
289
        };
290
291
10.8k
        while self.should_evict(state.lru.len(), peek_entry, state.sum_store_size, max_bytes) {
  Branch (291:15): [True: 0, False: 0]
  Branch (291:15): [True: 1, False: 10.1k]
  Branch (291:15): [True: 0, False: 0]
  Branch (291:15): [True: 0, False: 0]
  Branch (291:15): [Folded - Ignored]
  Branch (291:15): [True: 0, False: 6]
  Branch (291:15): [True: 0, False: 1]
  Branch (291:15): [True: 0, False: 3]
  Branch (291:15): [True: 12, False: 31]
  Branch (291:15): [True: 0, False: 3]
  Branch (291:15): [True: 0, False: 1]
  Branch (291:15): [True: 0, False: 1]
  Branch (291:15): [True: 0, False: 5]
  Branch (291:15): [True: 1, False: 2]
  Branch (291:15): [True: 1, False: 3]
  Branch (291:15): [True: 0, False: 2]
  Branch (291:15): [True: 0, False: 3]
  Branch (291:15): [True: 0, False: 2]
  Branch (291:15): [True: 0, False: 33]
  Branch (291:15): [True: 0, False: 0]
  Branch (291:15): [True: 0, False: 4]
  Branch (291:15): [Folded - Ignored]
  Branch (291:15): [True: 0, False: 69]
  Branch (291:15): [True: 1, False: 530]
292
16
            let (key, eviction_item) = state
293
16
                .lru
294
16
                .pop_lru()
295
16
                .expect("Tried to peek() then pop() but failed");
296
16
            event!(Level::INFO, ?key, 
"Evicting"0
,);
297
16
            state.remove(&key, &eviction_item, false).await;
298
299
16
            peek_entry = if let Some((_, 
entry13
)) = state.lru.peek_lru() {
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 1, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [Folded - Ignored]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 9, False: 3]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 1, False: 0]
  Branch (299:33): [True: 1, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [Folded - Ignored]
  Branch (299:33): [True: 0, False: 0]
  Branch (299:33): [True: 1, False: 0]
300
13
                entry
301
            } else {
302
3
                return;
303
            };
304
        }
305
10.8k
    }
306
307
    /// Return the size of a `key`, if not found `None` is returned.
308
79
    pub async fn size_for_key<Q>(&self, key: &Q) -> Option<u64>
309
79
    where
310
79
        K: Borrow<Q>,
311
79
        Q: Ord + Hash + Eq + Debug + Sync,
312
79
    {
313
79
        let mut results = [None];
314
79
        self.sizes_for_keys([key], &mut results[..], false).await;
315
79
        results[0]
316
79
    }
317
318
    /// Return the sizes of a collection of `keys`. Expects `results` collection
319
    /// to be provided for storing the resulting key sizes. Each index value in
320
    /// `keys` maps directly to the size value for the key in `results`.
321
    /// If no key is found in the internal map, `None` is filled in its place.
322
    /// If `peek` is set to `true`, the items are not promoted to the front of the
323
    /// LRU cache. Note: peek may still evict, but won't promote.
324
327
    pub async fn sizes_for_keys<It, Q, R>(&self, keys: It, results: &mut [Option<u64>], peek: bool)
325
327
    where
326
327
        It: IntoIterator<Item = R> + Send,
327
327
        // Note: It's not enough to have the inserts themselves be Send. The
328
327
        // returned iterator should be Send as well.
329
327
        <It as IntoIterator>::IntoIter: Send,
330
327
        // This may look strange, but what we are doing is saying:
331
327
        // * `K` must be able to borrow `Q`
332
327
        // * `R` (the input stream item type) must also be able to borrow `Q`
333
327
        // Note: That K and R do not need to be the same type, they just both need
334
327
        // to be able to borrow a `Q`.
335
327
        K: Borrow<Q>,
336
327
        R: Borrow<Q> + Send,
337
327
        Q: Ord + Hash + Eq + Debug + Sync,
338
327
    {
339
327
        let mut state = self.state.lock().await;
340
341
327
        let lru_len = state.lru.len();
342
369
        for (key, result) in 
keys.into_iter().zip(results.iter_mut())327
{
343
369
            let maybe_entry = if peek {
  Branch (343:34): [True: 0, False: 0]
  Branch (343:34): [True: 0, False: 225]
  Branch (343:34): [True: 0, False: 0]
  Branch (343:34): [True: 0, False: 0]
  Branch (343:34): [Folded - Ignored]
  Branch (343:34): [True: 0, False: 25]
  Branch (343:34): [True: 5, False: 0]
  Branch (343:34): [True: 3, False: 0]
  Branch (343:34): [True: 4, False: 0]
  Branch (343:34): [True: 0, False: 0]
  Branch (343:34): [True: 0, False: 0]
  Branch (343:34): [True: 0, False: 0]
  Branch (343:34): [True: 0, False: 0]
  Branch (343:34): [True: 0, False: 1]
  Branch (343:34): [True: 0, False: 5]
  Branch (343:34): [True: 0, False: 0]
  Branch (343:34): [Folded - Ignored]
  Branch (343:34): [True: 0, False: 47]
  Branch (343:34): [True: 0, False: 54]
344
12
                state.lru.peek_mut(key.borrow())
345
            } else {
346
357
                state.lru.get_mut(key.borrow())
347
            };
348
369
            match maybe_entry {
349
212
                Some(entry) => {
350
212
                    // Since we are not inserting anythign we don't need to evict based
351
212
                    // on the size of the store.
352
212
                    // Note: We need to check eviction because the item might be expired
353
212
                    // based on the current time. In such case, we remove the item while
354
212
                    // we are here.
355
212
                    let should_evict = self.should_evict(lru_len, entry, 0, u64::MAX);
356
212
                    if !should_evict && 
peek210
{
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [True: 100, False: 0]
  Branch (356:41): [True: 0, False: 100]
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [Folded - Ignored]
  Branch (356:41): [Folded - Ignored]
  Branch (356:24): [True: 13, False: 1]
  Branch (356:41): [True: 0, False: 13]
  Branch (356:24): [True: 3, False: 1]
  Branch (356:41): [True: 3, False: 0]
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [True: 3, False: 0]
  Branch (356:41): [True: 3, False: 0]
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [True: 3, False: 0]
  Branch (356:41): [True: 0, False: 3]
  Branch (356:24): [True: 0, False: 0]
  Branch (356:41): [True: 0, False: 0]
  Branch (356:24): [Folded - Ignored]
  Branch (356:41): [Folded - Ignored]
  Branch (356:24): [True: 34, False: 0]
  Branch (356:41): [True: 0, False: 34]
  Branch (356:24): [True: 54, False: 0]
  Branch (356:41): [True: 0, False: 54]
357
6
                        *result = Some(entry.data.len());
358
206
                    } else if !should_evict && 
entry.data.touch().await204
{
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 100, False: 0]
  Branch (358:48): [True: 100, False: 0]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [Folded - Ignored]
  Branch (358:48): [Folded - Ignored]
  Branch (358:31): [True: 13, False: 1]
  Branch (358:48): [True: 13, False: 0]
  Branch (358:31): [True: 0, False: 1]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [True: 3, False: 0]
  Branch (358:48): [True: 1, False: 2]
  Branch (358:31): [True: 0, False: 0]
  Branch (358:48): [True: 0, False: 0]
  Branch (358:31): [Folded - Ignored]
  Branch (358:48): [Folded - Ignored]
  Branch (358:31): [True: 34, False: 0]
  Branch (358:48): [True: 34, False: 0]
  Branch (358:31): [True: 54, False: 0]
  Branch (358:48): [True: 54, False: 0]
359
202
                        entry.seconds_since_anchor = self.anchor_time.elapsed().as_secs() as i32;
360
202
                        *result = Some(entry.data.len());
361
202
                    } else {
362
4
                        *result = None;
363
4
                        if let Some((key, eviction_item)) = state.lru.pop_entry(key.borrow()) {
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [Folded - Ignored]
  Branch (363:32): [True: 1, False: 0]
  Branch (363:32): [True: 1, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 2, False: 0]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [Folded - Ignored]
  Branch (363:32): [True: 0, False: 0]
  Branch (363:32): [True: 0, False: 0]
364
4
                            if should_evict {
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [Folded - Ignored]
  Branch (364:32): [True: 1, False: 0]
  Branch (364:32): [True: 1, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 2]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [Folded - Ignored]
  Branch (364:32): [True: 0, False: 0]
  Branch (364:32): [True: 0, False: 0]
365
2
                                event!(Level::INFO, ?key, 
"Item expired, evicting"0
);
366
                            } else {
367
2
                                event!(Level::INFO, ?key, 
"Touch failed, evicting"0
);
368
                            }
369
4
                            state.remove(key.borrow(), &eviction_item, false).await;
370
0
                        }
371
                    }
372
                }
373
157
                None => *result = None,
374
            }
375
        }
376
327
    }
377
378
5.00k
    pub async fn get<Q>(&self, key: &Q) -> Option<T>
379
5.00k
    where
380
5.00k
        K: Borrow<Q>,
381
5.00k
        Q: Ord + Hash + Eq + Debug + Sync,
382
5.00k
    {
383
5.00k
        let mut state = self.state.lock().await;
384
5.00k
        self.evict_items(&mut *state).await;
385
386
5.00k
        let 
entry4.49k
= state.lru.get_mut(key.borrow())
?509
;
387
388
4.49k
        if entry.data.touch().await {
  Branch (388:12): [True: 0, False: 0]
  Branch (388:12): [True: 4.45k, False: 0]
  Branch (388:12): [True: 0, False: 0]
  Branch (388:12): [Folded - Ignored]
  Branch (388:12): [True: 1, False: 0]
  Branch (388:12): [True: 3, False: 0]
  Branch (388:12): [True: 0, False: 0]
  Branch (388:12): [True: 1, False: 0]
  Branch (388:12): [True: 0, False: 0]
  Branch (388:12): [True: 1, False: 0]
  Branch (388:12): [True: 0, False: 0]
  Branch (388:12): [True: 11, False: 0]
  Branch (388:12): [True: 0, False: 0]
  Branch (388:12): [True: 4, False: 0]
  Branch (388:12): [Folded - Ignored]
  Branch (388:12): [True: 20, False: 0]
  Branch (388:12): [True: 3, False: 0]
389
4.49k
            entry.seconds_since_anchor = self.anchor_time.elapsed().as_secs() as i32;
390
4.49k
            return Some(entry.data.clone());
391
0
        }
392
393
0
        let (key, eviction_item) = state.lru.pop_entry(key.borrow())?;
394
0
        event!(Level::INFO, ?key, "Touch failed, evicting");
395
0
        state.remove(key.borrow(), &eviction_item, false).await;
396
0
        None
397
5.00k
    }
398
399
    /// Returns the replaced item if any.
400
5.85k
    pub async fn insert(&self, key: K, data: T) -> Option<T> {
401
5.85k
        self.insert_with_time(key, data, self.anchor_time.elapsed().as_secs() as i32)
402
5.85k
            .await
403
5.85k
    }
404
405
    /// Returns the replaced item if any.
406
5.85k
    pub async fn insert_with_time(&self, key: K, data: T, seconds_since_anchor: i32) -> Option<T> {
407
5.85k
        let mut state = self.state.lock().await;
408
5.85k
        let results = self
409
5.85k
            .inner_insert_many(&mut state, [(key, data)], seconds_since_anchor)
410
5.85k
            .await;
411
5.85k
        results.into_iter().next()
412
5.85k
    }
413
414
    /// Same as `insert()`, but optimized for multiple inserts.
415
    /// Returns the replaced items if any.
416
5
    pub async fn insert_many<It>(&self, inserts: It) -> Vec<T>
417
5
    where
418
5
        It: IntoIterator<Item = (K, T)> + Send,
419
5
        // Note: It's not enough to have the inserts themselves be Send. The
420
5
        // returned iterator should be Send as well.
421
5
        <It as IntoIterator>::IntoIter: Send,
422
5
    {
423
5
        let mut inserts = inserts.into_iter().peekable();
424
5
        // Shortcut for cases where there are no inserts, so we don't need to lock.
425
5
        if inserts.peek().is_none() {
  Branch (425:12): [True: 0, False: 0]
  Branch (425:12): [Folded - Ignored]
  Branch (425:12): [True: 1, False: 1]
  Branch (425:12): [True: 2, False: 1]
  Branch (425:12): [Folded - Ignored]
426
3
            return Vec::new();
427
2
        }
428
2
        let state = &mut self.state.lock().await;
429
2
        self.inner_insert_many(state, inserts, self.anchor_time.elapsed().as_secs() as i32)
430
2
            .await
431
5
    }
432
433
5.85k
    async fn inner_insert_many<It>(
434
5.85k
        &self,
435
5.85k
        state: &mut State<K, T>,
436
5.85k
        inserts: It,
437
5.85k
        seconds_since_anchor: i32,
438
5.85k
    ) -> Vec<T>
439
5.85k
    where
440
5.85k
        It: IntoIterator<Item = (K, T)> + Send,
441
5.85k
        // Note: It's not enough to have the inserts themselves be Send. The
442
5.85k
        // returned iterator should be Send as well.
443
5.85k
        <It as IntoIterator>::IntoIter: Send,
444
5.85k
    {
445
5.85k
        let mut replaced_items = Vec::new();
446
11.7k
        for (
key, data5.85k
) in inserts {
447
5.85k
            let new_item_size = data.len();
448
5.85k
            let eviction_item = EvictionItem {
449
5.85k
                seconds_since_anchor,
450
5.85k
                data,
451
5.85k
            };
452
453
5.85k
            if let Some(
old_item22
) = state.put(key, eviction_item).await {
  Branch (453:20): [True: 0, False: 0]
  Branch (453:20): [True: 8, False: 5.70k]
  Branch (453:20): [True: 0, False: 0]
  Branch (453:20): [True: 0, False: 0]
  Branch (453:20): [True: 0, False: 0]
  Branch (453:20): [Folded - Ignored]
  Branch (453:20): [True: 1, False: 1]
  Branch (453:20): [True: 0, False: 27]
  Branch (453:20): [True: 0, False: 3]
  Branch (453:20): [True: 0, False: 0]
  Branch (453:20): [True: 0, False: 1]
  Branch (453:20): [True: 0, False: 3]
  Branch (453:20): [True: 0, False: 1]
  Branch (453:20): [True: 0, False: 2]
  Branch (453:20): [True: 0, False: 2]
  Branch (453:20): [True: 1, False: 1]
  Branch (453:20): [True: 1, False: 1]
  Branch (453:20): [True: 0, False: 1]
  Branch (453:20): [True: 5, False: 17]
  Branch (453:20): [True: 0, False: 0]
  Branch (453:20): [Folded - Ignored]
  Branch (453:20): [True: 6, False: 43]
  Branch (453:20): [True: 0, False: 27]
454
22
                replaced_items.push(old_item);
455
5.83k
            }
456
5.85k
            state.sum_store_size += new_item_size;
457
5.85k
            state.lifetime_inserted_bytes.add(new_item_size);
458
5.85k
            self.evict_items(state).await;
459
        }
460
5.85k
        replaced_items
461
5.85k
    }
462
463
11
    pub async fn remove<Q>(&self, key: &Q) -> bool
464
11
    where
465
11
        K: Borrow<Q>,
466
11
        Q: Ord + Hash + Eq + Debug + Sync,
467
11
    {
468
11
        let mut state = self.state.lock().await;
469
11
        self.inner_remove(&mut state, key).await
470
11
    }
471
472
12
    async fn inner_remove<Q>(&self, state: &mut State<K, T>, key: &Q) -> bool
473
12
    where
474
12
        K: Borrow<Q>,
475
12
        Q: Ord + Hash + Eq + Debug + Sync,
476
12
    {
477
12
        self.evict_items(state).await;
478
12
        if let Some(
entry11
) = state.lru.pop(key.borrow()) {
  Branch (478:16): [True: 0, False: 0]
  Branch (478:16): [Folded - Ignored]
  Branch (478:16): [True: 6, False: 0]
  Branch (478:16): [True: 1, False: 0]
  Branch (478:16): [True: 1, False: 1]
  Branch (478:16): [True: 1, False: 0]
  Branch (478:16): [True: 1, False: 0]
  Branch (478:16): [True: 0, False: 0]
  Branch (478:16): [True: 0, False: 0]
  Branch (478:16): [True: 0, False: 0]
  Branch (478:16): [True: 0, False: 0]
  Branch (478:16): [True: 1, False: 0]
  Branch (478:16): [True: 0, False: 0]
  Branch (478:16): [True: 0, False: 0]
  Branch (478:16): [Folded - Ignored]
  Branch (478:16): [True: 0, False: 0]
479
11
            state.remove(key, &entry, false).await;
480
11
            return true;
481
1
        }
482
1
        false
483
12
    }
484
485
    /// Same as `remove()`, but allows for a conditional to be applied to the
486
    /// entry before removal in an atomic fashion.
487
1
    pub async fn remove_if<Q, F>(&self, key: &Q, cond: F) -> bool
488
1
    where
489
1
        K: Borrow<Q>,
490
1
        Q: Ord + Hash + Eq + Debug + Sync,
491
1
        F: FnOnce(&T) -> bool + Send,
492
1
    {
493
1
        let mut state = self.state.lock().await;
494
1
        if let Some(entry) = state.lru.get(key.borrow()) {
  Branch (494:16): [True: 0, False: 0]
  Branch (494:16): [Folded - Ignored]
  Branch (494:16): [True: 0, False: 0]
  Branch (494:16): [True: 0, False: 0]
  Branch (494:16): [True: 0, False: 0]
  Branch (494:16): [True: 0, False: 0]
  Branch (494:16): [True: 1, False: 0]
  Branch (494:16): [True: 0, False: 0]
  Branch (494:16): [True: 0, False: 0]
  Branch (494:16): [Folded - Ignored]
  Branch (494:16): [True: 0, False: 0]
495
1
            if !cond(&entry.data) {
  Branch (495:16): [True: 0, False: 0]
  Branch (495:16): [Folded - Ignored]
  Branch (495:16): [True: 0, False: 0]
  Branch (495:16): [True: 0, False: 0]
  Branch (495:16): [True: 0, False: 0]
  Branch (495:16): [True: 0, False: 0]
  Branch (495:16): [True: 0, False: 1]
  Branch (495:16): [True: 0, False: 0]
  Branch (495:16): [True: 0, False: 0]
  Branch (495:16): [Folded - Ignored]
  Branch (495:16): [True: 0, False: 0]
496
0
                return false;
497
1
            }
498
1
            return self.inner_remove(&mut state, key).await;
499
0
        }
500
0
        false
501
1
    }
502
}