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}