use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::io;
#[derive(Debug, Clone)]
pub struct TxnEnd {
pub id: i64,
pub timestamp_ms: u64,
pub last_lsn: u64,
pub rep_master_node_id: i32,
pub dtvlsn: i64,
}
impl TxnEnd {
pub fn new(
id: i64,
last_lsn: u64,
rep_master_node_id: i32,
dtvlsn: i64,
) -> Self {
let timestamp_ms = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64;
TxnEnd { id, timestamp_ms, last_lsn, rep_master_node_id, dtvlsn }
}
pub fn has_logged_entries(&self) -> bool {
self.last_lsn != noxu_util::NULL_LSN.as_u64()
}
pub fn log_size(&self) -> usize {
8 + 8 + 8 + 4 + 8 }
pub fn write_to_log(&self, buf: &mut Vec<u8>) {
buf.write_i64::<BigEndian>(self.id).unwrap();
buf.write_u64::<BigEndian>(self.timestamp_ms).unwrap();
buf.write_u64::<BigEndian>(self.last_lsn).unwrap();
buf.write_i32::<BigEndian>(self.rep_master_node_id).unwrap();
buf.write_i64::<BigEndian>(self.dtvlsn).unwrap();
}
pub fn read_from_log(buf: &[u8]) -> io::Result<Self> {
let mut cursor = io::Cursor::new(buf);
let id = cursor.read_i64::<BigEndian>()?;
let timestamp_ms = cursor.read_u64::<BigEndian>()?;
let last_lsn = cursor.read_u64::<BigEndian>()?;
let rep_master_node_id = cursor.read_i32::<BigEndian>()?;
let dtvlsn = cursor.read_i64::<BigEndian>()?;
Ok(TxnEnd { id, timestamp_ms, last_lsn, rep_master_node_id, dtvlsn })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let end = TxnEnd::new(42, 1000, 1, 100);
assert_eq!(end.id, 42);
assert_eq!(end.last_lsn, 1000);
assert_eq!(end.rep_master_node_id, 1);
assert_eq!(end.dtvlsn, 100);
assert!(end.timestamp_ms > 0);
}
#[test]
fn test_has_logged_entries() {
let end1 = TxnEnd::new(1, noxu_util::NULL_LSN.as_u64(), 0, 0);
assert!(!end1.has_logged_entries());
let end2 = TxnEnd::new(1, 1000, 0, 0);
assert!(end2.has_logged_entries());
}
#[test]
fn test_log_size() {
let end = TxnEnd::new(1, 1000, 0, 0);
assert_eq!(end.log_size(), 36);
}
#[test]
fn test_serialization_round_trip() {
let original = TxnEnd::new(12345, 67890, 5, 999);
let mut buf = Vec::new();
original.write_to_log(&mut buf);
assert_eq!(buf.len(), 36);
let deserialized = TxnEnd::read_from_log(&buf).unwrap();
assert_eq!(deserialized.id, original.id);
assert_eq!(deserialized.timestamp_ms, original.timestamp_ms);
assert_eq!(deserialized.last_lsn, original.last_lsn);
assert_eq!(
deserialized.rep_master_node_id,
original.rep_master_node_id
);
assert_eq!(deserialized.dtvlsn, original.dtvlsn);
}
}