use std::fs;
use std::path::Path;
use crate::error::DbResult;
pub struct ReplicationCursor {
pub shard_id: u8,
pub last_gsn: u64,
pub file_id: u32,
pub file_offset: u64,
}
const CURSOR_FILE: &str = "repl.cursor";
const CURSOR_SIZE: usize = 24;
impl ReplicationCursor {
pub fn new(shard_id: u8) -> Self {
Self {
shard_id,
last_gsn: 0,
file_id: 0,
file_offset: 0,
}
}
pub fn load(shard_id: u8, shard_dir: &Path) -> DbResult<Option<Self>> {
let path = shard_dir.join(CURSOR_FILE);
if !path.exists() {
return Ok(None);
}
let data = fs::read(&path)?;
if data.len() < CURSOR_SIZE {
return Ok(None);
}
let last_gsn = u64::from_le_bytes(data[0..8].try_into().expect("8 bytes"));
let file_id = u32::from_le_bytes(data[8..12].try_into().expect("4 bytes"));
let file_offset = u64::from_le_bytes(data[12..20].try_into().expect("8 bytes"));
Ok(Some(Self {
shard_id,
last_gsn,
file_id,
file_offset,
}))
}
pub fn save(&self, shard_dir: &Path) -> DbResult<()> {
let path = shard_dir.join(CURSOR_FILE);
let mut buf = [0u8; CURSOR_SIZE];
buf[0..8].copy_from_slice(&self.last_gsn.to_le_bytes());
buf[8..12].copy_from_slice(&self.file_id.to_le_bytes());
buf[12..20].copy_from_slice(&self.file_offset.to_le_bytes());
fs::write(&path, buf)?;
Ok(())
}
pub fn advance(&mut self, gsn: u64, file_id: u32, file_offset: u64) {
self.last_gsn = gsn;
self.file_id = file_id;
self.file_offset = file_offset;
}
}