use std::path::PathBuf;
use ccp_shared::types::CUAllocation;
use ccp_shared::types::EpochParameters;
use ccp_shared::types::LogicalCoreId;
use serde::Deserialize;
use serde::Serialize;
use crate::utility_thread::save_reliably;
const EXPECT_DEFAULT_DESERIALIZER: &str = "the default serde (de)serializer shouldn't fail";
const STATE_FILE: &str = "state.json";
pub(crate) struct StateStorage {
state_dir: PathBuf,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub(crate) struct CCPState {
pub(crate) epoch_params: EpochParameters,
pub(crate) cu_allocation: CUAllocation,
pub(crate) msr_state: ccp_msr::state::MSRState,
pub(crate) utility_cores: Vec<LogicalCoreId>,
}
impl StateStorage {
pub(crate) fn new(state_dir: PathBuf) -> Self {
Self { state_dir }
}
pub(crate) async fn save_state(&self, state: Option<&CCPState>) -> tokio::io::Result<()> {
let data = serde_json::to_vec(&state).expect(EXPECT_DEFAULT_DESERIALIZER);
let path = self.state_dir.join(STATE_FILE);
log::info!("Saving state to {:?}", path);
tokio::task::spawn_blocking(move || save_reliably(&path, &data)).await??;
Ok(())
}
pub(crate) async fn try_to_load_data(&self) -> tokio::io::Result<Option<CCPState>> {
log::info!("Try to restore previous state from {:?}", self.state_dir);
let path = self.state_dir.join(STATE_FILE);
if !path.exists() {
return Ok(None);
}
let state_data = tokio::fs::read(&path).await?;
match serde_json::from_slice(&state_data) {
Ok(data) => Ok(data),
Err(e) => {
log::warn!("failed to parse state data from {path:?}, ignoring: {e}");
Ok(None)
}
}
}
}