1use crate::{LockConflict, LockUpgrade};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
13pub enum LockType {
14 Read,
18
19 Write,
23
24 RangeRead,
28
29 RangeWrite,
33
34 RangeInsert,
38
39 None,
43
44 Restart,
48}
49
50impl LockType {
51 #[inline]
57 pub fn is_write_lock(self) -> bool {
58 matches!(self, LockType::Write | LockType::RangeWrite)
59 }
60
61 #[inline]
65 pub fn causes_restart(self) -> bool {
66 matches!(self, LockType::RangeRead | LockType::RangeWrite)
67 }
68
69 pub fn get_conflict(self, requested: LockType) -> LockConflict {
81 use LockConflict::*;
82 use LockType::*;
83
84 match (self, requested) {
85 (Read, Read) => Allow,
87 (Read, Write) => Block,
88 (Read, RangeRead) => Allow,
89 (Read, RangeWrite) => Block,
90 (Read, RangeInsert) => Allow,
91
92 (Write, Read) => Block,
94 (Write, Write) => Block,
95 (Write, RangeRead) => Block,
96 (Write, RangeWrite) => Block,
97 (Write, RangeInsert) => Allow,
98
99 (RangeRead, Read) => Allow,
101 (RangeRead, Write) => Block,
102 (RangeRead, RangeRead) => Allow,
103 (RangeRead, RangeWrite) => Block,
104 (RangeRead, RangeInsert) => Block,
105
106 (RangeWrite, Read) => Block,
108 (RangeWrite, Write) => Block,
109 (RangeWrite, RangeRead) => Block,
110 (RangeWrite, RangeWrite) => Block,
111 (RangeWrite, RangeInsert) => Block,
112
113 (RangeInsert, Read) => Allow,
115 (RangeInsert, Write) => Allow,
116 (RangeInsert, RangeRead) => LockConflict::Restart,
117 (RangeInsert, RangeWrite) => LockConflict::Restart,
118 (RangeInsert, RangeInsert) => Allow,
119
120 _ => Allow,
122 }
123 }
124
125 pub fn get_upgrade(self, requested: LockType) -> LockUpgrade {
137 use LockType::*;
138 use LockUpgrade::*;
139
140 match (self, requested) {
141 (Read, Read) => Existing,
143 (Read, Write) => WritePromote,
144 (Read, RangeRead) => RangeReadImmed,
145 (Read, RangeWrite) => RangeWritePromote,
146 (Read, RangeInsert) => Illegal,
147
148 (Write, Read) => Existing,
150 (Write, Write) => Existing,
151 (Write, RangeRead) => RangeWriteImmed,
152 (Write, RangeWrite) => RangeWriteImmed,
153 (Write, RangeInsert) => Illegal,
154
155 (RangeRead, Read) => Existing,
157 (RangeRead, Write) => RangeWritePromote,
158 (RangeRead, RangeRead) => Existing,
159 (RangeRead, RangeWrite) => RangeWritePromote,
160 (RangeRead, RangeInsert) => Illegal,
161
162 (RangeWrite, Read) => Existing,
164 (RangeWrite, Write) => Existing,
165 (RangeWrite, RangeRead) => Existing,
166 (RangeWrite, RangeWrite) => Existing,
167 (RangeWrite, RangeInsert) => Illegal,
168
169 (RangeInsert, Read) => Illegal,
171 (RangeInsert, Write) => Illegal,
172 (RangeInsert, RangeRead) => Illegal,
173 (RangeInsert, RangeWrite) => Illegal,
174 (RangeInsert, RangeInsert) => Existing,
175
176 (None, _) => Illegal,
178 (_, None) => Existing,
179 (Restart, _) => Illegal,
180 (_, Restart) => Illegal,
181 }
182 }
183
184 #[inline]
188 pub fn index(self) -> usize {
189 match self {
190 LockType::Read => 0,
191 LockType::Write => 1,
192 LockType::RangeRead => 2,
193 LockType::RangeWrite => 3,
194 LockType::RangeInsert => 4,
195 LockType::None => 5,
196 LockType::Restart => 6,
197 }
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204
205 #[test]
206 fn test_is_write_lock() {
207 assert!(!LockType::Read.is_write_lock());
208 assert!(LockType::Write.is_write_lock());
209 assert!(!LockType::RangeRead.is_write_lock());
210 assert!(LockType::RangeWrite.is_write_lock());
211 assert!(!LockType::RangeInsert.is_write_lock()); assert!(!LockType::None.is_write_lock());
213 assert!(!LockType::Restart.is_write_lock());
214 }
215
216 #[test]
217 fn test_causes_restart() {
218 assert!(!LockType::Read.causes_restart());
219 assert!(!LockType::Write.causes_restart());
220 assert!(LockType::RangeRead.causes_restart());
221 assert!(LockType::RangeWrite.causes_restart());
222 assert!(!LockType::RangeInsert.causes_restart());
223 assert!(!LockType::None.causes_restart());
224 assert!(!LockType::Restart.causes_restart());
225 }
226
227 #[test]
228 fn test_index() {
229 assert_eq!(LockType::Read.index(), 0);
230 assert_eq!(LockType::Write.index(), 1);
231 assert_eq!(LockType::RangeRead.index(), 2);
232 assert_eq!(LockType::RangeWrite.index(), 3);
233 assert_eq!(LockType::RangeInsert.index(), 4);
234 assert_eq!(LockType::None.index(), 5);
235 assert_eq!(LockType::Restart.index(), 6);
236 }
237
238 #[test]
240 fn test_conflict_matrix_read_row() {
241 assert_eq!(
242 LockType::Read.get_conflict(LockType::Read),
243 LockConflict::Allow
244 );
245 assert_eq!(
246 LockType::Read.get_conflict(LockType::Write),
247 LockConflict::Block
248 );
249 assert_eq!(
250 LockType::Read.get_conflict(LockType::RangeRead),
251 LockConflict::Allow
252 );
253 assert_eq!(
254 LockType::Read.get_conflict(LockType::RangeWrite),
255 LockConflict::Block
256 );
257 assert_eq!(
258 LockType::Read.get_conflict(LockType::RangeInsert),
259 LockConflict::Allow
260 );
261 }
262
263 #[test]
264 fn test_conflict_matrix_write_row() {
265 assert_eq!(
266 LockType::Write.get_conflict(LockType::Read),
267 LockConflict::Block
268 );
269 assert_eq!(
270 LockType::Write.get_conflict(LockType::Write),
271 LockConflict::Block
272 );
273 assert_eq!(
274 LockType::Write.get_conflict(LockType::RangeRead),
275 LockConflict::Block
276 );
277 assert_eq!(
278 LockType::Write.get_conflict(LockType::RangeWrite),
279 LockConflict::Block
280 );
281 assert_eq!(
282 LockType::Write.get_conflict(LockType::RangeInsert),
283 LockConflict::Allow
284 );
285 }
286
287 #[test]
288 fn test_conflict_matrix_range_read_row() {
289 assert_eq!(
290 LockType::RangeRead.get_conflict(LockType::Read),
291 LockConflict::Allow
292 );
293 assert_eq!(
294 LockType::RangeRead.get_conflict(LockType::Write),
295 LockConflict::Block
296 );
297 assert_eq!(
298 LockType::RangeRead.get_conflict(LockType::RangeRead),
299 LockConflict::Allow
300 );
301 assert_eq!(
302 LockType::RangeRead.get_conflict(LockType::RangeWrite),
303 LockConflict::Block
304 );
305 assert_eq!(
306 LockType::RangeRead.get_conflict(LockType::RangeInsert),
307 LockConflict::Block
308 );
309 }
310
311 #[test]
312 fn test_conflict_matrix_range_write_row() {
313 assert_eq!(
314 LockType::RangeWrite.get_conflict(LockType::Read),
315 LockConflict::Block
316 );
317 assert_eq!(
318 LockType::RangeWrite.get_conflict(LockType::Write),
319 LockConflict::Block
320 );
321 assert_eq!(
322 LockType::RangeWrite.get_conflict(LockType::RangeRead),
323 LockConflict::Block
324 );
325 assert_eq!(
326 LockType::RangeWrite.get_conflict(LockType::RangeWrite),
327 LockConflict::Block
328 );
329 assert_eq!(
330 LockType::RangeWrite.get_conflict(LockType::RangeInsert),
331 LockConflict::Block
332 );
333 }
334
335 #[test]
336 fn test_conflict_matrix_range_insert_row() {
337 assert_eq!(
338 LockType::RangeInsert.get_conflict(LockType::Read),
339 LockConflict::Allow
340 );
341 assert_eq!(
342 LockType::RangeInsert.get_conflict(LockType::Write),
343 LockConflict::Allow
344 );
345 assert_eq!(
346 LockType::RangeInsert.get_conflict(LockType::RangeRead),
347 LockConflict::Restart
348 );
349 assert_eq!(
350 LockType::RangeInsert.get_conflict(LockType::RangeWrite),
351 LockConflict::Restart
352 );
353 assert_eq!(
354 LockType::RangeInsert.get_conflict(LockType::RangeInsert),
355 LockConflict::Allow
356 );
357 }
358
359 #[test]
361 fn test_upgrade_matrix_read_row() {
362 assert_eq!(
363 LockType::Read.get_upgrade(LockType::Read),
364 LockUpgrade::Existing
365 );
366 assert_eq!(
367 LockType::Read.get_upgrade(LockType::Write),
368 LockUpgrade::WritePromote
369 );
370 assert_eq!(
371 LockType::Read.get_upgrade(LockType::RangeRead),
372 LockUpgrade::RangeReadImmed
373 );
374 assert_eq!(
375 LockType::Read.get_upgrade(LockType::RangeWrite),
376 LockUpgrade::RangeWritePromote
377 );
378 assert_eq!(
379 LockType::Read.get_upgrade(LockType::RangeInsert),
380 LockUpgrade::Illegal
381 );
382 }
383
384 #[test]
385 fn test_upgrade_matrix_write_row() {
386 assert_eq!(
387 LockType::Write.get_upgrade(LockType::Read),
388 LockUpgrade::Existing
389 );
390 assert_eq!(
391 LockType::Write.get_upgrade(LockType::Write),
392 LockUpgrade::Existing
393 );
394 assert_eq!(
395 LockType::Write.get_upgrade(LockType::RangeRead),
396 LockUpgrade::RangeWriteImmed
397 );
398 assert_eq!(
399 LockType::Write.get_upgrade(LockType::RangeWrite),
400 LockUpgrade::RangeWriteImmed
401 );
402 assert_eq!(
403 LockType::Write.get_upgrade(LockType::RangeInsert),
404 LockUpgrade::Illegal
405 );
406 }
407
408 #[test]
409 fn test_upgrade_matrix_range_read_row() {
410 assert_eq!(
411 LockType::RangeRead.get_upgrade(LockType::Read),
412 LockUpgrade::Existing
413 );
414 assert_eq!(
415 LockType::RangeRead.get_upgrade(LockType::Write),
416 LockUpgrade::RangeWritePromote
417 );
418 assert_eq!(
419 LockType::RangeRead.get_upgrade(LockType::RangeRead),
420 LockUpgrade::Existing
421 );
422 assert_eq!(
423 LockType::RangeRead.get_upgrade(LockType::RangeWrite),
424 LockUpgrade::RangeWritePromote
425 );
426 assert_eq!(
427 LockType::RangeRead.get_upgrade(LockType::RangeInsert),
428 LockUpgrade::Illegal
429 );
430 }
431
432 #[test]
433 fn test_upgrade_matrix_range_write_row() {
434 assert_eq!(
435 LockType::RangeWrite.get_upgrade(LockType::Read),
436 LockUpgrade::Existing
437 );
438 assert_eq!(
439 LockType::RangeWrite.get_upgrade(LockType::Write),
440 LockUpgrade::Existing
441 );
442 assert_eq!(
443 LockType::RangeWrite.get_upgrade(LockType::RangeRead),
444 LockUpgrade::Existing
445 );
446 assert_eq!(
447 LockType::RangeWrite.get_upgrade(LockType::RangeWrite),
448 LockUpgrade::Existing
449 );
450 assert_eq!(
451 LockType::RangeWrite.get_upgrade(LockType::RangeInsert),
452 LockUpgrade::Illegal
453 );
454 }
455
456 #[test]
457 fn test_upgrade_matrix_range_insert_row() {
458 assert_eq!(
459 LockType::RangeInsert.get_upgrade(LockType::Read),
460 LockUpgrade::Illegal
461 );
462 assert_eq!(
463 LockType::RangeInsert.get_upgrade(LockType::Write),
464 LockUpgrade::Illegal
465 );
466 assert_eq!(
467 LockType::RangeInsert.get_upgrade(LockType::RangeRead),
468 LockUpgrade::Illegal
469 );
470 assert_eq!(
471 LockType::RangeInsert.get_upgrade(LockType::RangeWrite),
472 LockUpgrade::Illegal
473 );
474 assert_eq!(
475 LockType::RangeInsert.get_upgrade(LockType::RangeInsert),
476 LockUpgrade::Existing
477 );
478 }
479
480 #[test]
481 fn test_upgrade_matrix_none() {
482 assert_eq!(
484 LockType::None.get_upgrade(LockType::Read),
485 LockUpgrade::Illegal
486 );
487 assert_eq!(
488 LockType::None.get_upgrade(LockType::Write),
489 LockUpgrade::Illegal
490 );
491
492 assert_eq!(
494 LockType::Read.get_upgrade(LockType::None),
495 LockUpgrade::Existing
496 );
497 assert_eq!(
498 LockType::Write.get_upgrade(LockType::None),
499 LockUpgrade::Existing
500 );
501 }
502}