use std::{fmt, sync::Arc};
use crate::sst::format::CompressionType;
pub type SkipPointFn = Arc<dyn Fn(&[u8]) -> bool + Send + Sync>;
#[derive(Clone)]
pub struct DbOptions {
pub create_if_missing: bool,
pub error_if_exists: bool,
pub write_buffer_size: usize,
pub max_immutable_memtables: usize,
pub l0_compaction_trigger: usize,
pub target_file_size_base: u64,
pub max_bytes_for_level_base: u64,
pub max_bytes_for_level_multiplier: f64,
pub num_levels: usize,
pub block_size: usize,
pub block_restart_interval: usize,
pub bloom_bits_per_key: u32,
pub compression: CompressionType,
pub block_cache_capacity: u64,
pub max_open_files: u64,
pub l0_slowdown_trigger: usize,
pub l0_stop_trigger: usize,
pub rate_limiter_bytes_per_sec: u64,
pub prefix_len: usize,
pub compression_per_level: Vec<CompressionType>,
pub compaction_filter: Option<Arc<dyn CompactionFilter>>,
pub max_background_compactions: usize,
pub max_subcompactions: usize,
pub pin_l0_filter_and_index_blocks_in_cache: bool,
pub block_property_collectors:
Vec<Arc<dyn Fn() -> Box<dyn BlockPropertyCollector> + Send + Sync>>,
pub lazy_delete_compaction_threshold: usize,
}
impl Default for DbOptions {
fn default() -> Self {
Self {
create_if_missing: true,
error_if_exists: false,
write_buffer_size: 64 * 1024 * 1024, max_immutable_memtables: 4,
l0_compaction_trigger: 4,
target_file_size_base: 64 * 1024 * 1024, max_bytes_for_level_base: 256 * 1024 * 1024, max_bytes_for_level_multiplier: 10.0,
num_levels: 7,
block_size: 4096,
block_restart_interval: 16,
bloom_bits_per_key: 10,
compression: CompressionType::None,
block_cache_capacity: 64 * 1024 * 1024, max_open_files: 1000,
l0_slowdown_trigger: 8,
l0_stop_trigger: 12,
rate_limiter_bytes_per_sec: 0,
prefix_len: 0,
compression_per_level: Vec::new(),
compaction_filter: None,
max_background_compactions: 1,
max_subcompactions: 1,
pin_l0_filter_and_index_blocks_in_cache: true,
block_property_collectors: Vec::new(),
lazy_delete_compaction_threshold: 10_000,
}
}
}
impl fmt::Debug for DbOptions {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DbOptions")
.field("create_if_missing", &self.create_if_missing)
.field("error_if_exists", &self.error_if_exists)
.field("write_buffer_size", &self.write_buffer_size)
.field("max_immutable_memtables", &self.max_immutable_memtables)
.field("l0_compaction_trigger", &self.l0_compaction_trigger)
.field("target_file_size_base", &self.target_file_size_base)
.field("max_bytes_for_level_base", &self.max_bytes_for_level_base)
.field(
"max_bytes_for_level_multiplier",
&self.max_bytes_for_level_multiplier,
)
.field("num_levels", &self.num_levels)
.field("block_size", &self.block_size)
.field("block_restart_interval", &self.block_restart_interval)
.field("bloom_bits_per_key", &self.bloom_bits_per_key)
.field("compression", &self.compression)
.field("block_cache_capacity", &self.block_cache_capacity)
.field("max_open_files", &self.max_open_files)
.field("l0_slowdown_trigger", &self.l0_slowdown_trigger)
.field("l0_stop_trigger", &self.l0_stop_trigger)
.field(
"rate_limiter_bytes_per_sec",
&self.rate_limiter_bytes_per_sec,
)
.field("prefix_len", &self.prefix_len)
.field("compression_per_level", &self.compression_per_level)
.field(
"compaction_filter",
&self.compaction_filter.as_ref().map(|_| ".."),
)
.field(
"max_background_compactions",
&self.max_background_compactions,
)
.field("max_subcompactions", &self.max_subcompactions)
.field(
"pin_l0_filter_and_index_blocks_in_cache",
&self.pin_l0_filter_and_index_blocks_in_cache,
)
.field(
"block_property_collectors",
&self.block_property_collectors.len(),
)
.field(
"lazy_delete_compaction_threshold",
&self.lazy_delete_compaction_threshold,
)
.finish()
}
}
impl DbOptions {
pub fn balanced() -> Self {
Self::default()
}
pub fn write_heavy() -> Self {
Self {
write_buffer_size: 128 * 1024 * 1024, l0_compaction_trigger: 8,
l0_slowdown_trigger: 20,
l0_stop_trigger: 36,
compression: CompressionType::Lz4,
max_background_compactions: 4,
..Default::default()
}
}
pub fn read_heavy() -> Self {
Self {
write_buffer_size: 32 * 1024 * 1024, l0_compaction_trigger: 2,
block_cache_capacity: 256 * 1024 * 1024, bloom_bits_per_key: 14,
pin_l0_filter_and_index_blocks_in_cache: true,
..Default::default()
}
}
}
#[derive(Clone)]
pub struct ReadOptions {
pub snapshot: Option<u64>,
pub fill_cache: bool,
pub skip_point: Option<SkipPointFn>,
pub block_property_filters: Vec<Arc<dyn BlockPropertyFilter>>,
pub iterate_lower_bound: Option<Vec<u8>>,
pub iterate_upper_bound: Option<Vec<u8>>,
}
impl Default for ReadOptions {
fn default() -> Self {
Self {
snapshot: None,
fill_cache: true,
skip_point: None,
block_property_filters: Vec::new(),
iterate_lower_bound: None,
iterate_upper_bound: None,
}
}
}
impl fmt::Debug for ReadOptions {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ReadOptions")
.field("snapshot", &self.snapshot)
.field("fill_cache", &self.fill_cache)
.field("skip_point", &self.skip_point.as_ref().map(|_| ".."))
.field("block_property_filters", &self.block_property_filters.len())
.field("iterate_lower_bound", &self.iterate_lower_bound)
.field("iterate_upper_bound", &self.iterate_upper_bound)
.finish()
}
}
#[derive(Debug, Clone, Default)]
pub struct WriteOptions {
pub sync: bool,
pub disable_wal: bool,
pub no_slowdown: bool,
}
#[derive(Debug)]
pub enum CompactionFilterDecision {
Keep,
Remove,
ChangeValue(Vec<u8>),
}
pub trait CompactionFilter: Send + Sync {
fn filter(&self, level: usize, key: &[u8], value: &[u8]) -> CompactionFilterDecision;
fn is_noop(&self) -> bool {
false
}
}
impl fmt::Debug for dyn CompactionFilter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CompactionFilter")
}
}
pub trait BlockPropertyCollector: Send + Sync {
fn add(&mut self, key: &[u8], value: &[u8]);
fn finish_block(&mut self) -> Vec<u8>;
fn name(&self) -> &str;
}
pub trait BlockPropertyFilter: Send + Sync {
fn should_skip(&self, properties: &[u8]) -> bool;
fn name(&self) -> &str;
}