feoxdb/storage/
metadata.rs

1use crate::constants::*;
2use std::mem;
3
4/// Metadata version - increment this when changing the metadata structure
5/// Version 1: Initial format
6/// Version 2: Added TTL support (8 bytes ttl_expiry field in records)
7const METADATA_VERSION: u32 = 2;
8
9#[repr(C)]
10#[derive(Debug, Clone, Copy)]
11pub struct Metadata {
12    pub signature: [u8; FEOX_SIGNATURE_SIZE],
13    pub version: u32,
14    pub total_records: u64,
15    pub total_size: u64,
16    pub device_size: u64,
17    pub block_size: u32,
18    pub fragmentation: u32,
19    pub creation_time: u64,
20    pub last_update_time: u64,
21    reserved: [u8; 68],
22}
23
24impl Default for Metadata {
25    fn default() -> Self {
26        Self::new()
27    }
28}
29
30impl Metadata {
31    pub fn new() -> Self {
32        let now = std::time::SystemTime::now()
33            .duration_since(std::time::UNIX_EPOCH)
34            .unwrap_or_else(|_| std::time::Duration::from_secs(0))
35            .as_secs();
36
37        Self {
38            signature: *FEOX_SIGNATURE,
39            version: METADATA_VERSION,
40            total_records: 0,
41            total_size: 0,
42            device_size: 0,
43            block_size: FEOX_BLOCK_SIZE as u32,
44            fragmentation: 0,
45            creation_time: now,
46            last_update_time: now,
47            reserved: [0; 68],
48        }
49    }
50
51    pub fn validate(&self) -> bool {
52        if self.signature != *FEOX_SIGNATURE {
53            return false;
54        }
55
56        if self.block_size != FEOX_BLOCK_SIZE as u32 {
57            return false;
58        }
59
60        if self.device_size == 0 || self.device_size > MAX_DEVICE_SIZE {
61            return false;
62        }
63
64        // Skip checksum validation to avoid alignment issues
65        // The signature and other field checks are sufficient for basic validation
66        true
67    }
68
69    pub fn update(&mut self) {
70        self.last_update_time = std::time::SystemTime::now()
71            .duration_since(std::time::UNIX_EPOCH)
72            .unwrap_or_else(|_| std::time::Duration::from_secs(0))
73            .as_secs();
74    }
75
76    pub fn as_bytes(&self) -> &[u8] {
77        unsafe {
78            std::slice::from_raw_parts(self as *const Self as *const u8, mem::size_of::<Self>())
79        }
80    }
81
82    pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
83        if bytes.len() < mem::size_of::<Self>() {
84            return None;
85        }
86
87        let metadata = unsafe { std::ptr::read_unaligned(bytes.as_ptr() as *const Self) };
88
89        if metadata.validate() {
90            Some(metadata)
91        } else {
92            None
93        }
94    }
95}