bitcasky_database/
common.rs

1use bitcasky_common::formatter::FormatterError;
2use bitcasky_common::tombstone::is_tombstone;
3use bitcasky_common::{storage_id::StorageId, tombstone::TOMBSTONE_VALUE};
4use std::ops::Deref;
5use thiserror::Error;
6
7use crate::DataStorageError;
8
9#[derive(Debug, PartialEq, Eq, Clone, Copy)]
10pub struct RowLocation {
11    pub storage_id: StorageId,
12    pub row_offset: usize,
13}
14
15#[derive(Debug)]
16pub struct TimedValue<V: AsRef<[u8]>> {
17    pub value: V,
18    pub expire_timestamp: u64,
19}
20
21impl<V: AsRef<[u8]>> TimedValue<V> {
22    pub fn is_valid(&self, now: u64) -> bool {
23        if is_tombstone(self.value.as_ref()) {
24            return false;
25        }
26
27        self.expire_timestamp == 0 || self.expire_timestamp > now
28    }
29
30    pub fn validate(self) -> Option<TimedValue<V>> {
31        if !is_tombstone(self.value.as_ref()) {
32            Some(self)
33        } else {
34            None
35        }
36    }
37}
38
39impl<V: AsRef<[u8]>> Deref for TimedValue<V> {
40    type Target = [u8];
41
42    fn deref(&self) -> &Self::Target {
43        self.value.as_ref()
44    }
45}
46
47pub fn deleted_value() -> TimedValue<Vec<u8>> {
48    TimedValue::immortal_value(TOMBSTONE_VALUE.as_bytes().to_vec())
49}
50
51impl<V: AsRef<[u8]>> TimedValue<V> {
52    pub fn immortal_value(value: V) -> TimedValue<V> {
53        TimedValue {
54            value,
55            expire_timestamp: 0,
56        }
57    }
58
59    pub fn expirable_value(value: V, expire_timestamp: u64) -> TimedValue<V> {
60        TimedValue {
61            value,
62            expire_timestamp,
63        }
64    }
65}
66
67#[derive(Debug)]
68pub struct RowToRead {
69    pub key: Vec<u8>,
70    pub row_location: RowLocation,
71    pub value: TimedValue<Vec<u8>>,
72}
73
74pub struct RecoveredRow {
75    pub row_location: RowLocation,
76    pub key: Vec<u8>,
77    pub invalid: bool,
78}
79
80#[derive(Error, Debug)]
81pub enum DatabaseError {
82    #[error(transparent)]
83    IoError(#[from] std::io::Error),
84    #[error("Permission Denied: \"{0}\"")]
85    PermissionDenied(String),
86    #[error("Database is broken due to previos unrecoverable error: {0}.")]
87    DatabaseBroken(String),
88    #[error("Hint file with file id {1} under path {2} corrupted")]
89    HintFileCorrupted(#[source] FormatterError, u32, String),
90    #[error("Read non-existent file with id {0}")]
91    TargetFileIdNotFound(u32),
92    #[error(transparent)]
93    StorageError(#[from] DataStorageError),
94}
95
96pub type DatabaseResult<T> = Result<T, DatabaseError>;