lsm_tree/
seqno.rs

1// Copyright (c) 2024-present, fjall-rs
2// This source code is licensed under both the Apache 2.0 and MIT License
3// (found in the LICENSE-* files in the repository)
4
5use crate::SeqNo;
6use std::sync::{
7    atomic::{
8        AtomicU64,
9        Ordering::{Acquire, Release},
10    },
11    Arc,
12};
13
14/// Thread-safe sequence number generator
15///
16/// # Examples
17///
18/// ```
19/// # use lsm_tree::{AbstractTree, Config, SequenceNumberCounter};
20/// #
21/// # let path = tempfile::tempdir()?;
22/// let tree = Config::new(path).open()?;
23///
24/// let seqno = SequenceNumberCounter::default();
25///
26/// // Do some inserts...
27/// tree.insert("a".as_bytes(), "abc", seqno.next());
28/// tree.insert("b".as_bytes(), "abc", seqno.next());
29/// tree.insert("c".as_bytes(), "abc", seqno.next());
30///
31/// // Maybe create a snapshot
32/// let snapshot = tree.snapshot(seqno.get());
33///
34/// // Create a batch
35/// let batch_seqno = seqno.next();
36/// tree.remove("a".as_bytes(), batch_seqno);
37/// tree.remove("b".as_bytes(), batch_seqno);
38/// tree.remove("c".as_bytes(), batch_seqno);
39/// #
40/// # assert!(tree.is_empty(None, None)?);
41/// # Ok::<(), lsm_tree::Error>(())
42/// ```
43#[derive(Clone, Default, Debug)]
44pub struct SequenceNumberCounter(Arc<AtomicU64>);
45
46impl std::ops::Deref for SequenceNumberCounter {
47    type Target = Arc<AtomicU64>;
48
49    fn deref(&self) -> &Self::Target {
50        &self.0
51    }
52}
53
54impl SequenceNumberCounter {
55    /// Creates a new counter, setting it to some previous value
56    #[must_use]
57    pub fn new(prev: SeqNo) -> Self {
58        Self(Arc::new(AtomicU64::new(prev)))
59    }
60
61    /// Gets the next sequence number, without incrementing the counter.
62    ///
63    /// This should only be used when creating a snapshot.
64    #[must_use]
65    pub fn get(&self) -> SeqNo {
66        self.load(Acquire)
67    }
68
69    /// Gets the next sequence number.
70    #[must_use]
71    pub fn next(&self) -> SeqNo {
72        self.fetch_add(1, Release)
73    }
74}