1use crate::{ColumnValue, MergeError, Operation, RowId, Timestamp, Write, WriteId, WriteOracle};
2use std::collections::BTreeMap;
3
4#[derive(Clone, Debug, PartialEq, Eq)]
6pub struct Cell<V> {
7 pub write: WriteId,
9 pub value: ColumnValue<V>,
11}
12
13#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
15pub struct LostKey {
16 pub column: String,
18 pub write: WriteId,
20}
21
22#[derive(Clone, Debug, PartialEq, Eq)]
24pub struct LostValue<V> {
25 pub incarnation: u64,
27 pub value: ColumnValue<V>,
29 pub replaced_by: WriteId,
31}
32
33pub const fn generation_present(generation: u64) -> bool {
37 !generation.is_multiple_of(2)
38}
39
40#[derive(Clone, Debug, PartialEq, Eq)]
43pub struct RowState<V> {
44 pub(crate) row: RowId,
45 pub(crate) generation: u64,
46 pub(crate) generations: BTreeMap<u64, WriteId>,
47 pub(crate) cells: BTreeMap<String, Cell<V>>,
48 pub(crate) lost: BTreeMap<LostKey, LostValue<V>>,
49}
50
51impl<V> RowState<V> {
52 pub fn new(row: RowId) -> Self {
54 Self {
55 row,
56 generation: 0,
57 generations: BTreeMap::new(),
58 cells: BTreeMap::new(),
59 lost: BTreeMap::new(),
60 }
61 }
62 pub fn from_parts<O: WriteOracle>(
67 row: RowId,
68 generations: BTreeMap<u64, WriteId>,
69 cells: BTreeMap<String, Cell<V>>,
70 lost: BTreeMap<LostKey, LostValue<V>>,
71 oracle: &O,
72 ) -> Result<Self, O::Error> {
73 let mut generation: u64 = 0;
74 let mut previous_stamp = None;
75 for (g, write) in &generations {
76 let expected = generation.checked_add(1).ok_or(MergeError::GenerationExhausted)?;
77 if *g != expected {
78 return Err(MergeError::GenerationGap(expected).into());
79 }
80 let stamp = timestamp(oracle, *write)?;
81 if previous_stamp.is_some_and(|previous| previous >= stamp) {
82 return Err(MergeError::GenerationTimestamp(*g).into());
83 }
84 previous_stamp = Some(stamp);
85 generation = *g;
86 }
87 if !generation_present(generation) && !cells.is_empty() {
88 return Err(MergeError::DeletedRowHasCells.into());
89 }
90 for (column, cell) in &cells {
91 let stamp = timestamp(oracle, cell.write)?;
92 if previous_stamp.is_some_and(|start| stamp < start) {
93 return Err(MergeError::CellBeforeIncarnation(column.clone()).into());
94 }
95 for parent in cell.value.parents.values() {
96 parent.validate_written(&row)?;
97 }
98 }
99 let state = Self { row, generation, generations, cells, lost };
100 for (key, value) in &state.lost {
101 state.validate_loss(key, value, oracle)?;
102 }
103 Ok(state)
104 }
105
106 pub fn validate_loss<O: WriteOracle>(
110 &self,
111 key: &LostKey,
112 value: &LostValue<V>,
113 oracle: &O,
114 ) -> Result<(), O::Error> {
115 let invalid = || MergeError::InvalidLostValue(key.clone());
116 let inc = value.incarnation;
117 if !generation_present(inc) || inc > self.generation {
118 return Err(invalid().into());
119 }
120 let start = self.generations.get(&inc).ok_or_else(invalid)?;
121 let setter_stamp = timestamp(oracle, key.write)?;
122 if setter_stamp < timestamp(oracle, *start)? {
123 return Err(invalid().into());
124 }
125 let canonical = if inc < self.generation {
126 let delete = inc.checked_add(1).ok_or(MergeError::GenerationExhausted)?;
127 *self.generations.get(&delete).ok_or_else(invalid)?
128 } else {
129 let cell = self.cells.get(&key.column).ok_or_else(invalid)?;
130 if timestamp(oracle, cell.write)? <= setter_stamp {
131 return Err(invalid().into());
132 }
133 cell.write
134 };
135 if value.replaced_by != canonical || oracle.had_read(canonical, key.write)? {
136 return Err(invalid().into());
137 }
138 for parent in value.value.parents.values() {
139 parent.validate_written(&self.row)?;
140 }
141 Ok(())
142 }
143
144 pub fn row(&self) -> &RowId {
146 &self.row
147 }
148 pub fn generation(&self) -> u64 {
150 self.generation
151 }
152 pub fn present(&self) -> bool {
154 generation_present(self.generation)
155 }
156 pub fn generations(&self) -> &BTreeMap<u64, WriteId> {
158 &self.generations
159 }
160 pub fn cells(&self) -> &BTreeMap<String, Cell<V>> {
162 &self.cells
163 }
164 pub fn lost(&self) -> &BTreeMap<LostKey, LostValue<V>> {
166 &self.lost
167 }
168
169 pub fn map_schema(
173 mut self,
174 row: RowId,
175 mut column: impl FnMut(String, ColumnValue<V>) -> Option<(String, ColumnValue<V>)>,
176 ) -> Self {
177 self.row = row;
178 self.cells = self
179 .cells
180 .into_iter()
181 .filter_map(|(name, cell)| {
182 let (name, value) = column(name, cell.value)?;
183 Some((name, Cell { write: cell.write, value }))
184 })
185 .collect();
186 self.lost = self
187 .lost
188 .into_iter()
189 .filter_map(|(key, lost)| {
190 let (name, value) = column(key.column, lost.value)?;
191 Some((LostKey { column: name, write: key.write }, LostValue { value, ..lost }))
192 })
193 .collect();
194 self
195 }
196
197 #[cfg(test)]
200 pub(crate) fn claim_order(
201 &self,
202 columns: &[String],
203 order: impl Fn(WriteId) -> Result<crate::ClaimOrder, MergeError>,
204 ) -> Result<crate::ClaimOrder, MergeError> {
205 let mut latest = None;
206 for column in columns {
207 let cell = self
208 .cells
209 .get(column)
210 .ok_or_else(|| MergeError::MissingClaimColumn(column.clone()))?;
211 let stamp = order(cell.write)?;
212 latest = Some(match latest {
213 Some(old) => std::cmp::max(old, stamp),
214 None => stamp,
215 });
216 }
217 latest.ok_or(MergeError::EmptyClaim)
218 }
219}
220
221#[derive(Clone, Debug, PartialEq, Eq)]
223pub enum LostChange<V> {
224 Put(LostKey, LostValue<V>),
226 Remove(LostKey),
228}
229
230#[derive(Clone, Debug, PartialEq, Eq)]
232pub struct RowUpdate<V> {
233 pub state: RowState<V>,
235 pub lost_changes: Vec<LostChange<V>>,
237}
238
239pub(crate) fn timestamp<O: WriteOracle>(oracle: &O, id: WriteId) -> Result<Timestamp, O::Error> {
240 oracle.timestamp(id)?.ok_or_else(|| MergeError::MissingWrite(id).into())
241}
242
243pub fn apply<V: Clone + Eq, P: crate::WritePast, O: WriteOracle>(
255 state: &RowState<V>,
256 write: &Write<V, P>,
257 oracle: &O,
258) -> Result<RowUpdate<V>, O::Error> {
259 write.validate_metadata(oracle)?;
260 let change = write
261 .changes
262 .get(&state.row)
263 .ok_or_else(|| MergeError::MissingChange(state.row.clone()))?;
264 change.validate(&state.row)?;
265 if change.generation > state.generation {
266 return Err(MergeError::GenerationAhead { row: state.row.clone() }.into());
267 }
268 if change.generation != 0 {
269 let first = state.generations.get(&change.generation).ok_or_else(|| {
270 MergeError::GenerationNotSeen { row: state.row.clone(), generation: change.generation }
271 })?;
272 let earliest = timestamp(oracle, *first)?;
273 let mut possible_witness = false;
274 for past in write.had_read.frontier() {
275 possible_witness |= timestamp(oracle, *past)? >= earliest;
276 }
277 if !possible_witness {
278 return Err(MergeError::GenerationNotSeen {
279 row: state.row.clone(),
280 generation: change.generation,
281 }
282 .into());
283 }
284 }
285 let incarnation = change.incarnation()?;
286 let columns = change.operation.columns();
287 let deletes = matches!(change.operation, Operation::Delete);
288 let mut next = state.clone();
289 for (key, old) in &state.lost {
291 let sets = columns.is_some_and(|c| c.contains_key(&key.column));
292 let replaces = (deletes && change.generation == old.incarnation)
293 || (sets
294 && incarnation == old.incarnation
295 && timestamp(oracle, key.write)? < write.timestamp);
296 if replaces {
297 if write.had_read.contains(&key.write) {
298 next.lost.remove(key);
299 } else {
300 let replacement = if deletes {
301 if old.incarnation < state.generation
302 && timestamp(oracle, old.replaced_by)? < write.timestamp
303 {
304 old.replaced_by
305 } else {
306 write.id
307 }
308 } else if old.incarnation < state.generation
309 || timestamp(oracle, old.replaced_by)? > write.timestamp
310 {
311 old.replaced_by
312 } else {
313 write.id
314 };
315 next.lost
316 .insert(key.clone(), LostValue { replaced_by: replacement, ..old.clone() });
317 }
318 }
319 }
320 for (column, current) in &state.cells {
322 let replaces = (deletes && change.generation == state.generation)
323 || (incarnation == state.generation
324 && columns.is_some_and(|c| c.contains_key(column))
325 && timestamp(oracle, current.write)? < write.timestamp);
326 if replaces && !write.had_read.contains(¤t.write) {
327 next.lost.insert(
328 LostKey { column: column.clone(), write: current.write },
329 LostValue {
330 incarnation: state.generation,
331 value: current.value.clone(),
332 replaced_by: write.id,
333 },
334 );
335 }
336 }
337 if let Some(columns) = columns {
339 for (column, value) in columns {
340 let replacement = if incarnation < state.generation {
341 let deleted_generation =
342 incarnation.checked_add(1).ok_or(MergeError::GenerationExhausted)?;
343 Some(*state.generations.get(&deleted_generation).ok_or_else(|| {
344 MergeError::GenerationNotSeen {
345 row: state.row.clone(),
346 generation: deleted_generation,
347 }
348 })?)
349 } else if incarnation == state.generation {
350 match state.cells.get(column) {
351 Some(current) if timestamp(oracle, current.write)? > write.timestamp => {
352 Some(current.write)
353 }
354 _ => None,
355 }
356 } else {
357 None
358 };
359 if let Some(replaced_by) = replacement {
360 next.lost.insert(
361 LostKey { column: column.clone(), write: write.id },
362 LostValue { incarnation, value: value.clone(), replaced_by },
363 );
364 }
365 }
366 }
367 if change.operation.advances() {
368 let generation = change.after()?;
369 let winner = match state.generations.get(&generation) {
370 Some(old) if timestamp(oracle, *old)? < write.timestamp => *old,
371 _ => write.id,
372 };
373 next.generations.insert(generation, winner);
374 if state.generation < generation {
375 next.generation = generation;
376 next.cells.clear();
377 if let Operation::Insert(columns) = &change.operation {
378 for (column, value) in columns {
379 next.cells
380 .insert(column.clone(), Cell { write: write.id, value: value.clone() });
381 }
382 }
383 }
384 }
385 if incarnation == state.generation {
386 if let Some(columns) = columns {
387 for (column, value) in columns {
388 let wins = match state.cells.get(column) {
389 Some(old) => timestamp(oracle, old.write)? < write.timestamp,
390 None => true,
391 };
392 if wins {
393 next.cells
394 .insert(column.clone(), Cell { write: write.id, value: value.clone() });
395 }
396 }
397 }
398 }
399 let mut lost_changes = Vec::new();
400 for key in state.lost.keys() {
401 if !next.lost.contains_key(key) {
402 lost_changes.push(LostChange::Remove(key.clone()));
403 }
404 }
405 for (key, value) in &next.lost {
406 if state.lost.get(key) != Some(value) {
407 lost_changes.push(LostChange::Put(key.clone(), value.clone()));
408 }
409 }
410 Ok(RowUpdate { state: next, lost_changes })
411}
412
413#[cfg(test)]
414#[path = "state_tests.rs"]
415mod tests;