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}