mirror of
https://github.com/neondatabase/neon.git
synced 2026-05-27 18:10:37 +00:00
add AtomicLsn
AtomicLsn is a wrapper around AtomicU64 that has load() and store() members that are cheap (on x86, anyway) and can be safely used in any context. This commit uses AtomicLsn in the page cache, and fixes up some downstream code that manually implemented LSN formatting. There's also a bugfix to the logging in wait_lsn, which prints the wrong lsn value.
This commit is contained in:
@@ -4,6 +4,7 @@ use std::fmt;
|
||||
use std::ops::{Add, AddAssign};
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
/// A Postgres LSN (Log Sequence Number), also known as an XLogRecPtr
|
||||
#[derive(Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
|
||||
@@ -108,6 +109,41 @@ impl AddAssign<u64> for Lsn {
|
||||
}
|
||||
}
|
||||
|
||||
/// An [`Lsn`] that can be accessed atomically.
|
||||
pub struct AtomicLsn {
|
||||
inner: AtomicU64,
|
||||
}
|
||||
|
||||
impl AtomicLsn {
|
||||
/// Creates a new atomic `Lsn`.
|
||||
pub fn new(val: u64) -> Self {
|
||||
AtomicLsn {
|
||||
inner: AtomicU64::new(val),
|
||||
}
|
||||
}
|
||||
|
||||
/// Atomically retrieve the `Lsn` value from memory.
|
||||
pub fn load(&self) -> Lsn {
|
||||
Lsn(self.inner.load(Ordering::Acquire))
|
||||
}
|
||||
|
||||
/// Atomically store a new `Lsn` value to memory.
|
||||
pub fn store(&self, lsn: Lsn) {
|
||||
self.inner.store(lsn.0, Ordering::Release);
|
||||
}
|
||||
|
||||
/// Adds to the current value, returning the previous value.
|
||||
///
|
||||
/// This operation will panic on overflow.
|
||||
pub fn fetch_add(&self, val: u64) -> Lsn {
|
||||
let prev = self.inner.fetch_add(val, Ordering::AcqRel);
|
||||
if prev.checked_add(val).is_none() {
|
||||
panic!("AtomicLsn overflow");
|
||||
}
|
||||
Lsn(prev)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user