use tessarikv_constants as limits;
use super::bounds::check_range;
use super::keyspace::KeyspaceOptions;
use super::modes::{StorageMode, WalRecovery};
use crate::{Error, Result};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DbOptions {
create_if_missing: bool,
error_if_exists: bool,
storage: StorageMode,
wal_segment_bytes: u64,
wal_recovery: WalRecovery,
block_cache_bytes: u64,
background_threads: u32,
compaction_bytes_per_second: u64,
delayed_write_bytes_per_second: u64,
serializable_transactions: bool,
pub(super) total_memtable_bytes: u64,
pub(super) max_open_files: u32,
pub(super) encryption: Option<super::Encryption>,
pub(super) encryption_cipher: Option<tessarikv_format::Cipher>,
pub(super) max_manifest_bytes: u64,
pub(super) statistics: bool,
default_keyspace: KeyspaceOptions,
pub(super) keyspaces: Vec<(String, KeyspaceOptions)>,
pub(super) create_missing_keyspaces: bool,
}
impl Default for DbOptions {
fn default() -> Self {
Self {
create_if_missing: true,
error_if_exists: false,
storage: StorageMode::Os,
wal_segment_bytes: limits::DEFAULT_WAL_SEGMENT_BYTES,
wal_recovery: WalRecovery::PointInTime,
block_cache_bytes: limits::DEFAULT_BLOCK_CACHE_BYTES,
background_threads: limits::DEFAULT_BACKGROUND_THREADS,
compaction_bytes_per_second: 0,
delayed_write_bytes_per_second: limits::DEFAULT_DELAYED_WRITE_BYTES_PER_SECOND,
serializable_transactions: false,
total_memtable_bytes: 0,
max_open_files: 0,
encryption: None,
encryption_cipher: None,
max_manifest_bytes: limits::DEFAULT_MAX_MANIFEST_BYTES,
statistics: false,
default_keyspace: KeyspaceOptions::default(),
keyspaces: Vec::new(),
create_missing_keyspaces: false,
}
}
}
impl DbOptions {
pub fn builder() -> DbOptionsBuilder {
Self::default().to_builder()
}
pub fn to_builder(&self) -> DbOptionsBuilder {
DbOptionsBuilder {
options: self.clone(),
}
}
#[must_use]
pub fn in_memory() -> Self {
Self {
storage: StorageMode::Memory,
..Self::default()
}
}
#[must_use]
pub const fn create_if_missing(&self) -> bool {
self.create_if_missing
}
#[must_use]
pub const fn error_if_exists(&self) -> bool {
self.error_if_exists
}
#[must_use]
pub const fn storage(&self) -> StorageMode {
self.storage
}
#[must_use]
pub const fn wal_segment_bytes(&self) -> u64 {
self.wal_segment_bytes
}
pub const fn wal_recovery(&self) -> WalRecovery {
self.wal_recovery
}
#[must_use]
pub const fn block_cache_bytes(&self) -> u64 {
self.block_cache_bytes
}
#[must_use]
pub const fn default_keyspace(&self) -> &KeyspaceOptions {
&self.default_keyspace
}
#[must_use]
pub const fn background_threads(&self) -> u32 {
self.background_threads
}
#[must_use]
pub const fn compaction_bytes_per_second(&self) -> u64 {
self.compaction_bytes_per_second
}
#[must_use]
pub const fn serializable_transactions(&self) -> bool {
self.serializable_transactions
}
#[must_use]
pub const fn delayed_write_bytes_per_second(&self) -> u64 {
self.delayed_write_bytes_per_second
}
}
#[derive(Debug, Clone)]
#[must_use]
pub struct DbOptionsBuilder {
pub(super) options: DbOptions,
}
impl DbOptionsBuilder {
pub const fn create_if_missing(mut self, value: bool) -> Self {
self.options.create_if_missing = value;
self
}
pub const fn error_if_exists(mut self, value: bool) -> Self {
self.options.error_if_exists = value;
self
}
pub const fn storage(mut self, value: StorageMode) -> Self {
self.options.storage = value;
self
}
pub const fn serializable_transactions(mut self, value: bool) -> Self {
self.options.serializable_transactions = value;
self
}
pub const fn wal_segment_bytes(mut self, value: u64) -> Self {
self.options.wal_segment_bytes = value;
self
}
pub const fn wal_recovery(mut self, value: WalRecovery) -> Self {
self.options.wal_recovery = value;
self
}
pub const fn block_cache_bytes(mut self, value: u64) -> Self {
self.options.block_cache_bytes = value;
self
}
pub const fn background_threads(mut self, value: u32) -> Self {
self.options.background_threads = value;
self
}
pub const fn compaction_bytes_per_second(mut self, value: u64) -> Self {
self.options.compaction_bytes_per_second = value;
self
}
pub const fn delayed_write_bytes_per_second(mut self, value: u64) -> Self {
self.options.delayed_write_bytes_per_second = value;
self
}
pub fn default_keyspace(mut self, value: KeyspaceOptions) -> Self {
self.options.default_keyspace = value;
self
}
pub fn build(self) -> Result<DbOptions> {
let options = self.options;
if options.error_if_exists && !options.create_if_missing {
return Err(Error::InvalidOptions {
option: "db.error_if_exists",
reason: "set without create_if_missing, no open could succeed".to_owned(),
});
}
check_range(
"db.wal_segment_bytes",
options.wal_segment_bytes,
limits::MIN_WAL_SEGMENT_BYTES,
limits::MAX_WAL_SEGMENT_BYTES,
)?;
check_range(
"db.background_threads",
u64::from(options.background_threads),
1,
u64::from(limits::MAX_BACKGROUND_THREADS),
)?;
check_range(
"db.delayed_write_bytes_per_second",
options.delayed_write_bytes_per_second,
limits::MIN_DELAYED_WRITE_BYTES_PER_SECOND,
limits::MAX_DELAYED_WRITE_BYTES_PER_SECOND,
)?;
if options.compaction_bytes_per_second != 0 {
check_range(
"db.compaction_bytes_per_second",
options.compaction_bytes_per_second,
limits::MIN_COMPACTION_BYTES_PER_SECOND,
limits::MAX_COMPACTION_BYTES_PER_SECOND,
)?;
}
super::memory::check(&options)?;
super::manifest::check(&options)?;
super::keyspaces::check(&options)?;
Ok(options)
}
}