trine-kv 0.5.13

Embedded LSM MVCC key-value database.
Documentation
use std::{
    collections::{BTreeMap, BTreeSet, btree_map::Entry},
    path::{Path, PathBuf},
    sync::Arc,
};

use crate::{
    codec::{self, CodecId},
    error::{Error, Result},
    internal_key::{InternalKey, ValueKind},
    limits,
    options::DurabilityMode,
    storage::{
        BlockingStorageObjectListBackend, BlockingStorageObjectWriteBackend,
        BlockingStorageReadBackend, BlockingStorageReadObject, NativeFileBackend, NativeFileObject,
        StorageCapability, StorageObjectId, StorageObjectKind, StorageObjectListBackend,
        StorageObjectListRequest, StorageObjectWriteBackend, StorageReadBackend, StorageReadObject,
    },
    types::Sequence,
};
use bytes::Bytes;

pub const BLOB_FILE_EXTENSION: &str = "trineb";
pub const BLOB_FILE_FORMAT_VERSION: u16 = 3;

const BLOB_MAGIC: u32 = 0x5452_424c;
const BLOB_FOOTER_MAGIC: u32 = 0x5452_4246;
const BLOB_HEADER_WITHOUT_CHECKSUM_LEN: usize = 39;
const BLOB_HEADER_LEN: usize = BLOB_HEADER_WITHOUT_CHECKSUM_LEN + 4;
const BLOB_FOOTER_LEN: usize = 24;
const MIN_BLOB_RECORD_FRAME_BYTES: usize = 12;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BlobIndex {
    pub file_id: u64,
    pub offset: u64,
    pub encoded_len: u64,
    pub value_len: u64,
    pub value_checksum: u32,
    pub record_checksum: u32,
    pub compression: CodecId,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BlobFileHeader {
    pub file_id: u64,
    pub creation_sequence: Sequence,
    pub bucket_options_digest: u64,
    pub blob_threshold_bytes: u64,
    pub default_compression: CodecId,
}

impl BlobFileHeader {
    #[must_use]
    pub const fn new(
        file_id: u64,
        creation_sequence: Sequence,
        blob_threshold_bytes: u64,
        default_compression: CodecId,
    ) -> Self {
        Self {
            file_id,
            creation_sequence,
            bucket_options_digest: 0,
            blob_threshold_bytes,
            default_compression,
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BlobRecord {
    pub internal_key: InternalKey,
    pub value: Vec<u8>,
    pub compression: CodecId,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BlobFileRecord {
    pub index: BlobIndex,
    pub record: BlobRecord,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BlobFileProperties {
    pub record_count: u64,
    pub value_bytes: u64,
    pub encoded_bytes: u64,
    pub compression_saved_bytes: u64,
    pub smallest_internal_key: InternalKey,
    pub largest_internal_key: InternalKey,
    pub smallest_sequence: Sequence,
    pub largest_sequence: Sequence,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BlobFile {
    pub header: BlobFileHeader,
    pub properties: BlobFileProperties,
    pub records: Vec<BlobFileRecord>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValueRef {
    Inline(Vec<u8>),
    BlobIndex(BlobIndex),
    Blob {
        file_id: u64,
        offset: u64,
        len: u64,
        checksum: u32,
    },
}

impl ValueRef {
    #[must_use]
    pub fn len(&self) -> u64 {
        match self {
            Self::Inline(bytes) => bytes.len() as u64,
            Self::BlobIndex(index) => index.value_len,
            Self::Blob { len, .. } => *len,
        }
    }
}

#[must_use]
pub fn blob_path(db_path: &Path, file_id: u64) -> PathBuf {
    db_path.join(format!("blob-{file_id:020}.{BLOB_FILE_EXTENSION}",))
}

#[path = "blob/codec.rs"]
mod file_format;
mod io;
#[allow(dead_code)]
mod listing;
mod values;

pub(crate) use file_format::*;
pub(crate) use io::*;
pub(crate) use listing::*;
pub(crate) use values::*;
#[cfg(test)]
mod tests;