Skip to main content

krabka_verified/
local_recovery.rs

1//! Local-log segment-chain and torn-tail recovery decisions.
2
3#[cfg(creusot)]
4use creusot_std::prelude::{DeepModel, Int, invariant, logic};
5
6#[krabka_macros::model_type]
7pub struct LocalRecoveryStep {
8    pub valid_end: u64,
9    pub last_offset: i64,
10    pub next_offset: i64,
11}
12
13/// What `Log::open` observes at one base offset that carries a compaction
14/// `.swap` file, from a single directory listing.
15///
16/// Compaction writes its survivor segment under `.cleaned` names, fsyncs it,
17/// renames the sidecars and then the log from `.cleaned` to `.swap`, and only
18/// after that rename is durable deletes the segments it replaces. So a
19/// `.log.swap` with no `.log.cleaned` beside it is a complete, durable segment,
20/// and it may already be the only copy of the records it holds.
21#[krabka_macros::model_type]
22pub struct LocalRecoverySwapFacts {
23    /// `<base>.log.cleaned` exists: the rewrite, or its rename to `.swap`,
24    /// never finished.
25    pub log_cleaned_exists: bool,
26    /// `<base>.log.swap` exists.
27    pub log_swap_exists: bool,
28    /// `<base>.log` exists.
29    pub final_log_exists: bool,
30}
31
32/// Crash-recovery action for one base offset that carries `.swap` files.
33#[krabka_macros::model_type]
34pub enum LocalRecoverySwapAction {
35    /// The swap never committed: delete its `.swap` files. No segment it
36    /// would replace has been touched.
37    AbortSwap,
38    /// The swap committed: delete every segment it replaces, then rename the
39    /// swap into place. This is Kafka's `LogLoader.load` second and third
40    /// passes.
41    CompleteSwap,
42    /// The log rename already finished; promote the remaining sidecars.
43    PromoteSidecars,
44    /// Sidecar swaps with no log in any form.
45    Reject,
46}
47
48mod index_frontier;
49#[cfg(creusot)]
50pub use index_frontier::swap_committed;
51pub use index_frontier::{
52    local_recovery_batch_step, local_recovery_index_frontier, local_recovery_sealed_last,
53    local_recovery_segment_chain, local_recovery_swap_action, local_recovery_swap_replaces,
54};
55
56#[cfg(test)]
57mod tests;