use std::time::Duration;
use crate::cnf::Config;
use crate::kvs::config::{SyncMode, parse_duration};
use crate::sys::TOTAL_SYSTEM_MEMORY;
#[derive(Debug, Clone)]
pub struct SurrealKvConfig {
pub versioned: bool,
pub retention: Duration,
pub sync_mode: SyncMode,
pub enable_vlog: bool,
pub versioned_index: bool,
pub block_size: usize,
pub vlog_max_file_size: u64,
pub vlog_threshold: usize,
pub block_cache_capacity: u64,
pub grouped_commit_timeout: u64,
pub grouped_commit_wait_threshold: usize,
pub grouped_commit_max_batch_size: usize,
pub max_memtable_size: usize,
}
const KIB: u64 = 1024;
const MIB: u64 = 1024 * KIB;
const GIB: u64 = 1024 * MIB;
fn default_log_file_size() -> u64 {
let mem = *TOTAL_SYSTEM_MEMORY;
if mem < 4 * GIB {
64 * MIB
} else if mem < 16 * GIB {
128 * MIB
} else if mem < 64 * GIB {
256 * MIB
} else {
512 * MIB
}
}
fn default_block_cache_capacity() -> u64 {
let mem = *TOTAL_SYSTEM_MEMORY;
(mem / 2).saturating_sub(GIB).max(16 * MIB)
}
fn default_max_memtable_size() -> usize {
let mem = *TOTAL_SYSTEM_MEMORY;
if mem < GIB {
64 * MIB as usize
} else if mem < 4 * GIB {
128 * MIB as usize
} else if mem < 16 * GIB {
256 * MIB as usize
} else if mem < 64 * GIB {
GIB as usize
} else {
4 * GIB as usize
}
}
impl Default for SurrealKvConfig {
fn default() -> Self {
Self {
versioned: false,
retention: Duration::ZERO,
sync_mode: SyncMode::Every,
enable_vlog: true,
versioned_index: false,
block_size: (64 * KIB) as usize,
vlog_max_file_size: default_log_file_size(),
vlog_threshold: (4 * KIB) as usize,
block_cache_capacity: default_block_cache_capacity(),
grouped_commit_timeout: Duration::from_millis(5).as_nanos() as u64,
grouped_commit_wait_threshold: 12,
grouped_commit_max_batch_size: 4096,
max_memtable_size: default_max_memtable_size(),
}
}
}
impl Config for SurrealKvConfig {
fn parse(&mut self, map: &crate::cnf::ConfigMap) {
map.parse_key("datastore_versioned", &mut self.versioned)
.parse_key_with("datastore_retention", &mut self.retention, |x| parse_duration(x).ok())
.parse_key("surrealkv_enable_vlog", &mut self.enable_vlog)
.parse_key("surrealkv_versioned_index", &mut self.versioned_index)
.parse_key("surrealkv_block_size", &mut self.block_size)
.parse_key("surrealkv_vlog_max_file_size", &mut self.vlog_max_file_size)
.parse_key("surrealkv_vlog_threshold", &mut self.vlog_threshold)
.parse_key("surrealkv_block_cache_capacity", &mut self.block_cache_capacity)
.parse_key("surrealkv_grouped_commit_timeout", &mut self.grouped_commit_timeout)
.parse_key(
"surrealkv_grouped_commit_wait_threshold",
&mut self.grouped_commit_wait_threshold,
)
.parse_key(
"surrealkv_grouped_commit_max_batch_size",
&mut self.grouped_commit_max_batch_size,
)
.parse_key("surrealkv_max_memtable_size", &mut self.max_memtable_size);
if map.has_key("datastore_sync") {
map.parse_key("datastore_sync", &mut self.sync_mode);
} else {
map.parse_key("datastore_sync_data", &mut self.sync_mode);
}
}
}
#[cfg(test)]
mod test {
use std::time::Duration;
use crate::cnf::ConfigMap;
use crate::kvs::config::SyncMode;
use crate::kvs::surrealkv::cnf::SurrealKvConfig;
#[test]
fn test_surrealkv_config_defaults() {
let map = ConfigMap::empty();
let config = map.load::<SurrealKvConfig>();
assert!(!config.versioned);
assert_eq!(config.retention, Duration::ZERO);
assert_eq!(config.sync_mode, SyncMode::Every);
}
#[test]
fn test_surrealkv_config_from_params() {
let map = ConfigMap::from_config_string("versioned=true&retention=30d&sync=every");
let config = map.load::<SurrealKvConfig>();
assert!(config.versioned);
assert_eq!(config.retention, Duration::from_secs(30 * 24 * 60 * 60));
assert_eq!(config.sync_mode, SyncMode::Every);
}
#[test]
fn test_surrealkv_config_interval_sync() {
let map = ConfigMap::from_config_string("sync=5s");
let config = map.load::<SurrealKvConfig>();
assert_eq!(config.sync_mode, SyncMode::Interval(Duration::from_secs(5)));
}
}