1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.

mod point_getter;
mod reader;
mod scanner;

pub use self::point_getter::{PointGetter, PointGetterBuilder};
#[cfg(test)]
pub use self::reader::tests as reader_tests;
pub use self::reader::{MvccReader, SnapshotReader};
pub use self::scanner::test_util;
pub use self::scanner::{
    has_data_in_range, seek_for_valid_write, DeltaScanner, EntryScanner, Scanner, ScannerBuilder,
};

use txn_types::{TimeStamp, Write, WriteType};

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum NewerTsCheckState {
    Unknown,
    Met,
    NotMetYet,
}

/// The result of `get_txn_commit_record`, which is used to get the status of a specified
/// transaction from write cf.
#[derive(Debug)]
pub enum TxnCommitRecord {
    /// The commit record of the given transaction is not found. But it's possible that there's
    /// another transaction's commit record, whose `commit_ts` equals to the current transaction's
    /// `start_ts`. That kind of record will be returned via the `overlapped_write` field.
    /// In this case, if the current transaction is to be rolled back, the `overlapped_write` must not
    /// be overwritten.
    None {
        overlapped_write: Option<OverlappedWrite>,
    },
    /// Found the transaction's write record.
    SingleRecord { commit_ts: TimeStamp, write: Write },
    /// The transaction's status is found in another transaction's record's `overlapped_rollback`
    /// field. This may happen when the current transaction's `start_ts` is the same as the
    /// `commit_ts` of another transaction on this key.
    OverlappedRollback { commit_ts: TimeStamp },
}

#[derive(Clone, Debug)]
pub struct OverlappedWrite {
    pub write: Write,
    /// GC fence for `overlapped_write`. PTAL at `txn_types::Write::gc_fence`.
    pub gc_fence: TimeStamp,
}

impl TxnCommitRecord {
    pub fn exist(&self) -> bool {
        match self {
            Self::None { .. } => false,
            Self::SingleRecord { .. } | Self::OverlappedRollback { .. } => true,
        }
    }

    pub fn info(&self) -> Option<(TimeStamp, WriteType)> {
        match self {
            Self::None { .. } => None,
            Self::SingleRecord { commit_ts, write } => Some((*commit_ts, write.write_type)),
            Self::OverlappedRollback { commit_ts } => Some((*commit_ts, WriteType::Rollback)),
        }
    }

    pub fn unwrap_single_record(self) -> (TimeStamp, WriteType) {
        match self {
            Self::SingleRecord { commit_ts, write } => (commit_ts, write.write_type),
            _ => panic!("not a single record: {:?}", self),
        }
    }

    pub fn unwrap_overlapped_rollback(self) -> TimeStamp {
        match self {
            Self::OverlappedRollback { commit_ts } => commit_ts,
            _ => panic!("not an overlapped rollback record: {:?}", self),
        }
    }

    pub fn unwrap_none(self) -> Option<OverlappedWrite> {
        match self {
            Self::None { overlapped_write } => overlapped_write,
            _ => panic!("txn record found but not expected: {:?}", self),
        }
    }
}