tikv_client/
timestamp.rs

1//! A timestamp returned from the timestamp oracle.
2//!
3//! The version used in transactions can be converted from a timestamp.
4//! The lower 18 (PHYSICAL_SHIFT_BITS) bits are the logical part of the timestamp.
5//! The higher bits of the version are the physical part of the timestamp.
6
7use std::convert::TryInto;
8
9pub use crate::proto::pdpb::Timestamp;
10
11const PHYSICAL_SHIFT_BITS: i64 = 18;
12const LOGICAL_MASK: i64 = (1 << PHYSICAL_SHIFT_BITS) - 1;
13
14/// A helper trait to convert a Timestamp to and from an u64.
15///
16/// Currently the only implmentation of this trait is [`Timestamp`](Timestamp) in TiKV.
17/// It contains a physical part (first 46 bits) and a logical part (last 18 bits).
18pub trait TimestampExt: Sized {
19    /// Convert the timestamp to u64.
20    fn version(&self) -> u64;
21    /// Convert u64 to a timestamp.
22    fn from_version(version: u64) -> Self;
23    /// Convert u64 to an optional timestamp, where `0` represents no timestamp.
24    fn try_from_version(version: u64) -> Option<Self>;
25}
26
27impl TimestampExt for Timestamp {
28    fn version(&self) -> u64 {
29        ((self.physical << PHYSICAL_SHIFT_BITS) + self.logical)
30            .try_into()
31            .expect("Overflow converting timestamp to version")
32    }
33
34    fn from_version(version: u64) -> Self {
35        let version = version as i64;
36        Self {
37            physical: version >> PHYSICAL_SHIFT_BITS,
38            logical: version & LOGICAL_MASK,
39            // Now we only support global transactions: suffix_bits: 0,
40            ..Default::default()
41        }
42    }
43
44    fn try_from_version(version: u64) -> Option<Self> {
45        if version == 0 {
46            None
47        } else {
48            Some(Self::from_version(version))
49        }
50    }
51}