1use std::collections::{BTreeMap, BTreeSet, HashMap};
2
3use crate::types::{CommittedVersion, Intent, Key, Timestamp, TxnId, Value};
4
5pub trait Backend {
10 fn get_committed_versions(&self, key: &[u8]) -> Result<Vec<CommittedVersion>, String>;
12 fn get_latest_committed(&self, key: &[u8]) -> Result<Option<CommittedVersion>, String>;
14 fn get_visible_committed(
16 &self,
17 key: &[u8],
18 read_ts: Timestamp,
19 ) -> Result<Option<CommittedVersion>, String>;
20 fn get_latest_commit_ts(&self, key: &[u8]) -> Result<Option<Timestamp>, String>;
22 fn get_intent(&self, _key: &[u8]) -> Result<Option<Intent>, String> {
24 Ok(None)
25 }
26 fn put_intent(&mut self, _intent: Intent) -> Result<(), String> {
28 Err("intent transactions are not supported by this backend".to_string())
29 }
30 fn remove_intent(
33 &mut self,
34 _key: &[u8],
35 _txn_id: TxnId,
36 _start_ts: Timestamp,
37 ) -> Result<bool, String> {
38 Ok(false)
39 }
40 fn put_committed(&mut self, version: CommittedVersion) -> Result<(), String>;
42 fn put_committed_batch(&mut self, versions: Vec<CommittedVersion>) -> Result<(), String>;
44 fn remove_committed_version(&mut self, key: &[u8], commit_ts: Timestamp) -> Result<(), String>;
46 fn all_keys(&self) -> Result<Vec<Key>, String>;
48 fn put_intents_batch(&mut self, intents: Vec<Intent>) -> Result<(), String> {
50 if intents.is_empty() {
51 Ok(())
52 } else {
53 Err("intent transactions are not supported by this backend".to_string())
54 }
55 }
56 fn commit_intents_batch(
59 &mut self,
60 _commits: Vec<CommittedVersion>,
61 _removed_intents: Vec<(Key, TxnId, Timestamp)>,
62 ) -> Result<(), String> {
63 Err("intent transactions are not supported by this backend".to_string())
64 }
65 fn remove_intents_batch(
67 &mut self,
68 intents: Vec<(Key, TxnId, Timestamp)>,
69 ) -> Result<(), String> {
70 if intents.is_empty() {
71 Ok(())
72 } else {
73 Err("intent transactions are not supported by this backend".to_string())
74 }
75 }
76 fn keys_from(&self, start: Option<&[u8]>, limit: usize) -> Result<Vec<Key>, String>;
78 fn keys_from_prefix(
81 &self,
82 prefix: &[u8],
83 start: Option<&[u8]>,
84 limit: usize,
85 ) -> Result<Vec<Key>, String>;
86 fn get_committed_timestamps_before(
89 &self,
90 key: &[u8],
91 before_ts: Timestamp,
92 limit: usize,
93 ) -> Result<Vec<Timestamp>, String>;
94 fn collapse_tombstone(
97 &mut self,
98 key: &[u8],
99 tombstone_ts: Timestamp,
100 older_ts: Vec<Timestamp>,
101 ) -> Result<(), String>;
102}
103
104#[derive(Debug, Clone, Default)]
107pub struct InMemoryBackend {
108 committed: BTreeMap<(Key, Timestamp), Option<Value>>,
109 intents: HashMap<Key, Intent>,
110 all_keys_set: BTreeSet<Key>,
111}
112
113impl InMemoryBackend {
114 pub fn new() -> Self {
116 Self::default()
117 }
118}
119
120impl Backend for InMemoryBackend {
121 fn get_committed_versions(&self, key: &[u8]) -> Result<Vec<CommittedVersion>, String> {
122 let mut result = Vec::new();
123 let start = (key.to_vec(), Timestamp(0));
124 for ((k, ts), value) in self.committed.range(start..) {
125 if k.as_slice() != key {
126 break;
127 }
128 result.push(CommittedVersion {
129 key: k.clone(),
130 commit_ts: *ts,
131 value: value.clone(),
132 });
133 }
134 Ok(result)
135 }
136
137 fn get_latest_committed(&self, key: &[u8]) -> Result<Option<CommittedVersion>, String> {
138 let range = (key.to_vec(), Timestamp(0))..=(key.to_vec(), Timestamp(u128::MAX));
139 if let Some(((k, ts), value)) = self.committed.range(range).next_back()
140 && k.as_slice() == key
141 {
142 return Ok(Some(CommittedVersion {
143 key: k.clone(),
144 commit_ts: *ts,
145 value: value.clone(),
146 }));
147 }
148 Ok(None)
149 }
150
151 fn get_visible_committed(
152 &self,
153 key: &[u8],
154 read_ts: Timestamp,
155 ) -> Result<Option<CommittedVersion>, String> {
156 let range = (key.to_vec(), Timestamp(0))..=(key.to_vec(), read_ts);
157 if let Some(((k, ts), value)) = self.committed.range(range).next_back()
158 && k.as_slice() == key
159 {
160 return Ok(Some(CommittedVersion {
161 key: k.clone(),
162 commit_ts: *ts,
163 value: value.clone(),
164 }));
165 }
166 Ok(None)
167 }
168
169 fn get_latest_commit_ts(&self, key: &[u8]) -> Result<Option<Timestamp>, String> {
170 let range = (key.to_vec(), Timestamp(0))..=(key.to_vec(), Timestamp(u128::MAX));
171 if let Some(((k, ts), _)) = self.committed.range(range).next_back()
172 && k.as_slice() == key
173 {
174 return Ok(Some(*ts));
175 }
176 Ok(None)
177 }
178
179 fn get_intent(&self, key: &[u8]) -> Result<Option<Intent>, String> {
180 Ok(self.intents.get(key).cloned())
181 }
182
183 fn put_intent(&mut self, intent: Intent) -> Result<(), String> {
184 self.all_keys_set.insert(intent.key.clone());
185 self.intents.insert(intent.key.clone(), intent);
186 Ok(())
187 }
188
189 fn remove_intent(
190 &mut self,
191 key: &[u8],
192 txn_id: TxnId,
193 start_ts: Timestamp,
194 ) -> Result<bool, String> {
195 if let Some(intent) = self.intents.get(key)
196 && intent.txn_id == txn_id
197 && intent.start_ts == start_ts
198 {
199 self.intents.remove(key);
200 self.maybe_remove_from_keys(key);
201 return Ok(true);
202 }
203 Ok(false)
204 }
205
206 fn put_committed(&mut self, version: CommittedVersion) -> Result<(), String> {
207 self.all_keys_set.insert(version.key.clone());
208 self.committed.insert(
209 (version.key.clone(), version.commit_ts),
210 version.value.clone(),
211 );
212 Ok(())
213 }
214
215 fn put_committed_batch(&mut self, versions: Vec<CommittedVersion>) -> Result<(), String> {
216 for version in versions {
217 self.all_keys_set.insert(version.key.clone());
218 self.committed.insert(
219 (version.key.clone(), version.commit_ts),
220 version.value.clone(),
221 );
222 }
223 Ok(())
224 }
225
226 fn remove_committed_version(&mut self, key: &[u8], commit_ts: Timestamp) -> Result<(), String> {
227 self.committed.remove(&(key.to_vec(), commit_ts));
228 self.maybe_remove_from_keys(key);
229 Ok(())
230 }
231
232 fn all_keys(&self) -> Result<Vec<Key>, String> {
233 Ok(self.all_keys_set.iter().cloned().collect())
234 }
235
236 fn put_intents_batch(&mut self, intents: Vec<Intent>) -> Result<(), String> {
237 for intent in intents {
238 self.all_keys_set.insert(intent.key.clone());
239 self.intents.insert(intent.key.clone(), intent);
240 }
241 Ok(())
242 }
243
244 fn commit_intents_batch(
245 &mut self,
246 commits: Vec<CommittedVersion>,
247 removed_intents: Vec<(Key, TxnId, Timestamp)>,
248 ) -> Result<(), String> {
249 for version in commits {
250 self.all_keys_set.insert(version.key.clone());
251 self.committed.insert(
252 (version.key.clone(), version.commit_ts),
253 version.value.clone(),
254 );
255 }
256 for (key, txn_id, start_ts) in removed_intents {
257 if let Some(intent) = self.intents.get(&key)
258 && intent.txn_id == txn_id
259 && intent.start_ts == start_ts
260 {
261 self.intents.remove(&key);
262 self.maybe_remove_from_keys(&key);
263 }
264 }
265 Ok(())
266 }
267
268 fn remove_intents_batch(
269 &mut self,
270 intents: Vec<(Key, TxnId, Timestamp)>,
271 ) -> Result<(), String> {
272 for (key, txn_id, start_ts) in intents {
273 if let Some(intent) = self.intents.get(&key)
274 && intent.txn_id == txn_id
275 && intent.start_ts == start_ts
276 {
277 self.intents.remove(&key);
278 self.maybe_remove_from_keys(&key);
279 }
280 }
281 Ok(())
282 }
283
284 fn keys_from(&self, start: Option<&[u8]>, limit: usize) -> Result<Vec<Key>, String> {
285 if let Some(s) = start {
286 Ok(self
287 .all_keys_set
288 .range(s.to_vec()..)
289 .take(limit)
290 .cloned()
291 .collect())
292 } else {
293 Ok(self.all_keys_set.iter().take(limit).cloned().collect())
294 }
295 }
296
297 fn keys_from_prefix(
298 &self,
299 prefix: &[u8],
300 start: Option<&[u8]>,
301 limit: usize,
302 ) -> Result<Vec<Key>, String> {
303 if limit == 0 {
304 return Ok(Vec::new());
305 }
306 if prefix.is_empty() {
307 return Err("Prefix cannot be empty".to_string());
308 }
309 if let Some(s) = start
310 && !s.starts_with(prefix)
311 {
312 return Err("Start cursor must start with the prefix".to_string());
313 }
314 let scan_start = start.unwrap_or(prefix);
315 let mut result = Vec::new();
316 let range_start = (scan_start.to_vec(), Timestamp(0));
317 for ((k, _), _) in self.committed.range(range_start..) {
318 if !k.starts_with(prefix) {
319 break;
320 }
321 if result.last() != Some(k) {
322 result.push(k.clone());
323 if result.len() == limit {
324 break;
325 }
326 }
327 }
328 Ok(result)
329 }
330
331 fn get_committed_timestamps_before(
332 &self,
333 key: &[u8],
334 before_ts: Timestamp,
335 limit: usize,
336 ) -> Result<Vec<Timestamp>, String> {
337 let range = (key.to_vec(), Timestamp(0))..(key.to_vec(), before_ts);
338 let mut result = Vec::new();
339 for ((k, ts), _) in self.committed.range(range).rev().take(limit) {
340 if k.as_slice() == key {
341 result.push(*ts);
342 }
343 }
344 Ok(result)
345 }
346
347 fn collapse_tombstone(
348 &mut self,
349 key: &[u8],
350 tombstone_ts: Timestamp,
351 older_ts: Vec<Timestamp>,
352 ) -> Result<(), String> {
353 self.committed.remove(&(key.to_vec(), tombstone_ts));
354 for ts in older_ts {
355 self.committed.remove(&(key.to_vec(), ts));
356 }
357 self.maybe_remove_from_keys(key);
358 Ok(())
359 }
360}
361
362impl InMemoryBackend {
363 fn maybe_remove_from_keys(&mut self, key: &[u8]) {
364 if !self.intents.contains_key(key) {
365 let range = (key.to_vec(), Timestamp(0))..=(key.to_vec(), Timestamp(u128::MAX));
366 if self.committed.range(range).next().is_none() {
367 self.all_keys_set.remove(key);
368 }
369 }
370 }
371}