Skip to main content

lace_rt/
compaction.rs

1//! Offline compaction of a native root (Lace-100 "Compacting a root").
2
3use std::path::Path;
4
5use lace_sans_io::core::RetentionSweep;
6use lace_sans_io::runtime_support::compaction::DEFAULT_COMPACTION_BATCH_BYTES;
7pub use lace_sans_io::runtime_support::compaction::{ArenaRelease, CompactionReport};
8use lace_sans_io::runtime_support::native_filesystem_store::compact_filesystem_root;
9
10use crate::{Error, IntoPolicy, Result};
11
12/// Remove every record of the filesystem root at `root` that none of
13/// `policies` selects, and release its bytes in place.
14///
15/// The root must have no open Lace and no live arena-backed record in any
16/// process. A root holding an interrupted compaction resumes it without
17/// evaluating `policies`.
18pub fn compact_filesystem<P: IntoPolicy>(
19    root: impl AsRef<Path>,
20    policies: impl IntoIterator<Item = P>,
21) -> Result<CompactionReport> {
22    let sweep = retention_sweep(policies)?;
23    compact_filesystem_root(
24        root.as_ref(),
25        sweep,
26        DEFAULT_COMPACTION_BATCH_BYTES,
27        &|| false,
28    )
29    .map_err(|error| Error::from_machine(error, None))
30}
31
32/// Remove every record of the LMDB root at `root` that none of `policies`
33/// selects, and release its arena bytes in place.
34///
35/// No other process may have the root open and no arena-backed record of it
36/// may be alive anywhere. Contending opens fail when their bounded
37/// bootstrap-lock retry expires. A root holding an interrupted compaction
38/// resumes it without evaluating `policies`.
39#[cfg(feature = "lmdb")]
40pub fn compact_lmdb<P: IntoPolicy>(
41    root: impl AsRef<Path>,
42    policies: impl IntoIterator<Item = P>,
43) -> Result<CompactionReport> {
44    let sweep = retention_sweep(policies)?;
45    lmdb_lace::NativeLmdbStore::compact(
46        root.as_ref(),
47        sweep,
48        DEFAULT_COMPACTION_BATCH_BYTES,
49        &|| false,
50    )
51    .map_err(|error| Error::from_machine(error, None))
52}
53
54fn retention_sweep<P: IntoPolicy>(policies: impl IntoIterator<Item = P>) -> Result<RetentionSweep> {
55    let policies = policies
56        .into_iter()
57        .map(IntoPolicy::into_policy)
58        .collect::<Result<Vec<_>>>()?;
59    Ok(RetentionSweep::new(&policies)?)
60}
61
62#[cfg(test)]
63#[path = "compaction_tests.rs"]
64mod tests;