sled_overlay/
tree.rs

1/* This file is part of sled-overlay
2 *
3 * Copyright (C) 2023-2024 Dyne.org foundation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
19use std::{
20    cmp::Ordering,
21    collections::{btree_map::Keys, BTreeMap, BTreeSet},
22    iter::{FusedIterator, Peekable},
23};
24
25use sled::{IVec, Iter};
26
27/// Struct representing [`SledTreeOverlay`] cache state.
28#[derive(Debug, Default, Clone, PartialEq)]
29pub struct SledTreeOverlayState {
30    /// The cache is the actual overlayed data represented as a [`BTreeMap`].
31    pub cache: BTreeMap<IVec, IVec>,
32    /// In `removed`, we keep track of keys that were removed in the overlay.
33    pub removed: BTreeSet<IVec>,
34}
35
36impl SledTreeOverlayState {
37    /// Instantiate a new [`SledTreeOverlayState`].
38    pub fn new() -> Self {
39        Self {
40            cache: BTreeMap::new(),
41            removed: BTreeSet::new(),
42        }
43    }
44
45    /// Aggregate all the current tree overlay state changes into
46    /// a [`sled::Batch`] ready for further operation.
47    /// If there are no changes, return `None`.
48    pub fn aggregate(&self) -> Option<sled::Batch> {
49        if self.cache.is_empty() && self.removed.is_empty() {
50            return None;
51        }
52
53        let mut batch = sled::Batch::default();
54
55        // This kind of first-insert-then-remove operation should be fine
56        // provided it's handled correctly in the above functions.
57        for (k, v) in self.cache.iter() {
58            batch.insert(k, v);
59        }
60
61        for k in self.removed.iter() {
62            batch.remove(k);
63        }
64
65        Some(batch)
66    }
67
68    /// Add provided tree overlay state changes to our own.
69    pub fn add_diff(&mut self, diff: &SledTreeOverlayStateDiff) {
70        // Add all new keys into cache
71        for (k, v) in diff.cache.iter() {
72            self.removed.remove(k);
73            self.cache.insert(k.clone(), v.1.clone());
74        }
75
76        // Remove dropped keys
77        for k in diff.removed.keys() {
78            self.cache.remove(k);
79            self.removed.insert(k.clone());
80        }
81    }
82
83    /// Remove provided tree overlay state changes from our own.
84    pub fn remove_diff(&mut self, diff: &SledTreeOverlayStateDiff) {
85        for (k, v) in diff.cache.iter() {
86            // Skip if its not in cache
87            let Some(value) = self.cache.get(k) else {
88                continue;
89            };
90
91            // Check if its value has been modified again
92            if v.1 != value {
93                continue;
94            }
95
96            self.cache.remove(k);
97        }
98
99        for k in diff.removed.keys() {
100            self.removed.remove(k);
101        }
102    }
103}
104
105impl From<&SledTreeOverlayStateDiff> for SledTreeOverlayState {
106    fn from(diff: &SledTreeOverlayStateDiff) -> Self {
107        let mut cache = BTreeMap::new();
108        let mut removed = BTreeSet::new();
109
110        for (key, value) in diff.cache.iter() {
111            cache.insert(key.clone(), value.1.clone());
112        }
113
114        for key in diff.removed.keys() {
115            removed.insert(key.clone());
116        }
117
118        Self { cache, removed }
119    }
120}
121
122/// Auxilliary struct representing a [`SledTreeOverlayState`] diff log.
123#[derive(Debug, Default, Clone, PartialEq)]
124pub struct SledTreeOverlayStateDiff {
125    /// Inserted data represented as a [`BTreeMap`].
126    /// The value contains both the previous key value(if it existed), along
127    /// with the new one.
128    pub cache: BTreeMap<IVec, (Option<IVec>, IVec)>,
129    /// In `removed`, we keep track of keys that were removed in the overlay,
130    /// along with their value.
131    pub removed: BTreeMap<IVec, IVec>,
132}
133
134impl SledTreeOverlayStateDiff {
135    /// Instantiate a new [`SledTreeOverlayStateDiff`], over the provided
136    /// [`sled::Tree`] that is being overlayed.
137    pub fn new(tree: &sled::Tree, state: &SledTreeOverlayState) -> Result<Self, sled::Error> {
138        let mut cache = BTreeMap::new();
139        let mut removed = BTreeMap::new();
140
141        // Set inserted keys
142        for (key, value) in state.cache.iter() {
143            // Grab each key previous value, if it existed
144            let previous = tree.get::<IVec>(key.into())?;
145            cache.insert(key.into(), (previous, value.into()));
146        }
147
148        // Set removed keys, if they exist
149        for key in state.removed.iter() {
150            if let Some(previous) = tree.get(key)? {
151                removed.insert(key.into(), previous);
152            };
153        }
154
155        Ok(Self { cache, removed })
156    }
157
158    /// Instantiate a new [`SledTreeOverlayStateDiff`], over the provided
159    /// [`sled::Tree`] that is being dropped. The diff will contain all
160    /// existing tree keys in its cache as inserts, representing the last tree state.
161    pub fn new_dropped(tree: &sled::Tree) -> Self {
162        let mut cache = BTreeMap::new();
163
164        // Insert all tree keys
165        for record in tree.iter() {
166            let (key, value) = record.unwrap();
167            cache.insert(key, (None, value));
168        }
169
170        Self {
171            cache,
172            removed: BTreeMap::new(),
173        }
174    }
175
176    /// Aggregate all the tree overlay state changes into
177    /// a [`sled::Batch`] ready for further operation.
178    /// If there are no changes, return `None`.
179    pub fn aggregate(&self) -> Option<sled::Batch> {
180        if self.cache.is_empty() && self.removed.is_empty() {
181            return None;
182        }
183
184        let mut batch = sled::Batch::default();
185
186        // This kind of first-insert-then-remove operation should be fine
187        // provided it's handled correctly in the above functions.
188        for (k, v) in self.cache.iter() {
189            batch.insert(k, v.1.clone());
190        }
191
192        for k in self.removed.keys() {
193            batch.remove(k);
194        }
195
196        Some(batch)
197    }
198
199    /// Aggregate all the current tree overlay state changes inverse
200    /// actions into a [`sled::Batch`] ready for further operation.
201    /// If there are no changes, return `None`.
202    pub fn revert(&self) -> Option<sled::Batch> {
203        if self.cache.is_empty() && self.removed.is_empty() {
204            return None;
205        }
206
207        let mut batch = sled::Batch::default();
208
209        // This kind of first-insert-then-remove operation should be fine
210        // provided it's handled correctly in the above functions.
211        for (k, v) in self.removed.iter() {
212            batch.insert(k, v.clone());
213        }
214
215        for (k, v) in self.cache.iter() {
216            // If key value has been modified, revert to previous one
217            if let Some(value) = &v.0 {
218                batch.insert(k, value.clone());
219                continue;
220            }
221            batch.remove(k);
222        }
223
224        Some(batch)
225    }
226
227    /// Produces a [`SledTreeOverlayStateDiff`] containing the inverse
228    /// changes from our own.
229    pub fn inverse(&self) -> Self {
230        let mut diff = Self::default();
231
232        // This kind of first-insert-then-remove operation should be fine
233        // provided it's handled correctly in the above functions.
234        for (k, v) in self.removed.iter() {
235            diff.cache.insert(k.clone(), (None, v.clone()));
236        }
237
238        for (k, v) in self.cache.iter() {
239            // If its value has been modified, flip it
240            if let Some(previous) = &v.0 {
241                diff.cache
242                    .insert(k.clone(), (Some(v.1.clone()), previous.clone()));
243                continue;
244            }
245            diff.removed.insert(k.clone(), v.1.clone());
246        }
247
248        diff
249    }
250
251    /// Remove provided tree overlay state changes from our own.
252    pub fn remove_diff(&mut self, other: &Self) {
253        for (k, v) in other.cache.iter() {
254            // Set as removed if its not in cache
255            let Some(values) = self.cache.get(k) else {
256                self.removed.insert(k.clone(), v.1.clone());
257                continue;
258            };
259
260            // Check if its value has been modified again
261            if v.1 != values.1 {
262                // Set previous value
263                self.cache
264                    .insert(k.clone(), (Some(v.1.clone()), values.1.clone()));
265                continue;
266            }
267
268            self.cache.remove(k);
269        }
270
271        for k in other.removed.keys() {
272            // Update cache key previous, if it exits
273            if let Some(values) = self.cache.get(k) {
274                self.cache.insert(k.clone(), (None, values.1.clone()));
275                continue;
276            }
277
278            self.removed.remove(k);
279        }
280    }
281
282    /// Update our cache key values to the ones in the provided
283    /// tree overlay state changes.
284    pub fn update_values(&mut self, other: &Self) {
285        for (k, v) in other.cache.iter() {
286            self.cache.insert(k.clone(), v.clone());
287        }
288
289        for k in other.removed.keys() {
290            self.cache.remove(k);
291        }
292    }
293}
294
295/// An overlay on top of a single [`sled::Tree`] instance.
296#[derive(Debug, Clone)]
297pub struct SledTreeOverlay {
298    /// The [`sled::Tree`] that is being overlayed.
299    pub tree: sled::Tree,
300    /// Current overlay cache state.
301    pub state: SledTreeOverlayState,
302    /// Checkpointed cache state to revert to.
303    checkpoint: SledTreeOverlayState,
304}
305
306impl SledTreeOverlay {
307    /// Instantiate a new [`SledTreeOverlay`] on top of a given [`sled::Tree`].
308    pub fn new(tree: &sled::Tree) -> Self {
309        Self {
310            tree: tree.clone(),
311            state: SledTreeOverlayState::new(),
312            checkpoint: SledTreeOverlayState::new(),
313        }
314    }
315
316    /// Returns `true` if the overlay contains a value for a specified key.
317    pub fn contains_key(&self, key: &[u8]) -> Result<bool, sled::Error> {
318        // First check if the key was removed in the overlay
319        if self.state.removed.contains::<IVec>(&key.into()) {
320            return Ok(false);
321        }
322
323        // Then check the cache and the main tree
324        if self.state.cache.contains_key::<IVec>(&key.into()) || self.tree.contains_key(key)? {
325            return Ok(true);
326        }
327
328        Ok(false)
329    }
330
331    /// Returns `true` if the overlay is empty.
332    pub fn is_empty(&self) -> bool {
333        // Keep a counter of all elements
334        let mut counter: i64 = 0;
335
336        // Add existing keys
337        counter += self.tree.len() as i64;
338
339        // Add new keys
340        counter += self.state.cache.len() as i64;
341
342        // Subtract removed keys
343        counter -= self.state.removed.len() as i64;
344
345        counter <= 0
346    }
347
348    /// Returns last key and value from the overlay or `None` if its empty,
349    /// based on the `Ord` implementation for `Vec<u8>`.
350    pub fn last(&self) -> Result<Option<(IVec, IVec)>, sled::Error> {
351        // If both main tree and cache are empty, return None
352        if self.tree.is_empty() && self.state.cache.is_empty() {
353            return Ok(None);
354        }
355
356        // Grab main tree last record
357        let tree_last = self.tree.last()?;
358
359        // If cache has no records, main tree last exists
360        if self.state.cache.is_empty() {
361            // We can safely unwrap here since main tree is not
362            // empty, as we have already checked if both main
363            // tree and cache are empty.
364            let record = tree_last.unwrap();
365
366            // Check if record is removed
367            if self.state.removed.contains(&record.0) {
368                // Find last existing record
369                let mut key = record.0.clone();
370                while let Some(record) = self.tree.get_lt(key)? {
371                    // Check if record is removed
372                    if self.state.removed.contains(&record.0) {
373                        key = record.0;
374                        continue;
375                    }
376                    // Return it
377                    return Ok(Some((record.0.clone(), record.1.clone())));
378                }
379
380                // Return None if no records exist
381                return Ok(None);
382            }
383
384            // Return it
385            return Ok(Some((record.0.clone(), record.1.clone())));
386        }
387
388        // Grab cache last record.
389        // We can safely unwrap here as we checked if the cache is
390        // empty on the previous step.
391        let cache_last = self.state.cache.last_key_value().unwrap();
392
393        // If the main tree has a last record, compare it with the cache
394        // last record, and return it if it's not removed
395        if let Some(tree_last) = tree_last {
396            if cache_last.0 < &tree_last.0 && !self.state.removed.contains(&tree_last.0) {
397                return Ok(Some((tree_last.0.clone(), tree_last.1.clone())));
398            }
399        }
400
401        // Return the cache last record
402        Ok(Some((cache_last.0.clone(), cache_last.1.clone())))
403    }
404
405    /// Retrieve a value from the overlay if it exists.
406    pub fn get(&self, key: &[u8]) -> Result<Option<IVec>, sled::Error> {
407        // First check if the key was removed in the overlay
408        if self.state.removed.contains::<IVec>(&key.into()) {
409            return Ok(None);
410        }
411
412        // Then check the cache
413        if let Some(v) = self.state.cache.get::<IVec>(&key.into()) {
414            return Ok(Some(v.clone()));
415        }
416
417        // And finally the main tree
418        self.tree.get(key)
419    }
420
421    /// Insert a key to a new value, returning the last value if it was set.
422    pub fn insert(&mut self, key: &[u8], value: &[u8]) -> Result<Option<IVec>, sled::Error> {
423        // Insert the value into the cache. We then optionally add the previous value
424        // into `prev`.
425        let mut prev: Option<IVec> = self.state.cache.insert(key.into(), value.into());
426
427        // In case this key was previously removed from the cache, we have to
428        // delete it from the `removed` set.
429        if self.state.removed.contains::<IVec>(&key.into()) {
430            self.state.removed.remove(key);
431            // And in that case, a previous value isn't supposed to exist
432            return Ok(None);
433        }
434
435        // If cache didn't contain this key previously, and it wasn't removed
436        // either, then check if it's in the main tree.
437        if prev.is_none() {
438            prev = self.tree.get::<IVec>(key.into())?;
439        }
440
441        Ok(prev)
442    }
443
444    /// Delete a value, if it exists, returning the old value.
445    pub fn remove(&mut self, key: &[u8]) -> Result<Option<IVec>, sled::Error> {
446        // If it was previously removed, we can just return None
447        if self.state.removed.contains::<IVec>(&key.into()) {
448            return Ok(None);
449        }
450
451        // Attempt to remove from cache, and if it wasn't in the cache before,
452        // we have to get the previous value from the sled tree:
453        let mut prev: Option<IVec> = self.state.cache.remove::<IVec>(&key.into());
454        if prev.is_none() {
455            prev = self.tree.get(key)?;
456        }
457
458        // Previous value must existed
459        if prev.is_none() {
460            return Err(sled::Error::CollectionNotFound(key.into()));
461        }
462
463        // Mark the key as removed
464        self.state.removed.insert(key.into());
465
466        Ok(prev)
467    }
468
469    /// Removes all values from the cache and marks all tree records as
470    /// removed.
471    pub fn clear(&mut self) -> Result<(), sled::Error> {
472        // Clear state
473        self.state.cache = BTreeMap::new();
474
475        // Mark all the db's keys as removed
476        self.state.removed = self
477            .tree
478            .iter()
479            .keys()
480            .collect::<Result<BTreeSet<IVec>, sled::Error>>()?;
481
482        Ok(())
483    }
484
485    /// Aggregate all the current overlay changes into a [`sled::Batch`] ready for
486    /// further operation. If there are no changes, return `None`.
487    pub fn aggregate(&self) -> Option<sled::Batch> {
488        self.state.aggregate()
489    }
490
491    /// Checkpoint current cache state so we can revert to it, if needed.
492    pub fn checkpoint(&mut self) {
493        self.checkpoint = self.state.clone();
494    }
495
496    /// Revert to current cache state checkpoint.
497    pub fn revert_to_checkpoint(&mut self) {
498        self.state = self.checkpoint.clone();
499    }
500
501    /// Calculate differences from provided overlay state changes
502    /// sequence. This can be used when we want to keep track of
503    /// consecutive individual changes performed over the current
504    /// overlay state. If the sequence is empty, current state
505    /// is returned as the diff.
506    pub fn diff(
507        &self,
508        sequence: &[SledTreeOverlayStateDiff],
509    ) -> Result<SledTreeOverlayStateDiff, sled::Error> {
510        // Grab current state
511        let mut current = SledTreeOverlayStateDiff::new(&self.tree, &self.state)?;
512
513        // Remove provided diffs sequence
514        for diff in sequence {
515            current.remove_diff(diff);
516        }
517
518        Ok(current)
519    }
520
521    /// Add provided tree overlay state changes from our own.
522    pub fn add_diff(&mut self, diff: &SledTreeOverlayStateDiff) {
523        self.state.add_diff(diff)
524    }
525
526    /// Remove provided tree overlay state changes from our own.
527    pub fn remove_diff(&mut self, diff: &SledTreeOverlayStateDiff) {
528        self.state.remove_diff(diff)
529    }
530
531    /// Immutably iterate through the tree overlay.
532    pub fn iter(&self) -> SledTreeOverlayIter<'_> {
533        SledTreeOverlayIter::new(self)
534    }
535}
536
537/// Immutable iterator of a [`SledTreeOverlay`].
538pub struct SledTreeOverlayIter<'a> {
539    // Reference to the tree overlay.
540    overlay: &'a SledTreeOverlay,
541    // Iterator over [`sled::Tree`] keys that is being overlayed.
542    tree_iter: Peekable<Iter>,
543    // Iterator over the overlay's chache keys.
544    cache_iter: Peekable<Keys<'a, IVec, IVec>>,
545}
546
547impl<'a> SledTreeOverlayIter<'a> {
548    fn new(overlay: &'a SledTreeOverlay) -> Self {
549        Self {
550            overlay,
551            tree_iter: overlay.tree.iter().peekable(),
552            cache_iter: overlay.state.cache.keys().peekable(),
553        }
554    }
555}
556
557impl Iterator for SledTreeOverlayIter<'_> {
558    type Item = Result<(IVec, IVec), sled::Error>;
559
560    fn next(&mut self) -> Option<Self::Item> {
561        // First we peek over the next tree key
562        let peek1 = self.tree_iter.peek();
563
564        // Check if a sled error occured
565        if let Some(Err(e)) = peek1 {
566            return Some(Err(e.clone()));
567        }
568
569        // Peek over the next cache key
570        let peek2 = self.cache_iter.peek();
571
572        // Find the next key we have to grab,
573        // and which iterator to advance.
574        let mut advance_iter: u8 = 0;
575        let next_key = match (peek1, peek2) {
576            (Some(k1), Some(&k2)) => {
577                // Its safe to unwrap here since we already checked for errors
578                let (k1, _) = k1.as_ref().unwrap();
579                match k1.cmp(k2) {
580                    Ordering::Equal => Some(k1.clone()),
581                    Ordering::Greater => {
582                        advance_iter = 2;
583                        Some(k2.clone())
584                    }
585                    Ordering::Less => {
586                        advance_iter = 1;
587                        Some(k1.clone())
588                    }
589                }
590            }
591            (Some(k1), None) => {
592                // Its safe to unwrap here since we already checked for errors
593                let (k1, _) = k1.as_ref().unwrap();
594                advance_iter = 1;
595                Some(k1.clone())
596            }
597            (None, Some(&k2)) => {
598                advance_iter = 2;
599                Some(k2.clone())
600            }
601            (None, None) => None,
602        };
603
604        // Check if we have a key to grab
605        let next_key = next_key?;
606
607        // Advance the corresponding iterator
608        match advance_iter {
609            1 => {
610                self.tree_iter.next();
611            }
612            2 => {
613                self.cache_iter.next();
614            }
615            _ => {
616                self.tree_iter.next();
617                self.cache_iter.next();
618            }
619        }
620
621        // Grab the next key value from the overlay
622        match self.overlay.get(&next_key) {
623            Ok(next_value) => match next_value {
624                Some(next_value) => Some(Ok((next_key, next_value))),
625                // If the value doesn't exist, it means it's in the
626                // removed set, so we advance the iterator.
627                None => self.next(),
628            },
629            Err(e) => Some(Err(e)),
630        }
631    }
632}
633
634impl FusedIterator for SledTreeOverlayIter<'_> {}
635
636/// Define fusion iteration behavior, allowing
637/// us to use the [`SledTreeOverlayIter`] iterator in
638/// loops directly, without using .iter() method
639/// of [`SledTreeOverlay`].
640impl<'a> IntoIterator for &'a SledTreeOverlay {
641    type Item = Result<(IVec, IVec), sled::Error>;
642
643    type IntoIter = SledTreeOverlayIter<'a>;
644
645    fn into_iter(self) -> Self::IntoIter {
646        self.iter()
647    }
648}