block-db 0.2.0

Local, multi-threaded, durable byte DB.
Documentation
// Authors: Robert Lopez

use super::{state::ChunkCount, TestDB};
use crate::{BlockKey, size::ByteSize, tests::util::size_bytes};

impl TestDB {
    pub async fn write(
        &mut self,
        bytes: &[u8],
        creates_data_file: bool,
    ) -> Result<BlockKey, String> {
        let block_key = self
            .block_db
            .write(bytes)
            .await
            .map_err(|err| format!("Failed to write bytes \n {err:?}"))?;
        let bytes_size = size_bytes(bytes, self.chunk_size);

        let data_file_id = &block_key.data_file_id;

        if creates_data_file {
            self.test_state.data_file_count += 1;
        }

        let ByteSize {
            used_bytes: block_db_used_bytes,
            free_bytes: block_db_free_bytes,
        } = &mut self.test_state.block_db_byte_size;

        let ByteSize {
            used_bytes: data_file_used_bytes,
            free_bytes: data_file_free_bytes,
        } = self
            .test_state
            .data_file_byte_size_map
            .entry(data_file_id.to_string())
            .or_default();

        let ChunkCount { used, free } = self
            .test_state
            .data_file_chunk_count_map
            .entry(data_file_id.to_string())
            .or_default();

        let introduced_chunks = bytes_size / self.chunk_size;
        let previous_free_chunks = *free;

        let new_free_chunks =
            (previous_free_chunks as i64 - introduced_chunks as i64).max(0) as usize;

        let used_free_chunks = previous_free_chunks - new_free_chunks;
        let used_free_bytes = used_free_chunks * self.chunk_size;

        let new_introduced_chunks = introduced_chunks - used_free_chunks;
        let new_introduced_bytes = new_introduced_chunks * self.chunk_size;

        *free = new_free_chunks;
        *used += new_introduced_chunks + used_free_chunks;

        *block_db_used_bytes += new_introduced_bytes + used_free_bytes;
        *block_db_free_bytes -= used_free_bytes;

        *data_file_used_bytes += new_introduced_bytes + used_free_bytes;
        *data_file_free_bytes -= used_free_bytes;

        self.test_state
            .assert_against_block_db(&self.block_db)
            .await?;

        self.read(&block_key, Some(bytes)).await?;

        Ok(block_key)
    }
}