/home/gh-runner/action-runner3/_work/feoxdb/feoxdb/src/storage/metadata.rs
Line | Count | Source |
1 | | use crate::constants::*; |
2 | | use 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) |
7 | | const METADATA_VERSION: u32 = 2; |
8 | | |
9 | | #[repr(C)] |
10 | | #[derive(Debug, Clone, Copy)] |
11 | | pub 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 | | |
24 | | impl Default for Metadata { |
25 | 0 | fn default() -> Self { |
26 | 0 | Self::new() |
27 | 0 | } |
28 | | } |
29 | | |
30 | | impl Metadata { |
31 | 85 | pub fn new() -> Self { |
32 | 85 | let now = std::time::SystemTime::now() |
33 | 85 | .duration_since(std::time::UNIX_EPOCH) |
34 | 85 | .unwrap_or_else(|_| std::time::Duration::from_secs0 (0)) |
35 | 85 | .as_secs(); |
36 | | |
37 | 85 | Self { |
38 | 85 | signature: *FEOX_SIGNATURE, |
39 | 85 | version: METADATA_VERSION, |
40 | 85 | total_records: 0, |
41 | 85 | total_size: 0, |
42 | 85 | device_size: 0, |
43 | 85 | block_size: FEOX_BLOCK_SIZE as u32, |
44 | 85 | fragmentation: 0, |
45 | 85 | creation_time: now, |
46 | 85 | last_update_time: now, |
47 | 85 | reserved: [0; 68], |
48 | 85 | } |
49 | 85 | } |
50 | | |
51 | 19 | pub fn validate(&self) -> bool { |
52 | 19 | if self.signature != *FEOX_SIGNATURE { |
53 | 1 | return false; |
54 | 18 | } |
55 | | |
56 | 18 | if self.block_size != FEOX_BLOCK_SIZE as u32 { |
57 | 0 | return false; |
58 | 18 | } |
59 | | |
60 | 18 | if self.device_size == 0 || self.device_size > MAX_DEVICE_SIZE { |
61 | 0 | return false; |
62 | 18 | } |
63 | | |
64 | | // Skip checksum validation to avoid alignment issues |
65 | | // The signature and other field checks are sufficient for basic validation |
66 | 18 | true |
67 | 19 | } |
68 | | |
69 | 40 | pub fn update(&mut self) { |
70 | 40 | self.last_update_time = std::time::SystemTime::now() |
71 | 40 | .duration_since(std::time::UNIX_EPOCH) |
72 | 40 | .unwrap_or_else(|_| std::time::Duration::from_secs0 (0)) |
73 | 40 | .as_secs(); |
74 | 40 | } |
75 | | |
76 | 30 | pub fn as_bytes(&self) -> &[u8] { |
77 | | unsafe { |
78 | 30 | std::slice::from_raw_parts(self as *const Self as *const u8, mem::size_of::<Self>()) |
79 | | } |
80 | 30 | } |
81 | | |
82 | 20 | pub fn from_bytes(bytes: &[u8]) -> Option<Self> { |
83 | 20 | if bytes.len() < mem::size_of::<Self>() { |
84 | 1 | return None; |
85 | 19 | } |
86 | | |
87 | 19 | let metadata = unsafe { std::ptr::read_unaligned(bytes.as_ptr() as *const Self) }; |
88 | | |
89 | 19 | if metadata.validate() { |
90 | 18 | Some(metadata) |
91 | | } else { |
92 | 1 | None |
93 | | } |
94 | 20 | } |
95 | | } |