armdb 0.1.13

sharded bitcask key-value storage optimized for NVMe
Documentation
use std::sync::Arc;

use quick_cache::Weighter;
use quick_cache::sync::Cache;

use crate::config::CacheConfig;
use crate::io::aligned_buf::AlignedBuf;

/// Cache key: identifies a 4096-byte aligned block on disk.
/// Includes `shard_id` because file_ids are assigned independently per shard
/// (each shard starts at file_id=1), so (file_id, block_offset) alone is ambiguous.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct BlockKey {
    pub shard_id: u8,
    pub file_id: u32,
    pub block_offset: u64,
}

#[derive(Clone)]
struct BlockWeighter;

impl Weighter<BlockKey, Arc<AlignedBuf>> for BlockWeighter {
    fn weight(&self, _key: &BlockKey, _value: &Arc<AlignedBuf>) -> u64 {
        4096
    }
}

/// Block cache for `VarTree`, backed by `quick_cache` with S3-FIFO eviction.
/// Caches 4096-byte aligned disk blocks — the natural unit of O_DIRECT reads.
pub struct BlockCache {
    inner: Option<Cache<BlockKey, Arc<AlignedBuf>, BlockWeighter>>,
}

impl BlockCache {
    pub fn new(config: &CacheConfig) -> Self {
        if config.max_size == 0 {
            return Self { inner: None };
        }
        let cache = Cache::with_weighter(config.estimated_items, config.max_size, BlockWeighter);
        Self { inner: Some(cache) }
    }

    pub fn get(&self, key: &BlockKey) -> Option<Arc<AlignedBuf>> {
        self.inner.as_ref()?.get(key)
    }

    pub fn insert(&self, key: BlockKey, block: Arc<AlignedBuf>) {
        if let Some(cache) = &self.inner {
            cache.insert(key, block);
        }
    }

    /// Invalidate all cached blocks for a file. Called after compaction
    /// replaces a file's contents (file_id reuse).
    pub fn invalidate_file(&self, shard_id: u8, file_id: u32, total_bytes: u64) {
        if let Some(cache) = &self.inner {
            let num_blocks = total_bytes.div_ceil(4096);
            for i in 0..num_blocks {
                cache.remove(&BlockKey {
                    shard_id,
                    file_id,
                    block_offset: i * 4096,
                });
            }
        }
    }
}