NAC_Blockchain/nac-constitution-state/src/storage.rs

170 lines
4.6 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.unwrap().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).unwrap();
assert!(storage.backup(&backup_path).is_ok());
assert!(backup_path.exists());
storage.delete().unwrap();
assert!(!storage.exists());
assert!(storage.restore(&backup_path).is_ok());
assert!(storage.exists());
// 清理
let _ = storage.delete();
let _ = fs::remove_file(backup_path);
}
}