use crate::{LockConflict, LockUpgrade};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum LockType {
Read,
Write,
RangeRead,
RangeWrite,
RangeInsert,
None,
Restart,
}
impl LockType {
#[inline]
pub fn is_write_lock(self) -> bool {
matches!(self, LockType::Write | LockType::RangeWrite)
}
#[inline]
pub fn causes_restart(self) -> bool {
matches!(self, LockType::RangeRead | LockType::RangeWrite)
}
pub fn get_conflict(self, requested: LockType) -> LockConflict {
use LockConflict::*;
use LockType::*;
match (self, requested) {
(Read, Read) => Allow,
(Read, Write) => Block,
(Read, RangeRead) => Allow,
(Read, RangeWrite) => Block,
(Read, RangeInsert) => Allow,
(Write, Read) => Block,
(Write, Write) => Block,
(Write, RangeRead) => Block,
(Write, RangeWrite) => Block,
(Write, RangeInsert) => Allow,
(RangeRead, Read) => Allow,
(RangeRead, Write) => Block,
(RangeRead, RangeRead) => Allow,
(RangeRead, RangeWrite) => Block,
(RangeRead, RangeInsert) => Block,
(RangeWrite, Read) => Block,
(RangeWrite, Write) => Block,
(RangeWrite, RangeRead) => Block,
(RangeWrite, RangeWrite) => Block,
(RangeWrite, RangeInsert) => Block,
(RangeInsert, Read) => Allow,
(RangeInsert, Write) => Allow,
(RangeInsert, RangeRead) => LockConflict::Restart,
(RangeInsert, RangeWrite) => LockConflict::Restart,
(RangeInsert, RangeInsert) => Allow,
_ => Allow,
}
}
pub fn get_upgrade(self, requested: LockType) -> LockUpgrade {
use LockType::*;
use LockUpgrade::*;
match (self, requested) {
(Read, Read) => Existing,
(Read, Write) => WritePromote,
(Read, RangeRead) => RangeReadImmed,
(Read, RangeWrite) => RangeWritePromote,
(Read, RangeInsert) => Illegal,
(Write, Read) => Existing,
(Write, Write) => Existing,
(Write, RangeRead) => RangeWriteImmed,
(Write, RangeWrite) => RangeWriteImmed,
(Write, RangeInsert) => Illegal,
(RangeRead, Read) => Existing,
(RangeRead, Write) => RangeWritePromote,
(RangeRead, RangeRead) => Existing,
(RangeRead, RangeWrite) => RangeWritePromote,
(RangeRead, RangeInsert) => Illegal,
(RangeWrite, Read) => Existing,
(RangeWrite, Write) => Existing,
(RangeWrite, RangeRead) => Existing,
(RangeWrite, RangeWrite) => Existing,
(RangeWrite, RangeInsert) => Illegal,
(RangeInsert, Read) => Illegal,
(RangeInsert, Write) => Illegal,
(RangeInsert, RangeRead) => Illegal,
(RangeInsert, RangeWrite) => Illegal,
(RangeInsert, RangeInsert) => Existing,
(None, _) => Illegal,
(_, None) => Existing,
(Restart, _) => Illegal,
(_, Restart) => Illegal,
}
}
#[inline]
pub fn index(self) -> usize {
match self {
LockType::Read => 0,
LockType::Write => 1,
LockType::RangeRead => 2,
LockType::RangeWrite => 3,
LockType::RangeInsert => 4,
LockType::None => 5,
LockType::Restart => 6,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_write_lock() {
assert!(!LockType::Read.is_write_lock());
assert!(LockType::Write.is_write_lock());
assert!(!LockType::RangeRead.is_write_lock());
assert!(LockType::RangeWrite.is_write_lock());
assert!(!LockType::RangeInsert.is_write_lock()); assert!(!LockType::None.is_write_lock());
assert!(!LockType::Restart.is_write_lock());
}
#[test]
fn test_causes_restart() {
assert!(!LockType::Read.causes_restart());
assert!(!LockType::Write.causes_restart());
assert!(LockType::RangeRead.causes_restart());
assert!(LockType::RangeWrite.causes_restart());
assert!(!LockType::RangeInsert.causes_restart());
assert!(!LockType::None.causes_restart());
assert!(!LockType::Restart.causes_restart());
}
#[test]
fn test_index() {
assert_eq!(LockType::Read.index(), 0);
assert_eq!(LockType::Write.index(), 1);
assert_eq!(LockType::RangeRead.index(), 2);
assert_eq!(LockType::RangeWrite.index(), 3);
assert_eq!(LockType::RangeInsert.index(), 4);
assert_eq!(LockType::None.index(), 5);
assert_eq!(LockType::Restart.index(), 6);
}
#[test]
fn test_conflict_matrix_read_row() {
assert_eq!(
LockType::Read.get_conflict(LockType::Read),
LockConflict::Allow
);
assert_eq!(
LockType::Read.get_conflict(LockType::Write),
LockConflict::Block
);
assert_eq!(
LockType::Read.get_conflict(LockType::RangeRead),
LockConflict::Allow
);
assert_eq!(
LockType::Read.get_conflict(LockType::RangeWrite),
LockConflict::Block
);
assert_eq!(
LockType::Read.get_conflict(LockType::RangeInsert),
LockConflict::Allow
);
}
#[test]
fn test_conflict_matrix_write_row() {
assert_eq!(
LockType::Write.get_conflict(LockType::Read),
LockConflict::Block
);
assert_eq!(
LockType::Write.get_conflict(LockType::Write),
LockConflict::Block
);
assert_eq!(
LockType::Write.get_conflict(LockType::RangeRead),
LockConflict::Block
);
assert_eq!(
LockType::Write.get_conflict(LockType::RangeWrite),
LockConflict::Block
);
assert_eq!(
LockType::Write.get_conflict(LockType::RangeInsert),
LockConflict::Allow
);
}
#[test]
fn test_conflict_matrix_range_read_row() {
assert_eq!(
LockType::RangeRead.get_conflict(LockType::Read),
LockConflict::Allow
);
assert_eq!(
LockType::RangeRead.get_conflict(LockType::Write),
LockConflict::Block
);
assert_eq!(
LockType::RangeRead.get_conflict(LockType::RangeRead),
LockConflict::Allow
);
assert_eq!(
LockType::RangeRead.get_conflict(LockType::RangeWrite),
LockConflict::Block
);
assert_eq!(
LockType::RangeRead.get_conflict(LockType::RangeInsert),
LockConflict::Block
);
}
#[test]
fn test_conflict_matrix_range_write_row() {
assert_eq!(
LockType::RangeWrite.get_conflict(LockType::Read),
LockConflict::Block
);
assert_eq!(
LockType::RangeWrite.get_conflict(LockType::Write),
LockConflict::Block
);
assert_eq!(
LockType::RangeWrite.get_conflict(LockType::RangeRead),
LockConflict::Block
);
assert_eq!(
LockType::RangeWrite.get_conflict(LockType::RangeWrite),
LockConflict::Block
);
assert_eq!(
LockType::RangeWrite.get_conflict(LockType::RangeInsert),
LockConflict::Block
);
}
#[test]
fn test_conflict_matrix_range_insert_row() {
assert_eq!(
LockType::RangeInsert.get_conflict(LockType::Read),
LockConflict::Allow
);
assert_eq!(
LockType::RangeInsert.get_conflict(LockType::Write),
LockConflict::Allow
);
assert_eq!(
LockType::RangeInsert.get_conflict(LockType::RangeRead),
LockConflict::Restart
);
assert_eq!(
LockType::RangeInsert.get_conflict(LockType::RangeWrite),
LockConflict::Restart
);
assert_eq!(
LockType::RangeInsert.get_conflict(LockType::RangeInsert),
LockConflict::Allow
);
}
#[test]
fn test_upgrade_matrix_read_row() {
assert_eq!(
LockType::Read.get_upgrade(LockType::Read),
LockUpgrade::Existing
);
assert_eq!(
LockType::Read.get_upgrade(LockType::Write),
LockUpgrade::WritePromote
);
assert_eq!(
LockType::Read.get_upgrade(LockType::RangeRead),
LockUpgrade::RangeReadImmed
);
assert_eq!(
LockType::Read.get_upgrade(LockType::RangeWrite),
LockUpgrade::RangeWritePromote
);
assert_eq!(
LockType::Read.get_upgrade(LockType::RangeInsert),
LockUpgrade::Illegal
);
}
#[test]
fn test_upgrade_matrix_write_row() {
assert_eq!(
LockType::Write.get_upgrade(LockType::Read),
LockUpgrade::Existing
);
assert_eq!(
LockType::Write.get_upgrade(LockType::Write),
LockUpgrade::Existing
);
assert_eq!(
LockType::Write.get_upgrade(LockType::RangeRead),
LockUpgrade::RangeWriteImmed
);
assert_eq!(
LockType::Write.get_upgrade(LockType::RangeWrite),
LockUpgrade::RangeWriteImmed
);
assert_eq!(
LockType::Write.get_upgrade(LockType::RangeInsert),
LockUpgrade::Illegal
);
}
#[test]
fn test_upgrade_matrix_range_read_row() {
assert_eq!(
LockType::RangeRead.get_upgrade(LockType::Read),
LockUpgrade::Existing
);
assert_eq!(
LockType::RangeRead.get_upgrade(LockType::Write),
LockUpgrade::RangeWritePromote
);
assert_eq!(
LockType::RangeRead.get_upgrade(LockType::RangeRead),
LockUpgrade::Existing
);
assert_eq!(
LockType::RangeRead.get_upgrade(LockType::RangeWrite),
LockUpgrade::RangeWritePromote
);
assert_eq!(
LockType::RangeRead.get_upgrade(LockType::RangeInsert),
LockUpgrade::Illegal
);
}
#[test]
fn test_upgrade_matrix_range_write_row() {
assert_eq!(
LockType::RangeWrite.get_upgrade(LockType::Read),
LockUpgrade::Existing
);
assert_eq!(
LockType::RangeWrite.get_upgrade(LockType::Write),
LockUpgrade::Existing
);
assert_eq!(
LockType::RangeWrite.get_upgrade(LockType::RangeRead),
LockUpgrade::Existing
);
assert_eq!(
LockType::RangeWrite.get_upgrade(LockType::RangeWrite),
LockUpgrade::Existing
);
assert_eq!(
LockType::RangeWrite.get_upgrade(LockType::RangeInsert),
LockUpgrade::Illegal
);
}
#[test]
fn test_upgrade_matrix_range_insert_row() {
assert_eq!(
LockType::RangeInsert.get_upgrade(LockType::Read),
LockUpgrade::Illegal
);
assert_eq!(
LockType::RangeInsert.get_upgrade(LockType::Write),
LockUpgrade::Illegal
);
assert_eq!(
LockType::RangeInsert.get_upgrade(LockType::RangeRead),
LockUpgrade::Illegal
);
assert_eq!(
LockType::RangeInsert.get_upgrade(LockType::RangeWrite),
LockUpgrade::Illegal
);
assert_eq!(
LockType::RangeInsert.get_upgrade(LockType::RangeInsert),
LockUpgrade::Existing
);
}
#[test]
fn test_upgrade_matrix_none() {
assert_eq!(
LockType::None.get_upgrade(LockType::Read),
LockUpgrade::Illegal
);
assert_eq!(
LockType::None.get_upgrade(LockType::Write),
LockUpgrade::Illegal
);
assert_eq!(
LockType::Read.get_upgrade(LockType::None),
LockUpgrade::Existing
);
assert_eq!(
LockType::Write.get_upgrade(LockType::None),
LockUpgrade::Existing
);
}
}