montana/Montana-Protocol/Code/crates/montana-node/src/clock.rs

86 lines
2.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use crate::identity::NodeError;
pub const CURRENT_WINDOW_FILE: &str = "current_window.bin";
// Layout v1 (16 байт):
// [0..4] magic = b"mtcw"
// [4] version = 1
// [5..8] reserved = 0 (выравнивание + future flags)
// [8..16] window u64 LE
// Legacy v0 (8 байт): только window u64 LE без magic. На load auto-upgrade:
// распарсить как v0, следующий save запишет уже в v1.
const MAGIC: &[u8; 4] = b"mtcw";
const VERSION: u8 = 1;
const FILE_SIZE_V1: usize = 16;
const FILE_SIZE_V0: usize = 8;
pub fn meta_dir(data_dir: &Path) -> PathBuf {
data_dir.join("meta")
}
pub fn current_window_path(data_dir: &Path) -> PathBuf {
meta_dir(data_dir).join(CURRENT_WINDOW_FILE)
}
pub fn load_current_window(data_dir: &Path) -> Result<u64, NodeError> {
let path = current_window_path(data_dir);
if !path.exists() {
return Ok(0);
}
let bytes = fs::read(&path)?;
match bytes.len() {
FILE_SIZE_V1 => {
if &bytes[0..4] != MAGIC.as_slice() {
return Err(NodeError::InvalidMagic);
}
if bytes[4] != VERSION {
return Err(NodeError::UnsupportedVersion(bytes[4]));
}
let mut buf = [0u8; 8];
buf.copy_from_slice(&bytes[8..16]);
Ok(u64::from_le_bytes(buf))
},
FILE_SIZE_V0 => {
// Legacy без magic. Парсим как u64 LE; следующий save запишет v1.
let mut buf = [0u8; 8];
buf.copy_from_slice(&bytes);
Ok(u64::from_le_bytes(buf))
},
actual => Err(NodeError::CorruptedSize {
expected: FILE_SIZE_V1,
actual,
}),
}
}
pub fn save_current_window(data_dir: &Path, window: u64) -> Result<(), NodeError> {
fs::create_dir_all(meta_dir(data_dir))?;
let path = current_window_path(data_dir);
let tmp = path.with_extension("bin.tmp");
let mut bytes = [0u8; FILE_SIZE_V1];
bytes[0..4].copy_from_slice(MAGIC);
bytes[4] = VERSION;
bytes[8..16].copy_from_slice(&window.to_le_bytes());
fs::write(&tmp, bytes)?;
fs::rename(&tmp, &path)?;
Ok(())
}
pub fn ensure_current_window_initialized(data_dir: &Path) -> Result<u64, NodeError> {
let path = current_window_path(data_dir);
if path.exists() {
return load_current_window(data_dir);
}
save_current_window(data_dir, 0)?;
Ok(0)
}
#[allow(dead_code)]
fn _io_to_local(e: io::Error) -> NodeError {
NodeError::Io(e)
}