170 lines
4.7 KiB
Rust
170 lines
4.7 KiB
Rust
//! 宪法状态持久化模块
|
|
|
|
use crate::{ConstitutionVersion, Result, Error};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
use std::path::{Path, PathBuf};
|
|
use std::fs;
|
|
|
|
/// 状态快照
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct StateSnapshot {
|
|
/// 当前版本
|
|
pub current_version: ConstitutionVersion,
|
|
/// 历史版本
|
|
pub history: Vec<ConstitutionVersion>,
|
|
/// 待处理的升级
|
|
pub pending_upgrades: HashMap<u64, ConstitutionVersion>,
|
|
}
|
|
|
|
/// 存储管理器
|
|
pub struct Storage {
|
|
/// 存储路径
|
|
path: PathBuf,
|
|
}
|
|
|
|
impl Storage {
|
|
/// 创建新的存储管理器
|
|
pub fn new(path: PathBuf) -> Self {
|
|
Self { path }
|
|
}
|
|
|
|
/// 保存状态
|
|
pub fn save(&self, state: &StateSnapshot) -> Result<()> {
|
|
// 创建目录
|
|
if let Some(parent) = self.path.parent() {
|
|
fs::create_dir_all(parent)
|
|
.map_err(|e| Error::StorageError(format!("创建目录失败: {}", e)))?;
|
|
}
|
|
|
|
// 序列化状态
|
|
let json = serde_json::to_string_pretty(state)
|
|
.map_err(|e| Error::StorageError(format!("序列化失败: {}", e)))?;
|
|
|
|
// 写入文件
|
|
fs::write(&self.path, json)
|
|
.map_err(|e| Error::StorageError(format!("写入文件失败: {}", e)))?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 加载状态
|
|
pub fn load(&self) -> Result<StateSnapshot> {
|
|
// 读取文件
|
|
let json = fs::read_to_string(&self.path)
|
|
.map_err(|e| Error::StorageError(format!("读取文件失败: {}", e)))?;
|
|
|
|
// 反序列化状态
|
|
let state = serde_json::from_str(&json)
|
|
.map_err(|e| Error::StorageError(format!("反序列化失败: {}", e)))?;
|
|
|
|
Ok(state)
|
|
}
|
|
|
|
/// 检查存储是否存在
|
|
pub fn exists(&self) -> bool {
|
|
self.path.exists()
|
|
}
|
|
|
|
/// 删除存储
|
|
pub fn delete(&self) -> Result<()> {
|
|
if self.exists() {
|
|
fs::remove_file(&self.path)
|
|
.map_err(|e| Error::StorageError(format!("删除文件失败: {}", e)))?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// 备份状态
|
|
pub fn backup(&self, backup_path: &Path) -> Result<()> {
|
|
if !self.exists() {
|
|
return Err(Error::StorageError("源文件不存在".to_string()));
|
|
}
|
|
|
|
fs::copy(&self.path, backup_path)
|
|
.map_err(|e| Error::StorageError(format!("备份失败: {}", e)))?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 恢复状态
|
|
pub fn restore(&self, backup_path: &Path) -> Result<()> {
|
|
if !backup_path.exists() {
|
|
return Err(Error::StorageError("备份文件不存在".to_string()));
|
|
}
|
|
|
|
fs::copy(backup_path, &self.path)
|
|
.map_err(|e| Error::StorageError(format!("恢复失败: {}", e)))?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use nac_udm::primitives::{Hash, Address};
|
|
|
|
fn create_test_version(version: u64) -> ConstitutionVersion {
|
|
ConstitutionVersion::new(
|
|
version,
|
|
Hash::zero(),
|
|
version * 1000,
|
|
10,
|
|
version * 100,
|
|
Address::zero(),
|
|
format!("Version {}", version),
|
|
)
|
|
}
|
|
|
|
fn create_test_snapshot() -> StateSnapshot {
|
|
StateSnapshot {
|
|
current_version: create_test_version(2),
|
|
history: vec![create_test_version(1)],
|
|
pending_upgrades: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_save_and_load() {
|
|
let temp_dir = std::env::temp_dir();
|
|
let path = temp_dir.join("test_state.json");
|
|
let storage = Storage::new(path.clone());
|
|
|
|
let snapshot = create_test_snapshot();
|
|
assert!(storage.save(&snapshot).is_ok());
|
|
assert!(storage.exists());
|
|
|
|
let loaded = storage.load();
|
|
assert!(loaded.is_ok());
|
|
assert_eq!(loaded.expect("mainnet: handle error").current_version.version, 2);
|
|
|
|
// 清理
|
|
let _ = storage.delete();
|
|
}
|
|
|
|
#[test]
|
|
fn test_backup_and_restore() {
|
|
let temp_dir = std::env::temp_dir();
|
|
let path = temp_dir.join("test_state_backup.json");
|
|
let backup_path = temp_dir.join("test_state_backup_copy.json");
|
|
let storage = Storage::new(path.clone());
|
|
|
|
let snapshot = create_test_snapshot();
|
|
storage.save(&snapshot).expect("mainnet: handle error");
|
|
|
|
assert!(storage.backup(&backup_path).is_ok());
|
|
assert!(backup_path.exists());
|
|
|
|
storage.delete().expect("mainnet: handle error");
|
|
assert!(!storage.exists());
|
|
|
|
assert!(storage.restore(&backup_path).is_ok());
|
|
assert!(storage.exists());
|
|
|
|
// 清理
|
|
let _ = storage.delete();
|
|
let _ = fs::remove_file(backup_path);
|
|
}
|
|
}
|