LCOV - differential code coverage report
Current view: top level - libs/utils/src - lsn.rs (source / functions) Coverage Total Hit UBC CBC
Current: cd44433dd675caa99df17a61b18949c8387e2242.info Lines: 89.0 % 355 316 39 316
Current Date: 2024-01-09 02:06:09 Functions: 69.9 % 113 79 34 79
Baseline: 66c52a629a0f4a503e193045e0df4c77139e344b.info
Baseline Date: 2024-01-08 15:34:46

           TLA  Line data    Source code
       1                 : #![warn(missing_docs)]
       2                 : 
       3                 : use camino::Utf8Path;
       4                 : use serde::{de::Visitor, Deserialize, Serialize};
       5                 : use std::fmt;
       6                 : use std::ops::{Add, AddAssign};
       7                 : use std::str::FromStr;
       8                 : use std::sync::atomic::{AtomicU64, Ordering};
       9                 : 
      10                 : use crate::seqwait::MonotonicCounter;
      11                 : 
      12                 : /// Transaction log block size in bytes
      13                 : pub const XLOG_BLCKSZ: u32 = 8192;
      14                 : 
      15                 : /// A Postgres LSN (Log Sequence Number), also known as an XLogRecPtr
      16 CBC   640361986 : #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash)]
      17                 : pub struct Lsn(pub u64);
      18                 : 
      19                 : impl Serialize for Lsn {
      20          217242 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
      21          217242 :     where
      22          217242 :         S: serde::Serializer,
      23          217242 :     {
      24          217242 :         if serializer.is_human_readable() {
      25           40069 :             serializer.collect_str(self)
      26                 :         } else {
      27          177173 :             self.0.serialize(serializer)
      28                 :         }
      29          217242 :     }
      30                 : }
      31                 : 
      32                 : impl<'de> Deserialize<'de> for Lsn {
      33         9937681 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
      34         9937681 :     where
      35         9937681 :         D: serde::Deserializer<'de>,
      36         9937681 :     {
      37         9937681 :         struct LsnVisitor {
      38         9937681 :             is_human_readable_deserializer: bool,
      39         9937681 :         }
      40         9937681 : 
      41         9937681 :         impl<'de> Visitor<'de> for LsnVisitor {
      42         9937681 :             type Value = Lsn;
      43         9937681 : 
      44         9937681 :             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
      45               2 :                 if self.is_human_readable_deserializer {
      46         9937681 :                     formatter.write_str(
      47               1 :                         "value in form of hex string({upper_u32_hex}/{lower_u32_hex}) representing u64 integer",
      48               1 :                     )
      49         9937681 :                 } else {
      50         9937681 :                     formatter.write_str("value in form of integer(u64)")
      51         9937681 :                 }
      52         9937681 :             }
      53         9937681 : 
      54         9937681 :             fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
      55         9930667 :             where
      56         9930667 :                 E: serde::de::Error,
      57         9930667 :             {
      58         9930667 :                 Ok(Lsn(v))
      59         9930667 :             }
      60         9937681 : 
      61         9937681 :             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
      62            7012 :             where
      63            7012 :                 E: serde::de::Error,
      64            7012 :             {
      65            7012 :                 Lsn::from_str(v).map_err(|e| E::custom(e))
      66            7012 :             }
      67         9937681 :         }
      68         9937681 : 
      69         9937681 :         if deserializer.is_human_readable() {
      70            7013 :             deserializer.deserialize_str(LsnVisitor {
      71            7013 :                 is_human_readable_deserializer: true,
      72            7013 :             })
      73                 :         } else {
      74         9930668 :             deserializer.deserialize_u64(LsnVisitor {
      75         9930668 :                 is_human_readable_deserializer: false,
      76         9930668 :             })
      77                 :         }
      78         9937681 :     }
      79                 : }
      80                 : 
      81                 : /// Allows (de)serialization of an `Lsn` always as `u64`.
      82                 : ///
      83                 : /// ### Example
      84                 : ///
      85                 : /// ```rust
      86                 : /// # use serde::{Serialize, Deserialize};
      87                 : /// use utils::lsn::Lsn;
      88                 : ///
      89                 : /// #[derive(PartialEq, Serialize, Deserialize, Debug)]
      90                 : /// struct Foo {
      91                 : ///   #[serde(with = "utils::lsn::serde_as_u64")]
      92                 : ///   always_u64: Lsn,
      93                 : /// }
      94                 : ///
      95                 : /// let orig = Foo { always_u64: Lsn(1234) };
      96                 : ///
      97                 : /// let res = serde_json::to_string(&orig).unwrap();
      98                 : /// assert_eq!(res, r#"{"always_u64":1234}"#);
      99                 : ///
     100                 : /// let foo = serde_json::from_str::<Foo>(&res).unwrap();
     101                 : /// assert_eq!(foo, orig);
     102                 : /// ```
     103                 : ///
     104                 : pub mod serde_as_u64 {
     105                 :     use super::Lsn;
     106                 : 
     107                 :     /// Serializes the Lsn as u64 disregarding the human readability of the format.
     108                 :     ///
     109                 :     /// Meant to be used via `#[serde(with = "...")]` or `#[serde(serialize_with = "...")]`.
     110 UBC           0 :     pub fn serialize<S: serde::Serializer>(lsn: &Lsn, serializer: S) -> Result<S::Ok, S::Error> {
     111               0 :         use serde::Serialize;
     112               0 :         lsn.0.serialize(serializer)
     113               0 :     }
     114                 : 
     115                 :     /// Deserializes the Lsn as u64 disregarding the human readability of the format.
     116                 :     ///
     117                 :     /// Meant to be used via `#[serde(with = "...")]` or `#[serde(deserialize_with = "...")]`.
     118 CBC           9 :     pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Lsn, D::Error> {
     119               9 :         use serde::Deserialize;
     120               9 :         u64::deserialize(deserializer).map(Lsn)
     121               9 :     }
     122                 : }
     123                 : 
     124                 : /// We tried to parse an LSN from a string, but failed
     125               1 : #[derive(Debug, PartialEq, Eq, thiserror::Error)]
     126                 : #[error("LsnParseError")]
     127                 : pub struct LsnParseError;
     128                 : 
     129                 : impl Lsn {
     130                 :     /// Maximum possible value for an LSN
     131                 :     pub const MAX: Lsn = Lsn(u64::MAX);
     132                 : 
     133                 :     /// Invalid value for InvalidXLogRecPtr, as defined in xlogdefs.h
     134                 :     pub const INVALID: Lsn = Lsn(0);
     135                 : 
     136                 :     /// Subtract a number, returning None on overflow.
     137         2042709 :     pub fn checked_sub<T: Into<u64>>(self, other: T) -> Option<Lsn> {
     138         2042709 :         let other: u64 = other.into();
     139         2042709 :         self.0.checked_sub(other).map(Lsn)
     140         2042709 :     }
     141                 : 
     142                 :     /// Subtract a number, returning the difference as i128 to avoid overflow.
     143          565118 :     pub fn widening_sub<T: Into<u64>>(self, other: T) -> i128 {
     144          565118 :         let other: u64 = other.into();
     145          565118 :         i128::from(self.0) - i128::from(other)
     146          565118 :     }
     147                 : 
     148                 :     /// Parse an LSN from a filename in the form `0000000000000000`
     149 UBC           0 :     pub fn from_filename<F>(filename: F) -> Result<Self, LsnParseError>
     150               0 :     where
     151               0 :         F: AsRef<Utf8Path>,
     152               0 :     {
     153               0 :         Lsn::from_hex(filename.as_ref().as_str())
     154               0 :     }
     155                 : 
     156                 :     /// Parse an LSN from a string in the form `0000000000000000`
     157 CBC      138125 :     pub fn from_hex<S>(s: S) -> Result<Self, LsnParseError>
     158          138125 :     where
     159          138125 :         S: AsRef<str>,
     160          138125 :     {
     161          138125 :         let s: &str = s.as_ref();
     162          138125 :         let n = u64::from_str_radix(s, 16).or(Err(LsnParseError))?;
     163          107583 :         Ok(Lsn(n))
     164          138125 :     }
     165                 : 
     166                 :     /// Compute the offset into a segment
     167                 :     #[inline]
     168       133502477 :     pub fn segment_offset(self, seg_sz: usize) -> usize {
     169       133502477 :         (self.0 % seg_sz as u64) as usize
     170       133502477 :     }
     171                 : 
     172                 :     /// Compute LSN of the segment start.
     173                 :     #[inline]
     174            1408 :     pub fn segment_lsn(self, seg_sz: usize) -> Lsn {
     175            1408 :         Lsn(self.0 - (self.0 % seg_sz as u64))
     176            1408 :     }
     177                 : 
     178                 :     /// Compute the segment number
     179                 :     #[inline]
     180         1246728 :     pub fn segment_number(self, seg_sz: usize) -> u64 {
     181         1246728 :         self.0 / seg_sz as u64
     182         1246728 :     }
     183                 : 
     184                 :     /// Compute the offset into a block
     185                 :     #[inline]
     186       131194913 :     pub fn block_offset(self) -> u64 {
     187       131194913 :         const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
     188       131194913 :         self.0 % BLCKSZ
     189       131194913 :     }
     190                 : 
     191                 :     /// Compute the block offset of the first byte of this Lsn within this
     192                 :     /// segment
     193                 :     #[inline]
     194             559 :     pub fn page_lsn(self) -> Lsn {
     195             559 :         Lsn(self.0 - self.block_offset())
     196             559 :     }
     197                 : 
     198                 :     /// Compute the block offset of the first byte of this Lsn within this
     199                 :     /// segment
     200                 :     #[inline]
     201             559 :     pub fn page_offset_in_segment(self, seg_sz: usize) -> u64 {
     202             559 :         (self.0 - self.block_offset()) - self.segment_lsn(seg_sz).0
     203             559 :     }
     204                 : 
     205                 :     /// Compute the bytes remaining in this block
     206                 :     ///
     207                 :     /// If the LSN is already at the block boundary, it will return `XLOG_BLCKSZ`.
     208                 :     #[inline]
     209       129360538 :     pub fn remaining_in_block(self) -> u64 {
     210       129360538 :         const BLCKSZ: u64 = XLOG_BLCKSZ as u64;
     211       129360538 :         BLCKSZ - (self.0 % BLCKSZ)
     212       129360538 :     }
     213                 : 
     214                 :     /// Compute the bytes remaining to fill a chunk of some size
     215                 :     ///
     216                 :     /// If the LSN is already at the chunk boundary, it will return 0.
     217             730 :     pub fn calc_padding<T: Into<u64>>(self, sz: T) -> u64 {
     218             730 :         let sz: u64 = sz.into();
     219             730 :         // By using wrapping_sub, we can subtract first and then mod second.
     220             730 :         // If it's done the other way around, then we would return a full
     221             730 :         // chunk size if we're already at the chunk boundary.
     222             730 :         // (Regular subtraction will panic on overflow in debug builds.)
     223             730 :         (sz.wrapping_sub(self.0)) % sz
     224             730 :     }
     225                 : 
     226                 :     /// Align LSN on 8-byte boundary (alignment of WAL records).
     227       222392268 :     pub fn align(&self) -> Lsn {
     228       222392268 :         Lsn((self.0 + 7) & !7)
     229       222392268 :     }
     230                 : 
     231                 :     /// Align LSN on 8-byte boundary (alignment of WAL records).
     232        98494262 :     pub fn is_aligned(&self) -> bool {
     233        98494262 :         *self == self.align()
     234        98494262 :     }
     235                 : 
     236                 :     /// Return if the LSN is valid
     237                 :     /// mimics postgres XLogRecPtrIsInvalid macro
     238        12983166 :     pub fn is_valid(self) -> bool {
     239        12983166 :         self != Lsn::INVALID
     240        12983166 :     }
     241                 : }
     242                 : 
     243                 : impl From<u64> for Lsn {
     244         5338272 :     fn from(n: u64) -> Self {
     245         5338272 :         Lsn(n)
     246         5338272 :     }
     247                 : }
     248                 : 
     249                 : impl From<Lsn> for u64 {
     250         7462645 :     fn from(lsn: Lsn) -> u64 {
     251         7462645 :         lsn.0
     252         7462645 :     }
     253                 : }
     254                 : 
     255                 : impl FromStr for Lsn {
     256                 :     type Err = LsnParseError;
     257                 : 
     258                 :     /// Parse an LSN from a string in the form `00000000/00000000`
     259                 :     ///
     260                 :     /// If the input string is missing the '/' character, then use `Lsn::from_hex`
     261            9463 :     fn from_str(s: &str) -> Result<Self, Self::Err> {
     262            9463 :         let mut splitter = s.trim().split('/');
     263            9463 :         if let (Some(left), Some(right), None) = (splitter.next(), splitter.next(), splitter.next())
     264                 :         {
     265            9463 :             let left_num = u32::from_str_radix(left, 16).map_err(|_| LsnParseError)?;
     266            9460 :             let right_num = u32::from_str_radix(right, 16).map_err(|_| LsnParseError)?;
     267            9458 :             Ok(Lsn((left_num as u64) << 32 | right_num as u64))
     268                 :         } else {
     269 UBC           0 :             Err(LsnParseError)
     270                 :         }
     271 CBC        9463 :     }
     272                 : }
     273                 : 
     274                 : impl fmt::Display for Lsn {
     275         4628681 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     276         4628681 :         write!(f, "{:X}/{:X}", self.0 >> 32, self.0 & 0xffffffff)
     277         4628681 :     }
     278                 : }
     279                 : 
     280                 : impl fmt::Debug for Lsn {
     281           17098 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     282           17098 :         write!(f, "{:X}/{:X}", self.0 >> 32, self.0 & 0xffffffff)
     283           17098 :     }
     284                 : }
     285                 : 
     286                 : impl Add<u64> for Lsn {
     287                 :     type Output = Lsn;
     288                 : 
     289        53293076 :     fn add(self, other: u64) -> Self::Output {
     290        53293076 :         // panic if the addition overflows.
     291        53293076 :         Lsn(self.0.checked_add(other).unwrap())
     292        53293076 :     }
     293                 : }
     294                 : 
     295                 : impl AddAssign<u64> for Lsn {
     296       255410462 :     fn add_assign(&mut self, other: u64) {
     297       255410462 :         // panic if the addition overflows.
     298       255410462 :         self.0 = self.0.checked_add(other).unwrap();
     299       255410462 :     }
     300                 : }
     301                 : 
     302                 : /// An [`Lsn`] that can be accessed atomically.
     303                 : pub struct AtomicLsn {
     304                 :     inner: AtomicU64,
     305                 : }
     306                 : 
     307                 : impl AtomicLsn {
     308                 :     /// Creates a new atomic `Lsn`.
     309            4453 :     pub fn new(val: u64) -> Self {
     310            4453 :         AtomicLsn {
     311            4453 :             inner: AtomicU64::new(val),
     312            4453 :         }
     313            4453 :     }
     314                 : 
     315                 :     /// Atomically retrieve the `Lsn` value from memory.
     316         1735944 :     pub fn load(&self) -> Lsn {
     317         1735944 :         Lsn(self.inner.load(Ordering::Acquire))
     318         1735944 :     }
     319                 : 
     320                 :     /// Atomically store a new `Lsn` value to memory.
     321           12686 :     pub fn store(&self, lsn: Lsn) {
     322           12686 :         self.inner.store(lsn.0, Ordering::Release);
     323           12686 :     }
     324                 : 
     325                 :     /// Adds to the current value, returning the previous value.
     326                 :     ///
     327                 :     /// This operation will panic on overflow.
     328               1 :     pub fn fetch_add(&self, val: u64) -> Lsn {
     329               1 :         let prev = self.inner.fetch_add(val, Ordering::AcqRel);
     330               1 :         assert!(prev.checked_add(val).is_some(), "AtomicLsn overflow");
     331               1 :         Lsn(prev)
     332               1 :     }
     333                 : 
     334                 :     /// Atomically sets the Lsn to the max of old and new value, returning the old value.
     335          577773 :     pub fn fetch_max(&self, lsn: Lsn) -> Lsn {
     336          577773 :         let prev = self.inner.fetch_max(lsn.0, Ordering::AcqRel);
     337          577773 :         Lsn(prev)
     338          577773 :     }
     339                 : }
     340                 : 
     341                 : impl From<Lsn> for AtomicLsn {
     342             951 :     fn from(lsn: Lsn) -> Self {
     343             951 :         Self::new(lsn.0)
     344             951 :     }
     345                 : }
     346                 : 
     347                 : /// Pair of LSN's pointing to the end of the last valid record and previous one
     348 UBC           0 : #[derive(Debug, Clone, Copy)]
     349                 : pub struct RecordLsn {
     350                 :     /// LSN at the end of the current record
     351                 :     pub last: Lsn,
     352                 :     /// LSN at the end of the previous record
     353                 :     pub prev: Lsn,
     354                 : }
     355                 : 
     356                 : /// Expose `self.last` as counter to be able to use RecordLsn in SeqWait
     357                 : impl MonotonicCounter<Lsn> for RecordLsn {
     358 CBC    48222384 :     fn cnt_advance(&mut self, lsn: Lsn) {
     359        48222384 :         assert!(self.last <= lsn);
     360        48222384 :         let new_prev = self.last;
     361        48222384 :         self.last = lsn;
     362        48222384 :         self.prev = new_prev;
     363        48222384 :     }
     364        50782237 :     fn cnt_value(&self) -> Lsn {
     365        50782237 :         self.last
     366        50782237 :     }
     367                 : }
     368                 : 
     369                 : /// Implements  [`rand::distributions::uniform::UniformSampler`] so we can sample [`Lsn`]s.
     370                 : ///
     371                 : /// This is used by the `pagebench` pageserver benchmarking tool.
     372                 : pub struct LsnSampler(<u64 as rand::distributions::uniform::SampleUniform>::Sampler);
     373                 : 
     374                 : impl rand::distributions::uniform::SampleUniform for Lsn {
     375                 :     type Sampler = LsnSampler;
     376                 : }
     377                 : 
     378                 : impl rand::distributions::uniform::UniformSampler for LsnSampler {
     379                 :     type X = Lsn;
     380                 : 
     381 UBC           0 :     fn new<B1, B2>(low: B1, high: B2) -> Self
     382               0 :     where
     383               0 :         B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
     384               0 :         B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
     385               0 :     {
     386               0 :         Self(
     387               0 :             <u64 as rand::distributions::uniform::SampleUniform>::Sampler::new(
     388               0 :                 low.borrow().0,
     389               0 :                 high.borrow().0,
     390               0 :             ),
     391               0 :         )
     392               0 :     }
     393                 : 
     394               0 :     fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
     395               0 :     where
     396               0 :         B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
     397               0 :         B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
     398               0 :     {
     399               0 :         Self(
     400               0 :             <u64 as rand::distributions::uniform::SampleUniform>::Sampler::new_inclusive(
     401               0 :                 low.borrow().0,
     402               0 :                 high.borrow().0,
     403               0 :             ),
     404               0 :         )
     405               0 :     }
     406                 : 
     407               0 :     fn sample<R: rand::prelude::Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
     408               0 :         Lsn(self.0.sample(rng))
     409               0 :     }
     410                 : }
     411                 : 
     412                 : #[cfg(test)]
     413                 : mod tests {
     414                 :     use crate::bin_ser::BeSer;
     415                 : 
     416                 :     use super::*;
     417                 : 
     418                 :     use serde::ser::Serialize;
     419                 :     use serde_assert::{Deserializer, Serializer, Token, Tokens};
     420                 : 
     421 CBC           1 :     #[test]
     422               1 :     fn test_lsn_strings() {
     423               1 :         assert_eq!("12345678/AAAA5555".parse(), Ok(Lsn(0x12345678AAAA5555)));
     424               1 :         assert_eq!("aaaa/bbbb".parse(), Ok(Lsn(0x0000AAAA0000BBBB)));
     425               1 :         assert_eq!("1/A".parse(), Ok(Lsn(0x000000010000000A)));
     426               1 :         assert_eq!("0/0".parse(), Ok(Lsn(0)));
     427               1 :         "ABCDEFG/12345678".parse::<Lsn>().unwrap_err();
     428               1 :         "123456789/AAAA5555".parse::<Lsn>().unwrap_err();
     429               1 :         "12345678/AAAA55550".parse::<Lsn>().unwrap_err();
     430               1 :         "-1/0".parse::<Lsn>().unwrap_err();
     431               1 :         "1/-1".parse::<Lsn>().unwrap_err();
     432               1 : 
     433               1 :         assert_eq!(format!("{}", Lsn(0x12345678AAAA5555)), "12345678/AAAA5555");
     434               1 :         assert_eq!(format!("{}", Lsn(0x000000010000000A)), "1/A");
     435                 : 
     436               1 :         assert_eq!(
     437               1 :             Lsn::from_hex("12345678AAAA5555"),
     438               1 :             Ok(Lsn(0x12345678AAAA5555))
     439               1 :         );
     440               1 :         assert_eq!(Lsn::from_hex("0"), Ok(Lsn(0)));
     441               1 :         assert_eq!(Lsn::from_hex("F12345678AAAA5555"), Err(LsnParseError));
     442                 : 
     443               1 :         let expected_lsn = Lsn(0x3C490F8);
     444               1 :         assert_eq!(" 0/3C490F8".parse(), Ok(expected_lsn));
     445               1 :         assert_eq!("0/3C490F8 ".parse(), Ok(expected_lsn));
     446               1 :         assert_eq!(" 0/3C490F8 ".parse(), Ok(expected_lsn));
     447               1 :     }
     448                 : 
     449               1 :     #[test]
     450               1 :     fn test_lsn_math() {
     451               1 :         assert_eq!(Lsn(1234) + 11u64, Lsn(1245));
     452                 : 
     453               1 :         assert_eq!(
     454               1 :             {
     455               1 :                 let mut lsn = Lsn(1234);
     456               1 :                 lsn += 11u64;
     457               1 :                 lsn
     458               1 :             },
     459               1 :             Lsn(1245)
     460               1 :         );
     461                 : 
     462               1 :         assert_eq!(Lsn(1234).checked_sub(1233u64), Some(Lsn(1)));
     463               1 :         assert_eq!(Lsn(1234).checked_sub(1235u64), None);
     464                 : 
     465               1 :         assert_eq!(Lsn(1235).widening_sub(1234u64), 1);
     466               1 :         assert_eq!(Lsn(1234).widening_sub(1235u64), -1);
     467               1 :         assert_eq!(Lsn(u64::MAX).widening_sub(0u64), i128::from(u64::MAX));
     468               1 :         assert_eq!(Lsn(0).widening_sub(u64::MAX), -i128::from(u64::MAX));
     469                 : 
     470               1 :         let seg_sz: usize = 16 * 1024 * 1024;
     471               1 :         assert_eq!(Lsn(0x1000007).segment_offset(seg_sz), 7);
     472               1 :         assert_eq!(Lsn(0x1000007).segment_number(seg_sz), 1u64);
     473                 : 
     474               1 :         assert_eq!(Lsn(0x4007).block_offset(), 7u64);
     475               1 :         assert_eq!(Lsn(0x4000).block_offset(), 0u64);
     476               1 :         assert_eq!(Lsn(0x4007).remaining_in_block(), 8185u64);
     477               1 :         assert_eq!(Lsn(0x4000).remaining_in_block(), 8192u64);
     478                 : 
     479               1 :         assert_eq!(Lsn(0xffff01).calc_padding(seg_sz as u64), 255u64);
     480               1 :         assert_eq!(Lsn(0x2000000).calc_padding(seg_sz as u64), 0u64);
     481               1 :         assert_eq!(Lsn(0xffff01).calc_padding(8u32), 7u64);
     482               1 :         assert_eq!(Lsn(0xffff00).calc_padding(8u32), 0u64);
     483               1 :     }
     484                 : 
     485               1 :     #[test]
     486               1 :     fn test_atomic_lsn() {
     487               1 :         let lsn = AtomicLsn::new(0);
     488               1 :         assert_eq!(lsn.fetch_add(1234), Lsn(0));
     489               1 :         assert_eq!(lsn.load(), Lsn(1234));
     490               1 :         lsn.store(Lsn(5678));
     491               1 :         assert_eq!(lsn.load(), Lsn(5678));
     492                 : 
     493               1 :         assert_eq!(lsn.fetch_max(Lsn(6000)), Lsn(5678));
     494               1 :         assert_eq!(lsn.fetch_max(Lsn(5000)), Lsn(6000));
     495               1 :     }
     496                 : 
     497               1 :     #[test]
     498               1 :     fn test_lsn_serde() {
     499               1 :         let original_lsn = Lsn(0x0123456789abcdef);
     500               1 :         let expected_readable_tokens = Tokens(vec![Token::U64(0x0123456789abcdef)]);
     501               1 :         let expected_non_readable_tokens =
     502               1 :             Tokens(vec![Token::Str(String::from("1234567/89ABCDEF"))]);
     503               1 : 
     504               1 :         // Testing human_readable ser/de
     505               1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     506               1 :         let readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     507               1 :         assert_eq!(readable_ser_tokens, expected_readable_tokens);
     508                 : 
     509               1 :         let mut deserializer = Deserializer::builder()
     510               1 :             .is_human_readable(false)
     511               1 :             .tokens(readable_ser_tokens)
     512               1 :             .build();
     513               1 :         let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
     514               1 :         assert_eq!(des_lsn, original_lsn);
     515                 : 
     516                 :         // Testing NON human_readable ser/de
     517               1 :         let serializer = Serializer::builder().is_human_readable(true).build();
     518               1 :         let non_readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     519               1 :         assert_eq!(non_readable_ser_tokens, expected_non_readable_tokens);
     520                 : 
     521               1 :         let mut deserializer = Deserializer::builder()
     522               1 :             .is_human_readable(true)
     523               1 :             .tokens(non_readable_ser_tokens)
     524               1 :             .build();
     525               1 :         let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
     526               1 :         assert_eq!(des_lsn, original_lsn);
     527                 : 
     528                 :         // Testing mismatching ser/de
     529               1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     530               1 :         let non_readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     531               1 : 
     532               1 :         let mut deserializer = Deserializer::builder()
     533               1 :             .is_human_readable(true)
     534               1 :             .tokens(non_readable_ser_tokens)
     535               1 :             .build();
     536               1 :         Lsn::deserialize(&mut deserializer).unwrap_err();
     537               1 : 
     538               1 :         let serializer = Serializer::builder().is_human_readable(true).build();
     539               1 :         let readable_ser_tokens = original_lsn.serialize(&serializer).unwrap();
     540               1 : 
     541               1 :         let mut deserializer = Deserializer::builder()
     542               1 :             .is_human_readable(false)
     543               1 :             .tokens(readable_ser_tokens)
     544               1 :             .build();
     545               1 :         Lsn::deserialize(&mut deserializer).unwrap_err();
     546               1 :     }
     547                 : 
     548               1 :     #[test]
     549               1 :     fn test_lsn_ensure_roundtrip() {
     550               1 :         let original_lsn = Lsn(0xaaaabbbb);
     551               1 : 
     552               1 :         let serializer = Serializer::builder().is_human_readable(false).build();
     553               1 :         let ser_tokens = original_lsn.serialize(&serializer).unwrap();
     554               1 : 
     555               1 :         let mut deserializer = Deserializer::builder()
     556               1 :             .is_human_readable(false)
     557               1 :             .tokens(ser_tokens)
     558               1 :             .build();
     559               1 : 
     560               1 :         let des_lsn = Lsn::deserialize(&mut deserializer).unwrap();
     561               1 :         assert_eq!(des_lsn, original_lsn);
     562               1 :     }
     563                 : 
     564               1 :     #[test]
     565               1 :     fn test_lsn_bincode_serde() {
     566               1 :         let lsn = Lsn(0x0123456789abcdef);
     567               1 :         let expected_bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
     568               1 : 
     569               1 :         let ser_bytes = lsn.ser().unwrap();
     570               1 :         assert_eq!(ser_bytes, expected_bytes);
     571                 : 
     572               1 :         let des_lsn = Lsn::des(&ser_bytes).unwrap();
     573               1 :         assert_eq!(des_lsn, lsn);
     574               1 :     }
     575                 : 
     576               1 :     #[test]
     577               1 :     fn test_lsn_bincode_ensure_roundtrip() {
     578               1 :         let original_lsn = Lsn(0x01_02_03_04_05_06_07_08);
     579               1 :         let expected_bytes = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
     580               1 : 
     581               1 :         let ser_bytes = original_lsn.ser().unwrap();
     582               1 :         assert_eq!(ser_bytes, expected_bytes);
     583                 : 
     584               1 :         let des_lsn = Lsn::des(&ser_bytes).unwrap();
     585               1 :         assert_eq!(des_lsn, original_lsn);
     586               1 :     }
     587                 : }
        

Generated by: LCOV version 2.1-beta