1use std::collections::{BTreeMap, BTreeSet};
17use std::ops::Bound;
18use std::sync::Arc;
19
20use crate::{Op, ReadCancellation, ReadView, ScanBounds, ScanProjection, StorageError};
21
22fn op_entry(op: &Op) -> (&[u8], Option<&[u8]>) {
23 match op {
24 Op::Put(key, value) | Op::Set(key, value) => (key, Some(value)),
25 Op::Del(key) | Op::Purge(key) => (key, None),
26 }
27}
28
29pub(crate) struct CommitLayer {
33 ci: u64,
34 ops: Arc<Vec<Op>>,
35 order: Vec<usize>,
37}
38
39impl CommitLayer {
40 pub(crate) fn new(ci: u64, ops: Arc<Vec<Op>>) -> Self {
41 let mut order: Vec<usize> = (0..ops.len()).collect();
42 order.sort_unstable_by(|a, b| {
45 op_entry(&ops[*a])
46 .0
47 .cmp(op_entry(&ops[*b]).0)
48 .then(b.cmp(a))
49 });
50 order.dedup_by(|later, kept| op_entry(&ops[*later]).0 == op_entry(&ops[*kept]).0);
51 Self { ci, ops, order }
52 }
53
54 pub(crate) fn ci(&self) -> u64 {
55 self.ci
56 }
57
58 #[cfg(test)]
60 pub(crate) fn ops(&self) -> &Arc<Vec<Op>> {
61 &self.ops
62 }
63
64 pub(crate) fn len(&self) -> usize {
66 self.order.len()
67 }
68
69 fn entry(&self, at: usize) -> (&[u8], Option<&[u8]>) {
70 op_entry(&self.ops[self.order[at]])
71 }
72
73 #[expect(
76 clippy::option_option,
77 reason = "not written by this layer and written as a tombstone are different answers"
78 )]
79 pub(crate) fn get(&self, key: &[u8]) -> Option<Option<&[u8]>> {
80 self.order
81 .binary_search_by(|at| op_entry(&self.ops[*at]).0.cmp(key))
82 .ok()
83 .map(|at| op_entry(&self.ops[self.order[at]]).1)
84 }
85
86 pub(crate) fn keys(&self) -> impl Iterator<Item = &[u8]> {
88 (0..self.order.len()).map(|at| self.entry(at).0)
89 }
90
91 fn range<'a>(
93 &'a self,
94 start: Bound<&[u8]>,
95 end: Bound<&[u8]>,
96 ) -> impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)> + 'a {
97 let key = |at: &usize| op_entry(&self.ops[*at]).0;
98 let from = match start {
99 Bound::Included(start) => self.order.partition_point(|at| key(at) < start),
100 Bound::Excluded(start) => self.order.partition_point(|at| key(at) <= start),
101 Bound::Unbounded => 0,
102 };
103 let to = match end {
104 Bound::Included(end) => self.order.partition_point(|at| key(at) <= end),
105 Bound::Excluded(end) => self.order.partition_point(|at| key(at) < end),
106 Bound::Unbounded => self.order.len(),
107 };
108 (from..to.max(from)).map(|at| self.entry(at))
109 }
110}
111
112#[derive(Clone)]
118pub struct OverlayView {
119 base: Arc<ReadView>,
120 layers: Vec<Arc<CommitLayer>>,
122 buffer: BTreeMap<Vec<u8>, Option<Vec<u8>>>,
123 derived: std::sync::OnceLock<Result<Arc<BTreeMap<Vec<u8>, Option<Vec<u8>>>>, StorageError>>,
127}
128
129impl std::fmt::Debug for OverlayView {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 f.debug_struct("OverlayView")
132 .field("commit_index", &self.base.commit_index())
133 .field("layers", &self.layers.len())
134 .field("overlay_keys", &self.buffer.len())
135 .finish_non_exhaustive()
136 }
137}
138
139impl OverlayView {
140 #[must_use]
142 pub fn new(base: Arc<ReadView>) -> Self {
143 Self::with_buffer(base, BTreeMap::new())
144 }
145
146 #[must_use]
148 pub fn with_buffer(base: Arc<ReadView>, buffer: BTreeMap<Vec<u8>, Option<Vec<u8>>>) -> Self {
149 Self {
150 base,
151 layers: Vec::new(),
152 buffer,
153 derived: std::sync::OnceLock::new(),
154 }
155 }
156
157 pub(crate) fn with_layers(base: Arc<ReadView>, layers: Vec<Arc<CommitLayer>>) -> Self {
159 Self {
160 layers,
161 ..Self::new(base)
162 }
163 }
164
165 fn has_staged(&self) -> bool {
166 !self.buffer.is_empty() || self.layers.iter().any(|layer| layer.len() > 0)
167 }
168
169 #[expect(
172 clippy::option_option,
173 reason = "not staged and staged as a tombstone are different answers"
174 )]
175 fn staged(&self, key: &[u8]) -> Option<Option<&[u8]>> {
176 if let Some(value) = self.buffer.get(key) {
177 return Some(value.as_deref());
178 }
179 self.layers.iter().rev().find_map(|layer| layer.get(key))
180 }
181
182 fn staged_range(
184 &self,
185 start: Bound<&[u8]>,
186 end: Bound<&[u8]>,
187 ) -> BTreeMap<&[u8], Option<&[u8]>> {
188 let mut merged = BTreeMap::new();
189 for layer in &self.layers {
190 merged.extend(layer.range(start, end));
191 }
192 merged.extend(
193 self.buffer
194 .range::<[u8], _>((start, end))
195 .map(|(key, value)| (key.as_slice(), value.as_deref())),
196 );
197 merged
198 }
199
200 pub(crate) fn staged_rows(
202 &self,
203 start: Bound<&[u8]>,
204 end: Bound<&[u8]>,
205 ) -> BTreeMap<Vec<u8>, Option<Vec<u8>>> {
206 self.staged_range(start, end)
207 .into_iter()
208 .map(|(key, value)| (key.to_vec(), value.map(<[u8]>::to_vec)))
209 .collect()
210 }
211
212 fn derived_rows(&self) -> Result<Arc<BTreeMap<Vec<u8>, Option<Vec<u8>>>>, StorageError> {
215 self.derived
216 .get_or_init(|| {
217 let mut rows = BTreeMap::new();
218 if let Some(deriver) = self.base.deriver() {
219 if self.has_staged() {
220 let ops: Vec<Op> = self
221 .staged_range(Bound::Unbounded, Bound::Unbounded)
222 .into_iter()
223 .map(|(key, value)| match value {
224 Some(value) => Op::Put(key.to_vec(), value.to_vec()),
225 None => Op::Del(key.to_vec()),
226 })
227 .collect();
228 for op in deriver.derive(0, &ops, &*self.base)? {
229 match op {
230 Op::Put(key, value) | Op::Set(key, value) => {
231 rows.insert(key, Some(value));
232 }
233 Op::Del(key) | Op::Purge(key) => {
234 rows.insert(key, None);
235 }
236 }
237 }
238 }
239 }
240 Ok(Arc::new(rows))
241 })
242 .clone()
243 }
244
245 fn reaches_derived(&self, prefix: &[u8]) -> bool {
246 self.has_staged()
247 && self
248 .base
249 .deriver()
250 .is_some_and(|deriver| deriver.prefix_reaches_derived(prefix))
251 }
252
253 #[must_use]
255 pub fn base(&self) -> &Arc<ReadView> {
256 &self.base
257 }
258
259 #[must_use]
261 pub fn commit_index(&self) -> u64 {
262 self.base.commit_index()
263 }
264
265 #[must_use]
267 pub fn cancellation(&self) -> ReadCancellation {
268 self.base.cancellation()
269 }
270
271 pub fn put(&mut self, key: Vec<u8>, value: Vec<u8>) {
273 self.derived = std::sync::OnceLock::new();
274 self.buffer.insert(key, Some(value));
275 }
276
277 pub fn delete(&mut self, key: Vec<u8>) {
279 self.derived = std::sync::OnceLock::new();
280 self.buffer.insert(key, None);
281 }
282
283 pub fn apply_ops(&mut self, ops: &[Op]) {
286 for op in ops {
287 match op {
288 Op::Put(k, v) | Op::Set(k, v) => {
289 self.buffer.insert(k.clone(), Some(v.clone()));
290 }
291 Op::Del(k) | Op::Purge(k) => {
292 self.buffer.insert(k.clone(), None);
293 }
294 }
295 }
296 self.derived = std::sync::OnceLock::new();
297 }
298
299 pub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, StorageError> {
304 self.with_value(key, |value| value.map(<[u8]>::to_vec))
305 }
306
307 pub fn with_value<R>(
314 &self,
315 key: &[u8],
316 f: impl FnOnce(Option<&[u8]>) -> R,
317 ) -> Result<R, StorageError> {
318 if let Some(value) = self.staged(key) {
319 return Ok(f(value));
320 }
321 if self.reaches_derived(key)
322 && self
323 .base
324 .deriver()
325 .is_some_and(|deriver| deriver.is_derived_key(key))
326 {
327 if let Some(value) = self.derived_rows()?.get(key) {
328 return Ok(f(value.as_deref()));
329 }
330 }
331 self.base.with_value(key, f)
332 }
333
334 pub fn range_prefix(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
340 let merged = self.base.range_prefix(prefix)?.into_iter().collect();
341 let upper = crate::prefix_range(prefix).1;
342 let end = if upper.is_empty() {
343 Bound::Unbounded
344 } else {
345 Bound::Excluded(upper.as_slice())
346 };
347 let derived = if self.reaches_derived(prefix) {
348 Some(self.derived_rows()?)
349 } else {
350 None
351 };
352 Ok(self.merge_staged(merged, prefix, end, derived.as_deref()))
353 }
354
355 fn merge_staged(
358 &self,
359 mut merged: BTreeMap<Vec<u8>, Vec<u8>>,
360 start: &[u8],
361 end: Bound<&[u8]>,
362 derived: Option<&BTreeMap<Vec<u8>, Option<Vec<u8>>>>,
363 ) -> Vec<(Vec<u8>, Vec<u8>)> {
364 let start = Bound::Included(start);
365 let derived_rows = derived.into_iter().flat_map(|rows| {
366 rows.range::<[u8], _>((start, end))
367 .map(|(key, value)| (key.as_slice(), value.as_deref()))
368 });
369 for (key, value) in self
370 .staged_range(start, end)
371 .into_iter()
372 .chain(derived_rows)
373 {
374 match value {
375 Some(value) => {
376 merged.insert(key.to_vec(), value.to_vec());
377 }
378 None => {
379 merged.remove(key);
380 }
381 }
382 }
383 merged.into_iter().collect()
384 }
385
386 pub fn range_keys(&self, start: &[u8], end: &[u8]) -> Result<Vec<Vec<u8>>, StorageError> {
393 let bounds = ScanBounds {
394 start: Bound::Included(start.to_vec()),
395 end: if end.is_empty() {
396 Bound::Unbounded
397 } else {
398 Bound::Excluded(end.to_vec())
399 },
400 };
401 let mut keys: BTreeSet<Vec<u8>> = BTreeSet::new();
402 let mut cursor = self.base.scan(bounds, ScanProjection::Keys)?;
403 loop {
404 let batch = cursor.next_batch(1024, 8 * 1024 * 1024)?;
405 for row in batch.rows {
406 keys.insert(row.key);
407 }
408 if batch.done {
409 break;
410 }
411 }
412 let end_bound = if end.is_empty() {
413 Bound::Unbounded
414 } else {
415 Bound::Excluded(end)
416 };
417 for (key, value) in self.staged_range(Bound::Included(start), end_bound) {
418 match value {
419 Some(_) => {
420 keys.insert(key.to_vec());
421 }
422 None => {
423 keys.remove(key);
424 }
425 }
426 }
427 Ok(keys.into_iter().collect())
428 }
429
430 pub fn range(&self, start: &[u8], end: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>, StorageError> {
436 let merged = self.base.range(start, end)?.into_iter().collect();
437 let end_bound = if end.is_empty() {
438 Bound::Unbounded
439 } else {
440 Bound::Excluded(end)
441 };
442 let common = start
443 .iter()
444 .zip(end.iter())
445 .take_while(|(a, b)| a == b)
446 .count();
447 let derived = if self.reaches_derived(&start[..common]) {
448 Some(self.derived_rows()?)
449 } else {
450 None
451 };
452 Ok(self.merge_staged(merged, start, end_bound, derived.as_deref()))
453 }
454}