mod backend;
mod entry;
mod head;
mod host;
mod lease;
mod memory;
mod object;
mod projection;
mod replay;
mod verify;
pub use backend::{Admission, JournalBackend, StoredState};
pub use entry::JournalEntry;
pub use head::JournalHead;
pub use host::{BackendCapabilities, Failpoint, HostDirJournalBackend};
pub use lease::Lease;
pub use memory::MemoryBackend;
pub use object::JournalObject;
pub use projection::{DirProjection, ProjectionRow, TableProjection};
pub use replay::{Replay, replay};
pub use verify::{JournalError, Verification};
use sim_kernel::{ContentId, Symbol};
pub struct Journal<B> {
backend: B,
}
impl<B: JournalBackend> Journal<B> {
pub fn new(backend: B) -> Self {
Self { backend }
}
pub fn acquire_lease(&self) -> Result<Lease, JournalError> {
self.backend.acquire_lease()
}
pub fn head(&self) -> Result<Option<JournalHead>, JournalError> {
let state = self.backend.read_state()?;
verify::verify_state(&state).map(|v| v.head)
}
pub fn publish(
&self,
lease: &Lease,
expected: Option<&JournalHead>,
objects: Vec<JournalObject>,
entries: Vec<JournalEntry>,
) -> Result<JournalHead, JournalError> {
if entries.is_empty() {
return Err(JournalError::EmptyBatch);
}
let before = self.backend.read_state()?;
verify::verify_state(&before)?;
verify::verify_batch(&before, expected, &objects, &entries)?;
let head = self.backend.admit(Admission {
fence: lease.fence,
expected: expected.cloned(),
objects,
entries: entries.clone(),
})?;
Ok(head)
}
pub fn verify(&self) -> Result<Verification, JournalError> {
verify::verify_state(&self.backend.read_state()?)
}
pub fn replay(&self) -> Result<Replay, JournalError> {
replay(self.backend.read_state()?)
}
pub fn table_projection(&self) -> Result<TableProjection, JournalError> {
Ok(TableProjection::from_verification(self.verify()?))
}
pub fn dir_projection(&self) -> Result<DirProjection, JournalError> {
Ok(DirProjection::from_verification(self.verify()?))
}
pub fn entry(
sequence: u64,
previous: Option<ContentId>,
kind: Symbol,
payloads: Vec<ContentId>,
) -> JournalEntry {
JournalEntry::new(sequence, previous, kind, payloads)
}
}
#[cfg(test)]
mod tests;