mod memtable;
mod unified_memtable; mod sstable;
mod compaction;
mod engine;
mod bloom;
mod blobstore;
mod merging_iterator;
pub use memtable::MemTable;
pub use unified_memtable::{UnifiedMemTable, UnifiedEntry}; pub use sstable::{SSTable, SSTableBuilder, BlockIndex};
pub use compaction::{CompactionWorker, CompactionConfig, Level, SSTableMeta, CompactionStats};
pub use engine::{LSMEngine, LSMBatchedIterator}; pub use bloom::BloomFilter;
pub use blobstore::BlobStore;
pub use merging_iterator::MergingIterator;
pub type Key = u64;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BlobRef {
pub file_id: u32,
pub offset: u64,
pub size: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ValueData {
Inline(Vec<u8>),
Blob(BlobRef),
}
impl ValueData {
pub fn len(&self) -> usize {
match self {
ValueData::Inline(data) => data.len(),
ValueData::Blob(_) => 16, }
}
pub fn is_empty(&self) -> bool {
match self {
ValueData::Inline(data) => data.is_empty(),
ValueData::Blob(_) => false,
}
}
}
#[derive(Clone, Debug)]
pub struct Value {
pub data: ValueData,
pub timestamp: u64,
pub deleted: bool,
}
impl Value {
pub fn new(data: Vec<u8>, timestamp: u64) -> Self {
Self {
data: ValueData::Inline(data),
timestamp,
deleted: false,
}
}
pub fn new_blob(blob_ref: BlobRef, timestamp: u64) -> Self {
Self {
data: ValueData::Blob(blob_ref),
timestamp,
deleted: false,
}
}
pub fn tombstone(timestamp: u64) -> Self {
Self {
data: ValueData::Inline(Vec::new()),
timestamp,
deleted: true,
}
}
pub fn as_inline(&self) -> Option<&[u8]> {
match &self.data {
ValueData::Inline(data) => Some(data),
ValueData::Blob(_) => None,
}
}
pub fn is_blob(&self) -> bool {
matches!(self.data, ValueData::Blob(_))
}
}
#[derive(Clone, Debug)]
pub struct LSMConfig {
pub memtable_size: usize,
pub block_size: usize,
pub num_levels: usize,
pub level_multiplier: usize,
pub l0_compaction_trigger: usize,
pub bloom_bits_per_key: usize,
pub enable_compression: bool,
pub blob_threshold: usize,
pub blob_file_size: usize,
pub sstable_cache_size: usize,
pub sstable_cache_memory_limit_mb: Option<usize>,
}
impl Default for LSMConfig {
fn default() -> Self {
Self {
memtable_size: 512 * 1024, block_size: 64 * 1024, num_levels: 7,
level_multiplier: 10,
l0_compaction_trigger: 2, bloom_bits_per_key: 12, enable_compression: true,
blob_threshold: 32 * 1024, blob_file_size: 256 * 1024 * 1024, sstable_cache_size: 8, sstable_cache_memory_limit_mb: Some(200), }
}
}
impl LSMConfig {
pub fn from_db_config(db_config: &crate::config::LSMConfig) -> Self {
let mut base = Self::default();
base.memtable_size = db_config.memtable_size_limit;
base.l0_compaction_trigger = db_config.level0_compaction_threshold;
base.bloom_bits_per_key = db_config.bloom_filter_false_positive_rate as usize;
base
}
pub fn read_optimized() -> Self {
Self {
memtable_size: 4 * 1024 * 1024,
block_size: 32 * 1024, num_levels: 7,
level_multiplier: 10,
l0_compaction_trigger: 2, bloom_bits_per_key: 16, enable_compression: true,
blob_threshold: 32 * 1024,
blob_file_size: 256 * 1024 * 1024,
sstable_cache_size: 16, sstable_cache_memory_limit_mb: Some(400), }
}
pub fn write_optimized() -> Self {
Self {
memtable_size: 16 * 1024 * 1024, block_size: 128 * 1024, num_levels: 6, level_multiplier: 8, l0_compaction_trigger: 8, bloom_bits_per_key: 8, enable_compression: true,
blob_threshold: 32 * 1024,
blob_file_size: 256 * 1024 * 1024,
sstable_cache_size: 8,
sstable_cache_memory_limit_mb: Some(200), }
}
pub fn embedded() -> Self {
Self {
memtable_size: 2 * 1024 * 1024, block_size: 32 * 1024, num_levels: 6, level_multiplier: 8, l0_compaction_trigger: 2,
bloom_bits_per_key: 8, enable_compression: true,
blob_threshold: 16 * 1024, blob_file_size: 128 * 1024 * 1024, sstable_cache_size: 4, sstable_cache_memory_limit_mb: Some(40), }
}
pub fn tiny() -> Self {
Self {
memtable_size: 1024 * 1024, block_size: 16 * 1024, num_levels: 5, level_multiplier: 4, l0_compaction_trigger: 2,
bloom_bits_per_key: 6, enable_compression: true,
blob_threshold: 8 * 1024, blob_file_size: 64 * 1024 * 1024, sstable_cache_size: 2, sstable_cache_memory_limit_mb: Some(20), }
}
pub fn memory_optimized() -> Self {
Self {
memtable_size: 2 * 1024 * 1024, block_size: 32 * 1024, num_levels: 7,
level_multiplier: 10,
l0_compaction_trigger: 2, bloom_bits_per_key: 10, enable_compression: true, blob_threshold: 16 * 1024, blob_file_size: 128 * 1024 * 1024, sstable_cache_size: 4, sstable_cache_memory_limit_mb: Some(100), }
}
pub fn balanced() -> Self {
Self::default()
}
}