Skip to main content

geographdb_core/storage/
data_structures.rs

1use bytemuck::{Pod, Zeroable};
2
3// A wrapper struct for spatial indexing, containing the node's ID and its 3D position.
4#[derive(Clone, Copy, Debug)]
5pub struct NodePoint {
6    pub id: u64,
7    pub x: f32,
8    pub y: f32,
9    pub z: f32,
10}
11
12impl PartialEq for NodePoint {
13    fn eq(&self, other: &Self) -> bool {
14        self.id == other.id
15    }
16}
17
18impl Eq for NodePoint {}
19
20impl PartialOrd for NodePoint {
21    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
22        Some(self.cmp(other))
23    }
24}
25
26impl Ord for NodePoint {
27    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
28        self.id.cmp(&other.id)
29    }
30}
31
32#[repr(C)]
33#[derive(Clone, Copy, Debug, Pod, Zeroable)]
34pub struct NodeRec {
35    pub id: u64,
36    pub morton_code: u64, // Changed back to u64 for alignment
37    pub x: f32,
38    pub y: f32,
39    pub z: f32,
40    pub edge_off: u32,
41    pub edge_len: u32,
42    pub flags: u32,
43    // MVCC fields for Tuple-MVCC
44    pub begin_ts: u64, // Transaction timestamp when this version was created
45    pub end_ts: u64,   // Transaction timestamp when this version was superseded (0 = current)
46    // Transaction tracking fields (Phase 1: WAL-MVCC Integration)
47    pub tx_id: u64, // Transaction ID that created this version (0 = system/bootstrap)
48    pub visibility: u8, // VERSION_UNCOMMITTED(0), VERSION_COMMITTED(1), VERSION_ABORTED(2)
49    pub _padding: [u8; 7], // Padding for 8-byte alignment (Pod trait requirement)
50}
51// Size: 72 bytes (was 56 bytes, increased by 16 bytes for transaction tracking)
52
53#[repr(C)]
54#[derive(Clone, Copy, Debug, Pod, Zeroable)]
55pub struct EdgeRec {
56    pub src: u64, // Source node index
57    pub dst: u64,
58    pub w: f32, // Semantic weight
59    pub flags: u32,
60    // MVCC fields for Tuple-MVCC
61    pub begin_ts: u64, // Transaction timestamp when this version was created
62    pub end_ts: u64,   // Transaction timestamp when this version was superseded (0 = current)
63    // Transaction tracking fields (Phase 1: WAL-MVCC Integration)
64    pub tx_id: u64, // Transaction ID that created this version (0 = system/bootstrap)
65    pub visibility: u8, // VERSION_UNCOMMITTED(0), VERSION_COMMITTED(1), VERSION_ABORTED(2)
66    pub _padding: [u8; 7], // Padding for 8-byte alignment (Pod trait requirement)
67}
68// Size: 48 bytes (was 32 bytes, increased by 16 bytes for transaction tracking)
69
70pub const WAL_ENTRY_NODE_CREATE: u8 = 1;
71pub const WAL_ENTRY_EDGE_CREATE: u8 = 2;
72pub const WAL_ENTRY_NODE_DELETE: u8 = 3;
73pub const WAL_ENTRY_EDGE_DELETE: u8 = 4;
74pub const WAL_ENTRY_PROPERTY_UPDATE: u8 = 5;
75pub const WAL_ENTRY_BEGIN_TX: u8 = 6;
76pub const WAL_ENTRY_COMMIT_TX: u8 = 7;
77pub const WAL_ENTRY_ABORT_TX: u8 = 8;
78
79pub const NODE_FLAG_TOMBSTONE: u32 = 0x1;
80pub const EDGE_FLAG_TOMBSTONE: u32 = 0x1;
81
82// Version visibility states for transaction tracking
83pub const VERSION_UNCOMMITTED: u8 = 0; // Created by active transaction, invisible to others
84pub const VERSION_COMMITTED: u8 = 1; // Committed, visible to snapshots >= commit_ts
85pub const VERSION_ABORTED: u8 = 2; // Rolled back, should be GC'd
86
87/// Fixed-size record for CFG block metadata (176 bytes for string storage)
88/// Stores terminator type and location info for each block
89#[repr(C)]
90#[derive(Clone, Copy, Debug, Pod, Zeroable)]
91pub struct MetadataRec {
92    /// Null-terminated string for block kind (max 31 bytes + null)
93    pub block_kind: [u8; 32],
94    /// Null-terminated string for terminator type (max 63 bytes + null)
95    pub terminator: [u8; 64],
96    pub byte_start: u64,
97    pub byte_end: u64,
98    pub start_line: u64,
99    pub start_col: u64,
100    pub end_line: u64,
101    pub end_col: u64,
102    pub _padding: [u8; 32],
103}
104
105impl MetadataRec {
106    pub const SIZE: usize = 176; // 32 + 64 + 6*8 + 32 = 176 bytes
107
108    /// Create from string values
109    #[rustfmt::skip]
110    #[allow(clippy::too_many_arguments, reason = "constructor maps all MetadataRec fields directly from CFG block metadata")]
111    pub fn from_strings(
112        block_kind: &str,
113        terminator: &str,
114        byte_start: u64,
115        byte_end: u64,
116        start_line: u64,
117        start_col: u64,
118        end_line: u64,
119        end_col: u64,
120    ) -> Self {
121        let mut rec = Self {
122            block_kind: [0u8; 32],
123            terminator: [0u8; 64],
124            byte_start,
125            byte_end,
126            start_line,
127            start_col,
128            end_line,
129            end_col,
130            _padding: [0u8; 32],
131        };
132
133        // Copy block_kind (truncate if needed) - already zero-initialized
134        let kind_bytes = block_kind.as_bytes();
135        let len = kind_bytes.len().min(31);
136        if len > 0 {
137            rec.block_kind[..len].copy_from_slice(&kind_bytes[..len]);
138        }
139        // block_kind[len..] is already 0 from initialization
140
141        // Copy terminator (truncate if needed) - already zero-initialized
142        let term_bytes = terminator.as_bytes();
143        let len = term_bytes.len().min(63);
144        if len > 0 {
145            rec.terminator[..len].copy_from_slice(&term_bytes[..len]);
146        }
147        // terminator[len..] is already 0 from initialization
148
149        rec
150    }
151
152    /// Get block kind as string
153    pub fn get_block_kind(&self) -> String {
154        let null_pos = self.block_kind.iter().position(|&b| b == 0).unwrap_or(32);
155        String::from_utf8_lossy(&self.block_kind[..null_pos]).to_string()
156    }
157
158    /// Get terminator as string
159    pub fn get_terminator(&self) -> String {
160        let null_pos = self.terminator.iter().position(|&b| b == 0).unwrap_or(64);
161        String::from_utf8_lossy(&self.terminator[..null_pos]).to_string()
162    }
163}
164
165impl Default for MetadataRec {
166    fn default() -> Self {
167        Self {
168            block_kind: [0u8; 32],
169            terminator: [0u8; 64],
170            byte_start: 0,
171            byte_end: 0,
172            start_line: 0,
173            start_col: 0,
174            end_line: 0,
175            end_col: 0,
176            _padding: [0u8; 32],
177        }
178    }
179}
180
181#[repr(C)]
182#[derive(Clone, Copy, Debug, Pod, Zeroable)]
183pub struct WalEntry {
184    pub timestamp: u64,    // 8 bytes - Epoch when entry was created
185    pub node_id: u64,      // 8 bytes - Node ID for node operations
186    pub edge_dst: u64,     // 8 bytes - Edge destination for edge operations
187    pub x: f32,            // 4 bytes - X coordinate
188    pub y: f32,            // 4 bytes - Y coordinate
189    pub z: f32,            // 4 bytes - Z coordinate
190    pub edge_w: f32,       // 4 bytes - Edge weight
191    pub entry_type: u8,    // 1 byte - Entry type (NODE_CREATE, BEGIN_TX, etc.)
192    pub _padding: [u8; 7], // 7 bytes - Padding for alignment
193    pub tx_id: u64,        // 8 bytes - Transaction ID (0 = auto-commit)
194    pub lsn: u64,          // 8 bytes - Log Sequence Number
195}