#![allow(dead_code)]
#![allow(unused_imports)]
pub mod compaction;
pub mod manifest;
pub mod segment;
use std::path::Path;
use manifest::{CompactionMetadata, SegmentTier};
pub type Result<T> = std::result::Result<T, StorageError>;
#[derive(Debug, thiserror::Error)]
pub enum StorageError {
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("checksum mismatch for page {page} in segment {segment}")]
ChecksumMismatch { segment: String, page: usize },
#[error("segment too small: {0} bytes")]
SegmentTooSmall(u64),
#[error("segment too large: {0} bytes (expected at most 256 MiB)")]
SegmentTooLarge(u64),
#[error("manifest serialization error: {0}")]
ManifestSerde(#[from] serde_json::Error),
#[error("invalid storage format: {0}")]
InvalidFormat(String),
#[error("compression error: {0}")]
Compression(String),
}
pub trait Segment: Send + Sync {
fn metadata(&self) -> &segment::SegmentMetadata;
fn open_reader(&self) -> Result<segment::SegmentReader>;
}
pub trait Manifest: Send + Sync {
fn register_segment(
&mut self,
tier: SegmentTier,
metadata: segment::SegmentMetadata,
) -> Result<()>;
fn record_compaction(
&mut self,
output_tier: SegmentTier,
output: segment::SegmentMetadata,
retired: Vec<String>,
metadata: CompactionMetadata,
) -> Result<()>;
fn persist(&self) -> Result<()>;
}
pub fn manifest_exists(path: &Path) -> bool {
path.exists()
}
pub fn validate_segment_length(length: u64) -> Result<()> {
if length == 0 {
return Err(StorageError::SegmentTooSmall(length));
}
const MAX: u64 = 256 * 1024 * 1024;
if length > MAX {
return Err(StorageError::SegmentTooLarge(length));
}
Ok(())
}
pub use segment::{CompressionCodec, FileSegment, SegmentMetadata, SegmentReader, SegmentWriter};
pub use manifest::FileManifest;
pub use compaction::{CompactionJob, Compactor};