1use crate::epoch::Epoch;
19use crate::memtable::Row;
20use crate::pma::Pma;
21use crate::rowid::RowId;
22use std::collections::BTreeMap;
23
24type VersionKey = (RowId, Epoch);
27
28#[derive(Clone)]
31pub struct MutableRun {
32 pma: Pma<VersionKey, Row>,
33 byte_size: u64,
34}
35
36impl Default for MutableRun {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl MutableRun {
43 pub fn new() -> Self {
44 Self {
45 pma: Pma::new(),
46 byte_size: 0,
47 }
48 }
49
50 pub fn insert_many(&mut self, rows: Vec<Row>) {
54 let batch: Vec<(VersionKey, Row)> = rows
55 .into_iter()
56 .map(|r| {
57 self.byte_size = self.byte_size.saturating_add(r.estimated_bytes());
58 ((r.row_id, r.committed_epoch), r)
59 })
60 .collect();
61 self.pma.extend_sorted(batch);
62 }
63
64 pub fn len(&self) -> usize {
66 self.pma.len()
67 }
68
69 pub fn is_empty(&self) -> bool {
70 self.pma.is_empty()
71 }
72
73 pub fn approx_bytes(&self) -> u64 {
75 self.byte_size
76 }
77
78 pub fn get_version(&self, row_id: RowId, snapshot_epoch: Epoch) -> Option<(Epoch, Row)> {
83 let mut best: Option<(Epoch, Row)> = None;
84 for ((rid, ep), row) in self.pma.iter_from(&(row_id, Epoch::ZERO)) {
85 if *rid != row_id {
86 break;
87 }
88 if *ep <= snapshot_epoch {
89 best = Some((*ep, row.clone()));
90 }
91 }
92 best
93 }
94
95 pub fn visible_versions(&self, snapshot_epoch: Epoch) -> Vec<Row> {
98 let mut by_row: BTreeMap<RowId, Row> = BTreeMap::new();
99 for ((rid, ep), row) in self.pma.iter() {
100 if *ep <= snapshot_epoch {
101 by_row.insert(*rid, row.clone()); }
103 }
104 by_row.into_values().collect()
105 }
106
107 pub fn drain_sorted(&mut self) -> Vec<Row> {
110 let out: Vec<Row> = self
111 .pma
112 .drain_sorted()
113 .into_iter()
114 .map(|(_, r)| r)
115 .collect();
116 self.byte_size = 0;
117 out
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use crate::memtable::Value;
125
126 fn row(id: u64, epoch: u64, v: i64) -> Row {
127 Row::new(RowId(id), Epoch(epoch)).with_column(1, Value::Int64(v))
128 }
129
130 fn tomb(id: u64, epoch: u64) -> Row {
131 Row {
132 row_id: RowId(id),
133 committed_epoch: Epoch(epoch),
134 columns: std::collections::HashMap::new(),
135 deleted: true,
136 }
137 }
138
139 fn int_of(r: &Row) -> i64 {
140 match r.columns.get(&1) {
141 Some(Value::Int64(x)) => *x,
142 _ => panic!("expected Int64 column"),
143 }
144 }
145
146 #[test]
147 fn get_version_returns_newest_visible() {
148 let mut mr = MutableRun::new();
149 mr.insert_many(vec![row(1, 1, 10), row(1, 3, 30), row(1, 9, 90)]);
150 assert_eq!(int_of(&mr.get_version(RowId(1), Epoch(5)).unwrap().1), 30);
152 assert_eq!(int_of(&mr.get_version(RowId(1), Epoch(9)).unwrap().1), 90);
154 assert!(mr.get_version(RowId(1), Epoch(0)).is_none());
156 assert!(mr.get_version(RowId(2), Epoch(100)).is_none());
158 }
159
160 #[test]
161 fn tombstone_is_returned_as_a_version() {
162 let mut mr = MutableRun::new();
163 mr.insert_many(vec![row(1, 1, 10), tomb(1, 2)]);
164 let v = mr.get_version(RowId(1), Epoch(5)).unwrap().1;
165 assert!(v.deleted);
166 let v0 = mr.get_version(RowId(1), Epoch(1)).unwrap().1;
168 assert!(!v0.deleted);
169 }
170
171 #[test]
172 fn visible_versions_dedups_to_newest_ascending() {
173 let mut mr = MutableRun::new();
174 mr.insert_many(vec![
175 row(3, 1, 30),
176 row(1, 1, 10),
177 row(2, 9, 20), row(1, 3, 11), row(3, 2, 31),
180 ]);
181 let out = mr.visible_versions(Epoch(5));
182 let got: Vec<(u64, i64)> = out.iter().map(|r| (r.row_id.0, int_of(r))).collect();
183 assert_eq!(got, vec![(1, 11), (3, 31)], "row 2 hidden, newest wins");
184 }
185
186 #[test]
187 fn drain_sorted_is_ascending_version_order_and_empties() {
188 let mut mr = MutableRun::new();
189 mr.insert_many(vec![row(3, 1, 0), row(1, 2, 0), row(1, 1, 0), row(2, 1, 0)]);
190 let out = mr.drain_sorted();
191 let keys: Vec<(u64, u64)> = out
192 .iter()
193 .map(|r| (r.row_id.0, r.committed_epoch.0))
194 .collect();
195 assert_eq!(keys, vec![(1, 1), (1, 2), (2, 1), (3, 1)]);
196 assert!(mr.is_empty());
197 assert_eq!(mr.approx_bytes(), 0);
198 }
199
200 #[test]
201 fn many_inserts_stay_queryable() {
202 let mut mr = MutableRun::new();
203 let mut rows = Vec::new();
204 for i in 0..500u64 {
205 rows.push(row(i, 1, i as i64));
206 }
207 mr.insert_many(rows);
208 assert_eq!(mr.len(), 500);
209 for i in 0..500u64 {
210 assert_eq!(
211 int_of(&mr.get_version(RowId(i), Epoch(1)).unwrap().1),
212 i as i64
213 );
214 }
215 assert!(mr.approx_bytes() > 0);
216 }
217}