#![allow(dead_code)]
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) enum AffinityKind {
#[default]
ReadWrite,
ReadOnly,
}
#[derive(Debug)]
pub(crate) struct TransactionAffinity {
entry_id: AtomicU64,
kind: AffinityKind,
}
impl Default for TransactionAffinity {
fn default() -> Self {
Self::new_read_write()
}
}
#[allow(dead_code)]
impl TransactionAffinity {
pub(crate) fn new() -> Self {
Self::new_read_write()
}
pub(crate) fn new_read_write() -> Self {
Self {
entry_id: AtomicU64::new(0),
kind: AffinityKind::ReadWrite,
}
}
pub(crate) fn new_read_only() -> Self {
Self {
entry_id: AtomicU64::new(0),
kind: AffinityKind::ReadOnly,
}
}
pub(crate) fn is_read_write(&self) -> bool {
self.kind == AffinityKind::ReadWrite
}
pub(crate) fn is_read_only(&self) -> bool {
self.kind == AffinityKind::ReadOnly
}
pub(crate) fn pinned_entry_id(&self) -> Option<u64> {
let id = self.entry_id.load(Ordering::Acquire);
(id != 0).then_some(id)
}
pub(crate) fn set_entry_id(&self, entry_id: u64) {
debug_assert_ne!(entry_id, 0, "entry_id must be non-zero");
self.entry_id.store(entry_id, Ordering::Release);
}
pub(crate) fn reset(&self) {
self.entry_id.store(0, Ordering::Release);
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fmt::Debug;
#[test]
fn traits() {
static_assertions::assert_impl_all!(TransactionAffinity: Debug, Send, Sync);
static_assertions::assert_impl_all!(AffinityKind: Clone, Copy, Debug, PartialEq, Eq, Send, Sync);
}
#[test]
fn transaction_affinity_pin_and_reset() {
assert_eq!(
AffinityKind::default(),
AffinityKind::ReadWrite,
"Default AffinityKind must be ReadWrite"
);
let default_affinity = TransactionAffinity::default();
assert!(
default_affinity.is_read_write(),
"Default affinity must be ReadWrite"
);
let new_affinity = TransactionAffinity::new();
assert!(
new_affinity.is_read_write(),
"TransactionAffinity::new must be ReadWrite"
);
let affinity = TransactionAffinity::new_read_write();
assert!(
affinity.is_read_write(),
"Default affinity must be ReadWrite"
);
assert!(
!affinity.is_read_only(),
"ReadWrite affinity is not ReadOnly"
);
assert_eq!(
affinity.pinned_entry_id(),
None,
"Initial pinned entry ID must be None"
);
affinity.set_entry_id(42);
assert_eq!(
affinity.pinned_entry_id(),
Some(42),
"Pinned entry ID must be 42 after set_entry_id"
);
affinity.set_entry_id(99);
assert_eq!(
affinity.pinned_entry_id(),
Some(99),
"Pinned entry ID must be updated to 99"
);
affinity.reset();
assert_eq!(
affinity.pinned_entry_id(),
None,
"Pinned entry ID must be None after reset"
);
let read_only_affinity = TransactionAffinity::new_read_only();
assert!(
read_only_affinity.is_read_only(),
"new_read_only must set ReadOnly kind"
);
assert!(
!read_only_affinity.is_read_write(),
"ReadOnly affinity is not ReadWrite"
);
}
}