sov_first_read_last_write_cache/
access.rs1use thiserror::Error;
2
3use crate::CacheValue;
4
5#[derive(Error, Debug, PartialEq, Eq)]
6pub enum MergeError {
7 #[error("consecutive reads are inconsistent: left read: {left:?}, right read: {right:?}")]
8 ReadThenRead {
9 left: Option<CacheValue>,
10 right: Option<CacheValue>,
11 },
12 #[error("the read: {read:?} is in inconsistent with the previous write: {write:?}")]
13 WriteThenRead {
14 write: Option<CacheValue>,
15 read: Option<CacheValue>,
16 },
17}
18
19#[derive(PartialEq, Eq, Debug, Clone)]
27pub(crate) enum Access {
28 Read(Option<CacheValue>),
29 ReadThenWrite {
30 original: Option<CacheValue>,
31 modified: Option<CacheValue>,
32 },
33 Write(Option<CacheValue>),
34}
35
36impl Access {
37 pub(crate) fn last_value(&self) -> &Option<CacheValue> {
38 match self {
39 Access::Read(value) => value,
40 Access::ReadThenWrite { modified, .. } => modified,
41 Access::Write(value) => value,
42 }
43 }
44
45 pub(crate) fn write_value(&mut self, new_value: Option<CacheValue>) {
46 match self {
47 Access::Read(original) => {
49 if original == &new_value {
51 return;
52 }
53 *self = Access::ReadThenWrite {
55 original: original.take(),
56
57 modified: new_value,
58 };
59 }
60 Access::ReadThenWrite { original, modified } => {
62 if original == &new_value {
64 *self = Access::Read(new_value)
65 } else {
66 *modified = new_value
67 }
68 }
69 Access::Write(value) => *value = new_value,
72 }
73 }
74
75 pub(crate) fn merge(&mut self, rhs: Self) -> Result<(), MergeError> {
76 match self {
79 Access::Read(left_read) => match rhs {
80 Access::Read(right_read) => {
81 if left_read != &right_read {
82 Err(MergeError::ReadThenRead {
83 left: left_read.clone(),
84 right: right_read,
85 })
86 } else {
87 Ok(())
88 }
89 }
90 Access::ReadThenWrite {
91 original: right_original,
92 modified: right_modified,
93 } => {
94 if left_read != &right_original {
95 Err(MergeError::ReadThenRead {
96 left: left_read.clone(),
97 right: right_original,
98 })
99 } else {
100 *self = Access::ReadThenWrite {
101 original: right_original,
102 modified: right_modified,
103 };
104
105 Ok(())
106 }
107 }
108 Access::Write(right_write) => {
109 *self = Access::ReadThenWrite {
110 original: left_read.take(),
111 modified: right_write,
112 };
113 Ok(())
114 }
115 },
116 Access::ReadThenWrite {
117 original: left_original,
118 modified: left_modified,
119 } => match rhs {
120 Access::Read(right_read) => {
121 if left_modified != &right_read {
122 Err(MergeError::WriteThenRead {
123 write: left_modified.clone(),
124 read: right_read,
125 })
126 } else {
127 Ok(())
128 }
129 }
130 Access::ReadThenWrite {
131 original: right_original,
132 modified: right_modified,
133 } => {
134 if left_modified != &right_original {
135 Err(MergeError::WriteThenRead {
136 write: left_modified.clone(),
137 read: right_original,
138 })
139 } else {
140 *self = Access::ReadThenWrite {
141 original: left_original.take(),
142 modified: right_modified,
143 };
144 Ok(())
145 }
146 }
147 Access::Write(right_write) => {
148 *self = Access::ReadThenWrite {
149 original: left_original.take(),
150 modified: right_write,
151 };
152 Ok(())
153 }
154 },
155 Access::Write(left_write) => match rhs {
156 Access::Read(right_read) => {
157 if left_write != &right_read {
158 Err(MergeError::WriteThenRead {
159 write: left_write.clone(),
160 read: right_read,
161 })
162 } else {
163 Ok(())
164 }
165 }
166 Access::ReadThenWrite {
167 original: right_original,
168 modified: right_modified,
169 } => {
170 if left_write != &right_original {
171 Err(MergeError::WriteThenRead {
172 write: left_write.clone(),
173 read: right_original,
174 })
175 } else {
176 *self = Access::Write(right_modified);
177 Ok(())
178 }
179 }
180 Access::Write(right_write) => {
181 *self = Access::Write(right_write);
182 Ok(())
183 }
184 },
185 }
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192 use crate::utils::test_util::create_value;
193
194 #[test]
195 fn test_access_read_write() {
196 let original_value = create_value(1);
197 let mut access = Access::Read(original_value.clone());
198
199 {
201 let new_value = create_value(2);
202 access.write_value(new_value.clone());
203
204 assert_eq!(access.last_value(), &new_value);
205 assert_eq!(
206 access,
207 Access::ReadThenWrite {
208 original: original_value.clone(),
209 modified: new_value
210 }
211 );
212 }
213
214 {
216 let new_value = create_value(3);
217 access.write_value(new_value.clone());
218
219 assert_eq!(access.last_value(), &new_value);
220 assert_eq!(
221 access,
222 Access::ReadThenWrite {
223 original: original_value,
224 modified: new_value
225 }
226 );
227 }
228 }
229
230 #[test]
231 fn test_access_write() {
232 let original_value = create_value(1);
233 let mut access = Access::Write(original_value.clone());
234
235 {
237 assert_eq!(access.last_value(), &original_value);
238 let new_value = create_value(3);
239 access.write_value(new_value.clone());
240 assert_eq!(access.last_value(), &new_value);
241 assert_eq!(access, Access::Write(new_value));
242 }
243 }
244
245 #[test]
246 fn test_access_merge() {
247 let first_read = 1;
248 let mut value = create_value(first_read);
249 let mut left = Access::Read(value.clone());
250
251 let last_write = 10;
252 for i in 2..last_write + 1 {
253 left.merge(Access::Read(value.clone())).unwrap();
254
255 value = create_value(i);
256 left.merge(Access::Write(value.clone())).unwrap();
257 }
258
259 assert_eq!(
260 left,
261 Access::ReadThenWrite {
262 original: create_value(first_read),
263 modified: create_value(last_write)
264 }
265 )
266 }
267
268 #[test]
269 fn test_err_merge_left_read_neq_right_read() {
270 let first_read = 1;
271 let value = create_value(first_read);
272 let left = &mut Access::Read(value.clone());
273
274 let second_read = 2;
275 let value2 = create_value(second_read);
276
277 assert_eq!(
278 left.merge(Access::Read(value2.clone())),
279 Err(MergeError::ReadThenRead {
280 left: value,
281 right: value2,
282 })
283 );
284 }
285
286 #[test]
287 fn test_err_merge_left_read_neq_right_orig() {
288 let first_read = 1;
289 let value = create_value(first_read);
290 let left = &mut Access::Read(value.clone());
291
292 let second_read = 2;
293 let value2 = create_value(second_read);
294 let right = Access::ReadThenWrite {
295 original: value2.clone(),
296 modified: value.clone(),
297 };
298
299 assert_eq!(
300 left.merge(right),
301 Err(MergeError::ReadThenRead {
302 left: value,
303 right: value2,
304 })
305 );
306 }
307
308 #[test]
309 fn test_err_merge_left_mod_neq_right_read() {
310 let first_read = 1;
311 let value = create_value(first_read);
312
313 let second_read = 2;
314 let value2 = create_value(second_read);
315
316 let left = &mut Access::ReadThenWrite {
317 original: value2.clone(),
318 modified: value.clone(),
319 };
320
321 let right = Access::Read(value2.clone());
322
323 assert_eq!(
324 left.merge(right),
325 Err(MergeError::WriteThenRead {
326 write: value,
327 read: value2,
328 })
329 )
330 }
331
332 #[test]
333 fn test_err_merge_left_mod_neq_right_orig() {
334 let first_read = 1;
335 let value = create_value(first_read);
336
337 let second_read = 2;
338 let value2 = create_value(second_read);
339
340 let left = &mut Access::ReadThenWrite {
341 original: value.clone(),
342 modified: value2.clone(),
343 };
344
345 let right = Access::ReadThenWrite {
346 original: value.clone(),
347 modified: value2.clone(),
348 };
349
350 assert_eq!(
351 left.merge(right),
352 Err(MergeError::WriteThenRead {
353 write: value2,
354 read: value,
355 })
356 )
357 }
358
359 #[test]
360 fn test_err_merge_left_right_neq_right_orig() {
361 let first_read = 1;
362 let value = create_value(first_read);
363
364 let second_read = 2;
365 let value2 = create_value(second_read);
366
367 let left = &mut Access::Write(value.clone());
368 let right = Access::ReadThenWrite {
369 original: value2.clone(),
370 modified: value.clone(),
371 };
372
373 assert_eq!(
374 left.merge(right),
375 Err(MergeError::WriteThenRead {
376 write: value,
377 read: value2,
378 })
379 )
380 }
381}