feat(enterprise): add auth TLS and recovery hardening

This commit is contained in:
2026-04-29 22:01:43 +00:00
parent 2f3031cfc7
commit ed2c02bcf9
27 changed files with 2369 additions and 55 deletions
+48 -7
View File
@@ -14,7 +14,7 @@ use dashmap::DashMap;
use crate::error::{StorageError, StorageResult};
use crate::record::{
DataRecord, FileHeader, FileType, RecordScanner, FILE_HEADER_SIZE, FORMAT_VERSION,
DataRecord, FileHeader, FileType, FILE_HEADER_SIZE, FORMAT_VERSION,
};
// ---------------------------------------------------------------------------
@@ -49,6 +49,10 @@ pub struct BuildStats {
pub tombstones: u64,
/// Number of records superseded by a later write for the same key.
pub superseded_records: u64,
/// Byte offset immediately after the last valid record.
pub valid_data_end: u64,
/// Number of invalid tail bytes after the last valid record.
pub invalid_tail_bytes: u64,
}
// ---------------------------------------------------------------------------
@@ -137,6 +141,7 @@ impl KeyDir {
/// stale records (superseded by later writes or tombstoned).
pub fn build_from_data_file(path: &Path) -> StorageResult<(Self, u64, BuildStats)> {
let file = std::fs::File::open(path)?;
let file_len = file.metadata()?.len();
let mut reader = BufReader::new(file);
// Read and validate file header
@@ -152,13 +157,49 @@ impl KeyDir {
let keydir = KeyDir::new();
let mut dead_bytes: u64 = 0;
let mut stats = BuildStats::default();
let mut stats = BuildStats {
valid_data_end: FILE_HEADER_SIZE as u64,
..BuildStats::default()
};
let scanner = RecordScanner::new(reader, FILE_HEADER_SIZE as u64);
for result in scanner {
let (offset, record) = result?;
loop {
let record_offset = stats.valid_data_end;
let (record, disk_size) = match DataRecord::decode_from(&mut reader) {
Ok(Some((record, disk_size))) => (record, disk_size),
Ok(None) => {
if file_len > record_offset {
stats.invalid_tail_bytes = file_len - record_offset;
}
break;
}
Err(StorageError::IoError(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
stats.invalid_tail_bytes = file_len.saturating_sub(record_offset);
break;
}
Err(StorageError::ChecksumMismatch { expected, actual }) => {
tracing::warn!(
path = %path.display(),
offset = record_offset,
"stopping data file scan at checksum mismatch: expected 0x{expected:08X}, got 0x{actual:08X}"
);
stats.invalid_tail_bytes = file_len.saturating_sub(record_offset);
break;
}
Err(StorageError::CorruptRecord(message)) => {
tracing::warn!(
path = %path.display(),
offset = record_offset,
"stopping data file scan at corrupt record: {message}"
);
stats.invalid_tail_bytes = file_len.saturating_sub(record_offset);
break;
}
Err(e) => return Err(e),
};
stats.valid_data_end += disk_size as u64;
let is_tombstone = record.is_tombstone();
let disk_size = record.disk_size() as u32;
let disk_size = disk_size as u32;
let value_len = record.value.len() as u32;
let timestamp = record.timestamp;
let key = String::from_utf8(record.key)
@@ -175,7 +216,7 @@ impl KeyDir {
dead_bytes += disk_size as u64;
} else {
let entry = KeyDirEntry {
offset,
offset: record_offset,
record_len: disk_size,
value_len,
timestamp,