reddb_server/storage/primitives/
ids.rs1use std::fmt;
23use std::ops::{Add, AddAssign, Sub, SubAssign};
24use std::sync::atomic::{AtomicU64, Ordering};
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
36#[repr(transparent)]
37pub struct BTreeNodeId(pub u64);
38
39impl BTreeNodeId {
40 pub const fn new(id: u64) -> Self {
42 Self(id)
43 }
44
45 pub const fn get(self) -> u64 {
47 self.0
48 }
49}
50
51impl fmt::Display for BTreeNodeId {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "btree:{}", self.0)
54 }
55}
56
57impl From<u64> for BTreeNodeId {
58 fn from(id: u64) -> Self {
59 Self(id)
60 }
61}
62
63impl From<BTreeNodeId> for u64 {
64 fn from(id: BTreeNodeId) -> Self {
65 id.0
66 }
67}
68
69static BTREE_NODE_ID_COUNTER: AtomicU64 = AtomicU64::new(1);
71
72pub fn next_btree_node_id() -> BTreeNodeId {
74 BTreeNodeId(BTREE_NODE_ID_COUNTER.fetch_add(1, Ordering::SeqCst))
75}
76
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
87#[repr(transparent)]
88pub struct HnswNodeId(pub u64);
89
90impl HnswNodeId {
91 pub const fn new(id: u64) -> Self {
93 Self(id)
94 }
95
96 pub const fn get(self) -> u64 {
98 self.0
99 }
100}
101
102impl fmt::Display for HnswNodeId {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 write!(f, "hnsw:{}", self.0)
105 }
106}
107
108impl From<u64> for HnswNodeId {
109 fn from(id: u64) -> Self {
110 Self(id)
111 }
112}
113
114impl From<HnswNodeId> for u64 {
115 fn from(id: HnswNodeId) -> Self {
116 id.0
117 }
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
131#[repr(transparent)]
132pub struct TxnId(pub u64);
133
134impl TxnId {
135 pub const fn new(id: u64) -> Self {
137 Self(id)
138 }
139
140 pub const ZERO: TxnId = TxnId(0);
142
143 pub const fn get(self) -> u64 {
145 self.0
146 }
147
148 pub const fn is_zero(self) -> bool {
150 self.0 == 0
151 }
152}
153
154impl fmt::Display for TxnId {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 write!(f, "txn:{}", self.0)
157 }
158}
159
160impl From<u64> for TxnId {
161 fn from(id: u64) -> Self {
162 Self(id)
163 }
164}
165
166impl From<TxnId> for u64 {
167 fn from(id: TxnId) -> Self {
168 id.0
169 }
170}
171
172impl Add<u64> for TxnId {
174 type Output = TxnId;
175 fn add(self, rhs: u64) -> TxnId {
176 TxnId(self.0 + rhs)
177 }
178}
179
180impl AddAssign<u64> for TxnId {
181 fn add_assign(&mut self, rhs: u64) {
182 self.0 += rhs;
183 }
184}
185
186impl Sub<u64> for TxnId {
187 type Output = TxnId;
188 fn sub(self, rhs: u64) -> TxnId {
189 TxnId(self.0 - rhs)
190 }
191}
192
193static TXN_ID_COUNTER: AtomicU64 = AtomicU64::new(1);
195
196pub fn next_txn_id() -> TxnId {
198 TxnId(TXN_ID_COUNTER.fetch_add(1, Ordering::SeqCst))
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
211#[repr(transparent)]
212pub struct VectorId(pub u64);
213
214impl VectorId {
215 pub const fn new(id: u64) -> Self {
217 Self(id)
218 }
219
220 pub const fn get(self) -> u64 {
222 self.0
223 }
224}
225
226impl fmt::Display for VectorId {
227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228 write!(f, "vec:{}", self.0)
229 }
230}
231
232impl From<u64> for VectorId {
233 fn from(id: u64) -> Self {
234 Self(id)
235 }
236}
237
238impl From<VectorId> for u64 {
239 fn from(id: VectorId) -> Self {
240 id.0
241 }
242}
243
244#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
255#[repr(transparent)]
256pub struct SegmentId(pub u64);
257
258impl SegmentId {
259 pub const fn new(id: u64) -> Self {
261 Self(id)
262 }
263
264 pub const fn get(self) -> u64 {
266 self.0
267 }
268}
269
270impl fmt::Display for SegmentId {
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 write!(f, "seg:{}", self.0)
273 }
274}
275
276impl From<u64> for SegmentId {
277 fn from(id: u64) -> Self {
278 Self(id)
279 }
280}
281
282impl From<SegmentId> for u64 {
283 fn from(id: SegmentId) -> Self {
284 id.0
285 }
286}
287
288#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
298#[repr(transparent)]
299pub struct PageId(pub u64);
300
301impl PageId {
302 pub const fn new(id: u64) -> Self {
304 Self(id)
305 }
306
307 pub const NULL: PageId = PageId(0);
309
310 pub const fn get(self) -> u64 {
312 self.0
313 }
314
315 pub const fn is_null(self) -> bool {
317 self.0 == 0
318 }
319}
320
321impl fmt::Display for PageId {
322 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
323 write!(f, "page:{}", self.0)
324 }
325}
326
327impl From<u64> for PageId {
328 fn from(id: u64) -> Self {
329 Self(id)
330 }
331}
332
333impl From<PageId> for u64 {
334 fn from(id: PageId) -> Self {
335 id.0
336 }
337}
338
339#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
348#[repr(transparent)]
349pub struct EntityId(pub u64);
350
351impl EntityId {
352 pub const fn new(id: u64) -> Self {
354 Self(id)
355 }
356
357 pub const fn get(self) -> u64 {
359 self.0
360 }
361}
362
363impl fmt::Display for EntityId {
364 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
365 write!(f, "entity:{}", self.0)
366 }
367}
368
369impl From<u64> for EntityId {
370 fn from(id: u64) -> Self {
371 Self(id)
372 }
373}
374
375impl From<EntityId> for u64 {
376 fn from(id: EntityId) -> Self {
377 id.0
378 }
379}
380
381#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
390#[repr(transparent)]
391pub struct Timestamp(pub u64);
392
393impl Timestamp {
394 pub const fn new(ts: u64) -> Self {
396 Self(ts)
397 }
398
399 pub const EPOCH: Timestamp = Timestamp(0);
401
402 pub const MAX: Timestamp = Timestamp(u64::MAX);
404
405 pub const fn get(self) -> u64 {
407 self.0
408 }
409
410 pub const fn is_epoch(self) -> bool {
412 self.0 == 0
413 }
414}
415
416impl fmt::Display for Timestamp {
417 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
418 write!(f, "ts:{}", self.0)
419 }
420}
421
422impl From<u64> for Timestamp {
423 fn from(ts: u64) -> Self {
424 Self(ts)
425 }
426}
427
428impl From<Timestamp> for u64 {
429 fn from(ts: Timestamp) -> Self {
430 ts.0
431 }
432}
433
434impl Add<u64> for Timestamp {
436 type Output = Timestamp;
437 fn add(self, rhs: u64) -> Timestamp {
438 Timestamp(self.0 + rhs)
439 }
440}
441
442impl Add<Timestamp> for Timestamp {
443 type Output = Timestamp;
444 fn add(self, rhs: Timestamp) -> Timestamp {
445 Timestamp(self.0 + rhs.0)
446 }
447}
448
449impl AddAssign<u64> for Timestamp {
450 fn add_assign(&mut self, rhs: u64) {
451 self.0 += rhs;
452 }
453}
454
455impl Sub<u64> for Timestamp {
456 type Output = Timestamp;
457 fn sub(self, rhs: u64) -> Timestamp {
458 Timestamp(self.0 - rhs)
459 }
460}
461
462impl Sub<Timestamp> for Timestamp {
463 type Output = Timestamp;
464 fn sub(self, rhs: Timestamp) -> Timestamp {
465 Timestamp(self.0 - rhs.0)
466 }
467}
468
469impl SubAssign<u64> for Timestamp {
470 fn sub_assign(&mut self, rhs: u64) {
471 self.0 -= rhs;
472 }
473}
474
475impl Timestamp {
476 pub const fn saturating_sub(self, rhs: Self) -> Self {
478 Timestamp(self.0.saturating_sub(rhs.0))
479 }
480
481 pub fn min(self, other: Self) -> Self {
483 Timestamp(self.0.min(other.0))
484 }
485
486 pub fn max(self, other: Self) -> Self {
488 Timestamp(self.0.max(other.0))
489 }
490}
491
492static GLOBAL_TIMESTAMP: AtomicU64 = AtomicU64::new(1);
494
495pub fn next_timestamp() -> Timestamp {
497 Timestamp(GLOBAL_TIMESTAMP.fetch_add(1, Ordering::SeqCst))
498}
499
500pub fn current_timestamp() -> Timestamp {
502 Timestamp(GLOBAL_TIMESTAMP.load(Ordering::SeqCst))
503}
504
505#[cfg(test)]
510mod tests {
511 use super::*;
512
513 #[test]
514 fn test_btree_node_id() {
515 let id1 = BTreeNodeId::new(42);
516 let id2 = BTreeNodeId::from(42u64);
517 assert_eq!(id1, id2);
518 assert_eq!(id1.get(), 42);
519 assert_eq!(format!("{}", id1), "btree:42");
520 }
521
522 #[test]
523 fn test_hnsw_node_id() {
524 let id = HnswNodeId::new(100);
525 assert_eq!(id.get(), 100);
526 assert_eq!(format!("{}", id), "hnsw:100");
527 }
528
529 #[test]
530 fn test_txn_id() {
531 assert!(TxnId::ZERO.is_zero());
532 let id = TxnId::new(5);
533 assert!(!id.is_zero());
534 assert_eq!(format!("{}", id), "txn:5");
535 }
536
537 #[test]
538 fn test_vector_id() {
539 let id = VectorId::new(999);
540 assert_eq!(id.get(), 999);
541 assert_eq!(u64::from(id), 999);
542 }
543
544 #[test]
545 fn test_page_id() {
546 assert!(PageId::NULL.is_null());
547 let id = PageId::new(1);
548 assert!(!id.is_null());
549 }
550
551 #[test]
552 fn test_timestamp() {
553 assert!(Timestamp::EPOCH.is_epoch());
554 let ts = Timestamp::new(100);
555 assert!(!ts.is_epoch());
556 assert!(ts < Timestamp::MAX);
557 }
558
559 #[test]
560 fn test_id_generation() {
561 let id1 = next_btree_node_id();
562 let id2 = next_btree_node_id();
563 assert!(id2.get() > id1.get());
564
565 let txn1 = next_txn_id();
566 let txn2 = next_txn_id();
567 assert!(txn2.get() > txn1.get());
568
569 let ts1 = next_timestamp();
570 let ts2 = next_timestamp();
571 assert!(ts2.get() > ts1.get());
572 }
573
574 #[test]
575 fn test_type_safety() {
576 let btree_id = BTreeNodeId::new(1);
579 let hnsw_id = HnswNodeId::new(1);
580 let txn_id = TxnId::new(1);
581
582 assert_eq!(btree_id.get(), hnsw_id.get());
584 assert_eq!(btree_id.get(), txn_id.get());
585
586 assert_ne!(format!("{}", btree_id), format!("{}", hnsw_id));
588 assert_ne!(format!("{}", btree_id), format!("{}", txn_id));
589 }
590}