use std::fmt;
use serde::{Deserialize, Serialize};
pub(crate) const MVCC_COMMIT_COL: &str = "_commit_ts";
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Timestamp(u64);
impl Timestamp {
pub const MIN: Self = Self(0);
pub const MAX: Self = Self(u64::MAX);
#[inline]
pub const fn new(raw: u64) -> Self {
Self(raw)
}
#[inline]
pub const fn get(self) -> u64 {
self.0
}
#[inline]
pub(crate) const fn next(self) -> Self {
Self(self.0.saturating_add(1))
}
#[inline]
pub(crate) const fn saturating_add(self, delta: u64) -> Self {
Self(self.0.saturating_add(delta))
}
#[inline]
pub(crate) const fn saturating_sub(self, delta: u64) -> Self {
Self(self.0.saturating_sub(delta))
}
}
impl From<u64> for Timestamp {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<Timestamp> for u64 {
fn from(ts: Timestamp) -> Self {
ts.0
}
}
impl fmt::Debug for Timestamp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Timestamp").field(&self.0).finish()
}
}
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Debug)]
pub struct CommitClock {
next: AtomicU64,
}
impl CommitClock {
#[inline]
pub(crate) const fn new(start: Timestamp) -> Self {
Self {
next: AtomicU64::new(start.get()),
}
}
#[inline]
pub(crate) fn alloc(&self) -> Timestamp {
let current = self.next.fetch_add(1, Ordering::Relaxed);
Timestamp::new(current)
}
#[inline]
pub(crate) fn peek(&self) -> Timestamp {
Timestamp::new(self.next.load(Ordering::Relaxed))
}
#[inline]
pub(crate) fn advance_to_at_least(&self, candidate: Timestamp) {
let mut current = self.next.load(Ordering::Relaxed);
while candidate.get() > current {
match self.next.compare_exchange(
current,
candidate.get(),
Ordering::Relaxed,
Ordering::Relaxed,
) {
Ok(_) => break,
Err(actual) => current = actual,
}
}
}
}
impl Default for CommitClock {
fn default() -> Self {
Self::new(Timestamp::MIN)
}
}
#[derive(Debug, Clone, Copy)]
pub struct ReadView {
read_ts: Timestamp,
}
impl ReadView {
#[inline]
pub(crate) const fn new(read_ts: Timestamp) -> Self {
Self { read_ts }
}
#[inline]
pub(crate) const fn read_ts(&self) -> Timestamp {
self.read_ts
}
}