sled/
context.rs

1use super::*;
2
3#[derive(Debug, Clone)]
4#[doc(hidden)]
5pub struct Context {
6    // TODO file from config should be in here
7    config: RunningConfig,
8    /// Periodically flushes dirty data. We keep this in an
9    /// Arc separate from the PageCache below to separate
10    /// "high-level" references from Db, Tree etc... from
11    /// "low-level" references like background threads.
12    /// When the last high-level reference is dropped, it
13    /// should trigger all background threads to clean
14    /// up synchronously.
15    #[cfg(all(
16        not(miri),
17        any(
18            windows,
19            target_os = "linux",
20            target_os = "macos",
21            target_os = "dragonfly",
22            target_os = "freebsd",
23            target_os = "openbsd",
24            target_os = "netbsd",
25        )
26    ))]
27    pub(crate) flusher: Arc<Mutex<Option<flusher::Flusher>>>,
28    #[doc(hidden)]
29    pub pagecache: Arc<PageCache>,
30}
31
32impl std::ops::Deref for Context {
33    type Target = RunningConfig;
34
35    fn deref(&self) -> &RunningConfig {
36        &self.config
37    }
38}
39
40impl Context {
41    pub(crate) fn start(config: RunningConfig) -> Result<Self> {
42        trace!("starting context");
43
44        let pagecache = Arc::new(PageCache::start(config.clone())?);
45
46        Ok(Self {
47            config,
48            pagecache,
49            #[cfg(all(
50                not(miri),
51                any(
52                    windows,
53                    target_os = "linux",
54                    target_os = "macos",
55                    target_os = "dragonfly",
56                    target_os = "freebsd",
57                    target_os = "openbsd",
58                    target_os = "netbsd",
59                )
60            ))]
61            flusher: Arc::new(parking_lot::Mutex::new(None)),
62        })
63    }
64
65    /// Returns `true` if the database was
66    /// recovered from a previous process.
67    /// Note that database state is only
68    /// guaranteed to be present up to the
69    /// last call to `flush`! Otherwise state
70    /// is synced to disk periodically if the
71    /// `sync_every_ms` configuration option
72    /// is set to `Some(number_of_ms_between_syncs)`
73    /// or if the IO buffer gets filled to
74    /// capacity before being rotated.
75    pub fn was_recovered(&self) -> bool {
76        self.pagecache.was_recovered()
77    }
78
79    /// Generate a monotonic ID. Not guaranteed to be
80    /// contiguous. Written to disk every `idgen_persist_interval`
81    /// operations, followed by a blocking flush. During recovery, we
82    /// take the last recovered generated ID and add 2x
83    /// the `idgen_persist_interval` to it. While persisting, if the
84    /// previous persisted counter wasn't synced to disk yet, we will do
85    /// a blocking flush to fsync the latest counter, ensuring
86    /// that we will never give out the same counter twice.
87    pub fn generate_id(&self) -> Result<u64> {
88        let _cc = concurrency_control::read();
89        self.pagecache.generate_id_inner()
90    }
91
92    pub(crate) fn pin_log(&self, guard: &Guard) -> Result<RecoveryGuard<'_>> {
93        self.pagecache.pin_log(guard)
94    }
95}