use radixdb_core::time_compat::{system_time_now, UNIX_EPOCH};
use std::fs::{self, File, OpenOptions};
use std::io::{self, BufReader, Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU64, Ordering};
use std::sync::Mutex;
use std::time::Instant;
use crate::cpu_runtime::StorageCpuLease;
use crate::instrumentation;
use crate::{PersistenceConfig, SyncMode};
use radixdb_catalog::ObjectId;
use radixdb_core::{Error, Result};
#[cfg(feature = "parallel")]
use rayon::prelude::*;
const WAL_ENTRY_MAGIC: u32 = 0x454C4157;
pub const DEFAULT_WAL_MAX_SIZE: u64 = 64 * 1024 * 1024;
pub const DEFAULT_WAL_FLUSH_TRIGGER: u64 = 32 * 1024;
pub const DEFAULT_WAL_BUFFER_SIZE: usize = 64 * 1024;
const WAL_VALIDATION_READ_BUFFER_SIZE: usize = 1024 * 1024;
const WAL_FORMAT_VERSION: u8 = 4;
const WAL_HEADER_SIZE: u16 = 32;
const MAX_WAL_RECORD_DATA_SIZE: usize = 64 * 1024 * 1024;
const MIN_WAL_RECORD_DATA_SIZE: usize = 8 + 16 + 8 + 1 + 8 + 4;
const WAL_KNOWN_FLAGS: u8 = 0x7f;
pub struct WALManager {
path: PathBuf,
wal_file: Mutex<Option<File>>,
current_wal_file: Mutex<String>,
current_lsn: AtomicU64,
previous_lsn: AtomicU64,
buffer: Mutex<Vec<u8>>,
flush_trigger: u64,
max_wal_size: u64,
last_checkpoint: AtomicU64,
transaction_high_water: AtomicI64,
sync_mode: SyncMode,
running: AtomicBool,
transition: Mutex<WalTransitionState>,
sync_clock_origin: Instant,
last_sync_elapsed_nanos: AtomicU64,
sync_interval_nanos: u64,
current_file_position: AtomicU64,
last_synced_file_position: AtomicU64,
wal_sequence: AtomicU64,
replay_floor: Mutex<crate::v6::WalReplayFloor>,
validated_closed_generations: Mutex<Vec<ValidatedWalGeneration>>,
#[cfg(any(test, feature = "test-hooks"))]
runtime_generation_validation_bytes: AtomicU64,
#[cfg(any(test, feature = "test-hooks"))]
append_test_hook: Mutex<Option<WalAppendTestHook>>,
#[cfg(any(test, feature = "test-hooks"))]
append_test_hook_owner: Mutex<()>,
#[cfg(test)]
close_test_hook: Mutex<Option<WalCloseTestHook>>,
#[cfg(test)]
close_test_hook_owner: Mutex<()>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct SnapshotWalGeneration {
generation: crate::v6::WalGeneration,
path: PathBuf,
byte_length: u64,
}
impl SnapshotWalGeneration {
pub(crate) const fn generation(&self) -> crate::v6::WalGeneration {
self.generation
}
pub(crate) fn path(&self) -> &Path {
&self.path
}
pub(crate) const fn byte_length(&self) -> u64 {
self.byte_length
}
}
mod append;
mod checkpoint;
mod open;
mod record;
mod recovery;
mod replay;
mod rotation;
pub use record::{WALEntry, WALOperationType, WalFlags};
pub use recovery::TwoPhaseRecoveryInfo;
use recovery::*;
#[cfg(any(test, feature = "test-hooks"))]
#[doc(hidden)]
pub use recovery::{
recovery_outcome_spill_count, reset_recovery_outcome_spill_count, WalAppendTestHook,
WalAppendTestHookGuard, TEST_RECOVERY_OUTCOME_MEMORY_LIMIT,
};
#[cfg(test)]
mod tests;