Skip to main content

noxu_txn/
write_lock_info.rs

1//! Undo information for write locks.
2//!
3
4/// Information needed to undo write operations if a transaction aborts.
5///
6/// Stores the "abort version"  -  the state of a record before this txn modified it.
7/// This allows the transaction to restore the previous state on abort.
8///
9///
10#[derive(Debug, Clone)]
11pub struct WriteLockInfo {
12    /// LSN of the record's abort version.
13    pub abort_lsn: u64,
14
15    /// Whether the abort version is a known-deleted record.
16    pub abort_known_deleted: bool,
17
18    /// Key of the abort version (if key updates allowed).
19    pub abort_key: Option<Vec<u8>>,
20
21    /// Data of the abort version (if embedded in BIN).
22    pub abort_data: Option<Vec<u8>>,
23
24    /// VLSN of the abort version.
25    pub abort_vlsn: i64,
26
27    /// On-disk size of the abort version.
28    pub abort_log_size: i32,
29
30    /// Expiration time of the abort version.
31    pub abort_expiration: i32,
32
33    /// Whether expiration is in hours (true) or days (false).
34    pub abort_expiration_in_hours: bool,
35
36    /// True if the LSN has never been locked before by this Txn.
37    ///
38    /// Per the: "True if this locker has never had this LSN locked, is false otherwise.
39    /// This is used to determine if the locker must add undo information for a write lock."
40    pub never_locked: bool,
41
42    /// Database ID of the database that was modified.
43    ///
44    /// Stored so that `Txn::abort()` can route each `UndoRecord` to the
45    /// correct database's B-tree.
46    pub database_id: u64,
47}
48
49impl WriteLockInfo {
50    /// Creates a new WriteLockInfo with default abort version values.
51    pub fn new() -> Self {
52        Self {
53            abort_lsn: noxu_util::NULL_LSN.as_u64(),
54            abort_known_deleted: false,
55            abort_key: None,
56            abort_data: None,
57            abort_vlsn: -1,
58            abort_log_size: 0,
59            abort_expiration: 0,
60            abort_expiration_in_hours: false,
61            never_locked: true,
62            database_id: 0,
63        }
64    }
65
66    /// Copies all abort information from another WriteLockInfo.
67    ///
68    ///
69    pub fn copy_all_info(&mut self, from: &WriteLockInfo) {
70        self.abort_lsn = from.abort_lsn;
71        self.abort_known_deleted = from.abort_known_deleted;
72        self.abort_key = from.abort_key.clone();
73        self.abort_data = from.abort_data.clone();
74        self.abort_vlsn = from.abort_vlsn;
75        self.abort_log_size = from.abort_log_size;
76        self.abort_expiration = from.abort_expiration;
77        self.abort_expiration_in_hours = from.abort_expiration_in_hours;
78        self.never_locked = from.never_locked;
79        self.database_id = from.database_id;
80    }
81
82    /// Sets the abort information from a log entry.
83    ///
84    ///
85    pub fn set_abort_info(
86        &mut self,
87        abort_lsn: u64,
88        abort_key: Option<Vec<u8>>,
89        abort_data: Option<Vec<u8>>,
90        abort_vlsn: i64,
91        abort_log_size: i32,
92        abort_known_deleted: bool,
93        abort_expiration: i32,
94        abort_expiration_in_hours: bool,
95    ) {
96        self.abort_lsn = abort_lsn;
97        self.abort_key = abort_key;
98        self.abort_data = abort_data;
99        self.abort_vlsn = abort_vlsn;
100        self.abort_log_size = abort_log_size;
101        self.abort_known_deleted = abort_known_deleted;
102        self.abort_expiration = abort_expiration;
103        self.abort_expiration_in_hours = abort_expiration_in_hours;
104    }
105
106    /// Returns true if this represents a NULL abort LSN.
107    pub fn is_null_abort_lsn(&self) -> bool {
108        self.abort_lsn == noxu_util::NULL_LSN.as_u64()
109    }
110}
111
112impl Default for WriteLockInfo {
113    fn default() -> Self {
114        Self::new()
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn test_new() {
124        let info = WriteLockInfo::new();
125        assert_eq!(info.abort_lsn, noxu_util::NULL_LSN.as_u64());
126        assert!(!info.abort_known_deleted);
127        assert!(info.abort_key.is_none());
128        assert!(info.abort_data.is_none());
129        assert_eq!(info.abort_vlsn, -1);
130        assert_eq!(info.abort_log_size, 0);
131        assert_eq!(info.abort_expiration, 0);
132        assert!(!info.abort_expiration_in_hours);
133        assert!(info.never_locked);
134    }
135
136    #[test]
137    fn test_copy_all_info() {
138        let mut source = WriteLockInfo::new();
139        source.abort_lsn = 12345;
140        source.abort_known_deleted = true;
141        source.abort_key = Some(vec![1, 2, 3]);
142        source.abort_data = Some(vec![4, 5, 6]);
143        source.abort_vlsn = 100;
144        source.abort_log_size = 42;
145        source.abort_expiration = 86400;
146        source.abort_expiration_in_hours = true;
147        source.never_locked = false;
148
149        let mut dest = WriteLockInfo::new();
150        dest.copy_all_info(&source);
151
152        assert_eq!(dest.abort_lsn, 12345);
153        assert!(dest.abort_known_deleted);
154        assert_eq!(dest.abort_key, Some(vec![1, 2, 3]));
155        assert_eq!(dest.abort_data, Some(vec![4, 5, 6]));
156        assert_eq!(dest.abort_vlsn, 100);
157        assert_eq!(dest.abort_log_size, 42);
158        assert_eq!(dest.abort_expiration, 86400);
159        assert!(dest.abort_expiration_in_hours);
160        assert!(!dest.never_locked);
161    }
162
163    #[test]
164    fn test_set_abort_info() {
165        let mut info = WriteLockInfo::new();
166        info.set_abort_info(
167            99999,
168            Some(vec![10, 20]),
169            Some(vec![30, 40]),
170            200,
171            128,
172            true,
173            3600,
174            false,
175        );
176
177        assert_eq!(info.abort_lsn, 99999);
178        assert_eq!(info.abort_key, Some(vec![10, 20]));
179        assert_eq!(info.abort_data, Some(vec![30, 40]));
180        assert_eq!(info.abort_vlsn, 200);
181        assert_eq!(info.abort_log_size, 128);
182        assert!(info.abort_known_deleted);
183        assert_eq!(info.abort_expiration, 3600);
184        assert!(!info.abort_expiration_in_hours);
185    }
186
187    #[test]
188    fn test_is_null_abort_lsn() {
189        let info = WriteLockInfo::new();
190        assert!(info.is_null_abort_lsn());
191
192        let mut info2 = WriteLockInfo::new();
193        info2.abort_lsn = 12345;
194        assert!(!info2.is_null_abort_lsn());
195    }
196}