reifydb_core/util/
multi.rs1use std::{fmt::Debug, sync::Arc};
5
6use crossbeam_skiplist::SkipMap;
7use reifydb_runtime::sync::rwlock::RwLock;
8
9use crate::common::CommitVersion;
10
11#[derive(Debug)]
12pub struct MultiVersionContainer<T: Debug + Clone + Send + Sync + 'static> {
13 inner: Arc<RwLock<MultiVersionDefInner<T>>>,
14}
15
16#[derive(Debug)]
17struct MultiVersionDefInner<T: Debug + Clone + Send + Sync + 'static> {
18 versions: SkipMap<CommitVersion, Option<T>>,
19}
20
21impl<T: Debug + Clone + Send + Sync + 'static> MultiVersionContainer<T> {
22 pub fn new() -> Self {
23 Self {
24 inner: Arc::new(RwLock::new(MultiVersionDefInner {
25 versions: SkipMap::new(),
26 })),
27 }
28 }
29
30 pub fn insert(&self, version: impl Into<CommitVersion>, value: T) -> Option<Option<T>> {
31 let version = version.into();
32 let inner = self.inner.write();
33 if let Some(entry) = inner.versions.get(&version) {
34 let old_value = entry.value().clone();
35 inner.versions.insert(version, Some(value));
36 Some(old_value)
37 } else {
38 inner.versions.insert(version, Some(value));
39 None
40 }
41 }
42
43 pub fn get(&self, version: impl Into<CommitVersion>) -> Option<T> {
44 let version = version.into();
45 let inner = self.inner.read();
46
47 inner.versions.range(..=version).next_back().and_then(|entry| entry.value().clone())
48 }
49
50 pub fn get_latest(&self) -> Option<T> {
51 let inner = self.inner.read();
52 inner.versions.back().and_then(|entry| entry.value().clone())
53 }
54
55 pub fn versions(&self) -> Vec<CommitVersion> {
56 let inner = self.inner.read();
57 inner.versions.iter().map(|entry| *entry.key()).collect()
58 }
59
60 pub fn remove(&self, version: impl Into<CommitVersion>) -> Option<Option<T>> {
61 let version = version.into();
62 let inner = self.inner.write();
63
64 if let Some(entry) = inner.versions.get(&version) {
65 let old_value = entry.value().clone();
66 inner.versions.insert(version, None);
67 Some(old_value)
68 } else {
69 inner.versions.insert(version, None);
70 None
71 }
72 }
73
74 pub fn len(&self) -> usize {
75 let inner = self.inner.read();
76 inner.versions.len()
77 }
78
79 pub fn is_empty(&self) -> bool {
80 let inner = self.inner.read();
81 inner.versions.is_empty()
82 }
83
84 pub fn clear(&self) {
85 let inner = self.inner.write();
86 inner.versions.clear();
87 }
88}
89
90impl<T: Debug + Clone + Send + Sync + 'static> Clone for MultiVersionContainer<T> {
91 fn clone(&self) -> Self {
92 Self {
93 inner: Arc::clone(&self.inner),
94 }
95 }
96}
97
98impl<T: Debug + Clone + Send + Sync + 'static> Default for MultiVersionContainer<T> {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104#[cfg(test)]
105pub mod tests {
106 use super::*;
107
108 #[derive(Debug, Clone, PartialEq)]
109 struct Test {
110 name: String,
111 }
112
113 #[test]
114 fn test_basic_operations() {
115 let multi = MultiVersionContainer::<Test>::new();
116
117 assert!(multi.is_empty());
118 assert_eq!(multi.len(), 0);
119 assert!(multi.get_latest().is_none());
120
121 let def1 = Test {
122 name: "v1".to_string(),
123 };
124 multi.insert(1, def1.clone());
125 assert!(!multi.is_empty());
126 assert_eq!(multi.len(), 1);
127
128 assert_eq!(multi.get(1), Some(def1.clone()));
130 assert_eq!(multi.get(2), Some(def1.clone()));
131 assert_eq!(multi.get_latest(), Some(def1.clone()));
132
133 let def2 = Test {
134 name: "v2".to_string(),
135 };
136 multi.insert(5, def2.clone());
137 assert_eq!(multi.len(), 2);
138 assert_eq!(multi.get(1), Some(def1.clone()));
139 assert_eq!(multi.get(3), Some(def1.clone()));
140 assert_eq!(multi.get(5), Some(def2.clone()));
141 assert_eq!(multi.get(10), Some(def2.clone()));
142 assert_eq!(multi.get_latest(), Some(def2.clone()));
143
144 multi.remove(7);
145 assert_eq!(multi.get(7), None);
146 assert_eq!(multi.get(10), None);
147
148 assert_eq!(multi.get_latest(), None);
149 }
150}