use serde::{Deserialize, Serialize};
pub const DEFAULT_BLOCK_SIZE_BYTES: usize = 128;
pub const DEFAULT_PAGE_SIZE_BYTES: usize = 32 * 1024 * 1024;
pub const DEFAULT_REGION_SIZE_BLOCKS: usize = 8_192;
pub const DEFAULT_USE_COMPRESSION: bool = true;
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Default)]
pub enum Compression {
None,
#[default]
LZ4,
}
#[derive(Debug, Default)]
pub struct StorageOptions {
pub page_size_bytes: Option<usize>,
pub block_size_bytes: Option<usize>,
pub region_size_blocks: Option<u16>,
pub compression: Option<Compression>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct StorageConfig {
pub page_size_bytes: usize,
pub block_size_bytes: usize,
pub region_size_blocks: usize,
#[serde(default)]
pub compression: Compression,
}
impl TryFrom<StorageOptions> for StorageConfig {
type Error = &'static str;
fn try_from(options: StorageOptions) -> Result<Self, Self::Error> {
let page_size_bytes = options.page_size_bytes.unwrap_or(DEFAULT_PAGE_SIZE_BYTES);
let block_size_bytes = options.block_size_bytes.unwrap_or(DEFAULT_BLOCK_SIZE_BYTES);
let region_size_blocks = options
.region_size_blocks
.map(|x| x as usize)
.unwrap_or(DEFAULT_REGION_SIZE_BLOCKS);
if block_size_bytes == 0 {
return Err("Block size must be greater than 0");
}
if region_size_blocks == 0 {
return Err("Region size must be greater than 0");
}
if page_size_bytes == 0 {
return Err("Page size must be greater than 0");
}
let region_size_bytes = block_size_bytes * region_size_blocks;
if page_size_bytes < region_size_bytes {
return Err("Page size must be greater than or equal to (block size * region size)");
}
if !page_size_bytes.is_multiple_of(region_size_bytes) {
return Err("Page size must be a multiple of (block size * region size)");
}
Ok(Self {
page_size_bytes,
block_size_bytes,
region_size_blocks,
compression: options.compression.unwrap_or_default(),
})
}
}
impl From<&StorageConfig> for StorageOptions {
fn from(config: &StorageConfig) -> Self {
Self {
page_size_bytes: Some(config.page_size_bytes),
block_size_bytes: Some(config.block_size_bytes),
region_size_blocks: Some(config.region_size_blocks as u16),
compression: Some(config.compression),
}
}
}