use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Config {
pub storage: StorageConfig,
pub memory: MemoryConfig,
pub query: QueryConfig,
#[cfg(target_arch = "wasm32")]
pub wasm: WasmConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageConfig {
pub memtable_size_threshold: u64,
#[serde(default = "default_memtable_hard_limit")]
pub memtable_hard_limit: u64,
pub compaction: CompactionConfig,
pub compression: CompressionConfig,
#[serde(default = "default_use_mmap")]
pub use_mmap: bool,
#[serde(default = "default_mmap_min_size_bytes")]
pub mmap_min_size_bytes: usize,
#[serde(default)]
pub disk_access_mode: DiskAccessMode,
#[serde(default = "default_direct_io_memory_fraction")]
pub direct_io_memory_fraction: f64,
#[serde(default)]
pub prefetch: PrefetchMode,
#[serde(default = "default_direct_io_prefetch_bytes")]
pub direct_io_prefetch_bytes: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum DiskAccessMode {
#[default]
Auto,
Buffered,
Mmap,
Direct,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum PrefetchMode {
Off,
Sequential,
WillNeed,
#[default]
Auto,
}
fn default_use_mmap() -> bool {
false
}
fn default_memtable_hard_limit() -> u64 {
256 * 1024 * 1024
}
fn default_mmap_min_size_bytes() -> usize {
4096
}
fn default_direct_io_memory_fraction() -> f64 {
0.5
}
fn default_direct_io_prefetch_bytes() -> usize {
1024 * 1024
}
impl Default for StorageConfig {
fn default() -> Self {
Self {
memtable_size_threshold: 64 * 1024 * 1024,
memtable_hard_limit: default_memtable_hard_limit(),
compaction: CompactionConfig::default(),
compression: CompressionConfig::default(),
use_mmap: default_use_mmap(),
mmap_min_size_bytes: default_mmap_min_size_bytes(),
disk_access_mode: DiskAccessMode::default(),
direct_io_memory_fraction: default_direct_io_memory_fraction(),
prefetch: PrefetchMode::default(),
direct_io_prefetch_bytes: default_direct_io_prefetch_bytes(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompactionConfig {
pub auto_compaction: bool,
#[serde(default = "default_compaction_min_threshold")]
pub min_threshold: usize,
#[serde(default = "default_compaction_max_threshold")]
pub max_threshold: usize,
}
fn default_compaction_min_threshold() -> usize {
4
}
fn default_compaction_max_threshold() -> usize {
32
}
impl Default for CompactionConfig {
fn default() -> Self {
Self {
auto_compaction: true,
min_threshold: default_compaction_min_threshold(),
max_threshold: default_compaction_max_threshold(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MemoryConfig {
pub max_memory: u64,
pub block_cache: CacheConfig,
}
impl Default for MemoryConfig {
fn default() -> Self {
let max_memory = 1024 * 1024 * 1024;
Self {
max_memory,
block_cache: CacheConfig {
enabled: true,
max_size: max_memory / 4, policy: CachePolicy::Lru,
},
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CacheConfig {
pub enabled: bool,
pub max_size: u64,
pub policy: CachePolicy,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CachePolicy {
Lru,
}
pub const DEFAULT_MAX_RESULT_BYTES: u64 = 64 * 1024 * 1024;
fn default_max_result_bytes() -> u64 {
DEFAULT_MAX_RESULT_BYTES
}
fn default_max_result_rows() -> u64 {
1_000_000
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum ReadPathMode {
#[default]
Auto,
Point,
Full,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueryConfig {
pub max_execution_time: Duration,
#[serde(default)]
pub forced_read_path: Option<ReadPathMode>,
#[serde(default = "default_max_result_rows")]
pub max_result_rows: u64,
#[serde(default = "default_max_result_bytes")]
pub max_result_bytes: u64,
pub query_cache_size: Option<usize>,
pub query_parallelism: Option<usize>,
pub analyze_iterations: Option<usize>,
}
impl Default for QueryConfig {
fn default() -> Self {
Self {
max_execution_time: Duration::from_secs(300), forced_read_path: None,
max_result_rows: 1_000_000,
max_result_bytes: DEFAULT_MAX_RESULT_BYTES,
query_cache_size: Some(100),
query_parallelism: Some(num_cpus::get()),
analyze_iterations: Some(5),
}
}
}
#[cfg(target_arch = "wasm32")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WasmConfig {
pub use_indexeddb: bool,
pub max_memory: u64,
pub enable_simd: bool,
pub enable_workers: bool,
pub max_workers: usize,
}
#[cfg(target_arch = "wasm32")]
impl Default for WasmConfig {
fn default() -> Self {
Self {
use_indexeddb: true,
max_memory: 256 * 1024 * 1024, enable_simd: true,
enable_workers: true,
max_workers: 4,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CompressionAlgorithm {
None,
Lz4,
Snappy,
Deflate,
Zstd,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompressionConfig {
pub enabled: bool,
pub algorithm: CompressionAlgorithm,
pub level: i32,
pub min_block_size: u32,
}
impl Default for CompressionConfig {
fn default() -> Self {
Self {
enabled: true,
algorithm: CompressionAlgorithm::Lz4,
level: 1, min_block_size: 1024, }
}
}
impl Config {
pub fn memory_optimized() -> Self {
let mut config = Self::default();
config.storage.memtable_size_threshold = 4 * 1024 * 1024; config.memory.max_memory = 256 * 1024 * 1024; config.memory.block_cache.max_size = 64 * 1024 * 1024;
config.storage.compression.algorithm = CompressionAlgorithm::Zstd;
config.storage.compression.enabled = true;
config
}
pub fn performance_optimized() -> Self {
let mut config = Self::default();
config.storage.memtable_size_threshold = 128 * 1024 * 1024; config.memory.max_memory = 4 * 1024 * 1024 * 1024;
config.storage.compression.algorithm = CompressionAlgorithm::Lz4;
config.storage.compression.enabled = true;
config.memory.block_cache.max_size = 1024 * 1024 * 1024;
config
}
#[cfg(target_arch = "wasm32")]
pub fn wasm_optimized() -> Self {
let mut config = Self::memory_optimized();
config.wasm.max_memory = 128 * 1024 * 1024; config.wasm.enable_simd = true;
config.wasm.enable_workers = false;
config.memory.max_memory = 128 * 1024 * 1024; config.storage.memtable_size_threshold = 2 * 1024 * 1024;
config.storage.compaction.auto_compaction = false;
config
}
#[cfg(test)]
pub fn test_config() -> Self {
let mut config = Config::default();
config.storage.compaction.auto_compaction = false;
config.query.max_execution_time = std::time::Duration::from_secs(1);
config.memory.max_memory = 64 * 1024 * 1024; config.memory.block_cache.max_size = config.memory.max_memory / 4; config.storage.memtable_size_threshold = 1024 * 1024;
config
}
}
#[path = "config_json.rs"]
mod json;
#[path = "config_validate.rs"]
mod validate;
#[cfg(test)]
#[path = "config_tests.rs"]
mod tests;