use crate::checkpoint::CheckpointFile;
use crate::error::PersistenceResult;
use crate::recover::CheckpointState;
use crate::storage::Directory;
use crate::walog::{WalEntry, WalMaintenance, WalWriter};
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct PublishResult {
pub checkpoint_path: String,
pub checkpoint_last_entry_id: u64,
pub wal_checkpoint_entry_id: u64,
pub deleted_wal_segments: usize,
}
pub struct CheckpointPublisher {
directory: Arc<dyn Directory>,
}
impl CheckpointPublisher {
pub fn new(directory: impl Into<Arc<dyn Directory>>) -> Self {
Self {
directory: directory.into(),
}
}
pub fn publish<C, E>(
&self,
wal: &mut WalWriter<E>,
state: &C,
checkpoint_last_entry_id: u64,
checkpoint_path: &str,
make_wal_entry: impl FnOnce(&str, u64) -> E,
) -> PersistenceResult<PublishResult>
where
C: serde::Serialize,
E: serde::Serialize + serde::de::DeserializeOwned,
{
let ckpt = CheckpointFile::new(self.directory.clone());
ckpt.write_postcard_durable(checkpoint_path, checkpoint_last_entry_id, state)?;
let entry = make_wal_entry(checkpoint_path, checkpoint_last_entry_id);
let wal_checkpoint_entry_id = wal.append(&entry)?;
wal.flush_and_sync()?;
let deleted_wal_segments = WalMaintenance::new(self.directory.clone())
.truncate_prefix(checkpoint_last_entry_id)?;
Ok(PublishResult {
checkpoint_path: checkpoint_path.to_string(),
checkpoint_last_entry_id,
wal_checkpoint_entry_id,
deleted_wal_segments,
})
}
pub fn publish_checkpoint(
&self,
wal: &mut WalWriter<WalEntry>,
state: &CheckpointState,
checkpoint_last_entry_id: u64,
checkpoint_path: &str,
) -> PersistenceResult<PublishResult> {
self.publish(
wal,
state,
checkpoint_last_entry_id,
checkpoint_path,
|path, last_id| WalEntry::Checkpoint {
checkpoint_path: path.to_string(),
last_entry_id: last_id,
},
)
}
}