use std::path::{Path, PathBuf};
use std::sync::Mutex;
use tracing::info;
use nodedb_types::config::tuning::WalTuning;
use nodedb_wal::segmented::{SegmentedWal, SegmentedWalConfig};
use nodedb_wal::writer::WalWriterConfig;
pub struct WalManager {
pub(super) wal: Mutex<SegmentedWal>,
pub(super) wal_dir: PathBuf,
pub(super) encryption_ring: Option<nodedb_wal::crypto::KeyRing>,
pub(super) audit_wal: Option<crate::wal::AuditWalSegment>,
}
impl WalManager {
pub fn open(path: &Path, use_direct_io: bool) -> crate::Result<Self> {
Self::open_with_segment_size(path, use_direct_io, 0)
}
pub fn open_with_segment_size(
path: &Path,
use_direct_io: bool,
segment_target_size: u64,
) -> crate::Result<Self> {
Self::open_internal(
path,
segment_target_size,
WalWriterConfig {
use_direct_io,
..Default::default()
},
)
}
pub fn open_with_tuning(
path: &Path,
use_direct_io: bool,
segment_target_size: u64,
tuning: &WalTuning,
) -> crate::Result<Self> {
Self::open_internal(
path,
segment_target_size,
WalWriterConfig {
write_buffer_size: tuning.write_buffer_size,
alignment: tuning.alignment,
use_direct_io,
dwb_mode: None,
},
)
}
pub(super) fn open_internal(
path: &Path,
segment_target_size: u64,
writer_config: WalWriterConfig,
) -> crate::Result<Self> {
let wal_dir = path.to_path_buf();
let effective_target = if segment_target_size > 0 {
segment_target_size
} else {
nodedb_wal::segment::DEFAULT_SEGMENT_TARGET_SIZE
};
let use_direct_io = writer_config.use_direct_io;
let config = SegmentedWalConfig {
wal_dir: wal_dir.clone(),
segment_target_size: effective_target,
writer_config,
};
let wal = SegmentedWal::open(config).map_err(crate::Error::Wal)?;
info!(
wal_dir = %wal_dir.display(),
next_lsn = wal.next_lsn(),
"WAL opened"
);
let audit_dir = wal_dir.join("audit.wal");
let audit_wal = match crate::wal::AuditWalSegment::open(&audit_dir, use_direct_io) {
Ok(aw) => {
info!(audit_dir = %audit_dir.display(), "audit WAL opened");
Some(aw)
}
Err(e) => {
tracing::warn!(error = %e, "audit WAL failed to open (audit entries not durable)");
None
}
};
Ok(Self {
wal: Mutex::new(wal),
wal_dir,
encryption_ring: None,
audit_wal,
})
}
pub fn open_for_testing(path: &Path) -> crate::Result<Self> {
Self::open(path, false)
}
pub fn wal_dir(&self) -> &Path {
&self.wal_dir
}
}