mod claim;
mod codec;
mod error;
mod integrity;
mod record;
mod stage;
#[cfg(any(test, feature = "test-support"))]
use crate::physical::CommitSnapshotDiagnostic;
use crate::physical::CommittedGenerationBytes;
use serde::{Deserialize, Serialize};
pub use claim::{ClaimConflict, ClaimOutcome, validate_declaration_claim};
pub use error::{AllocationStageError, LedgerCommitError, LedgerIntegrityError};
pub use record::{AllocationLedger, AllocationRecord, RecoveredLedger};
pub use stage::stage_generation;
use codec::decode_ledger;
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LedgerCommitStore {
#[serde(deserialize_with = "crate::encoding::deserialize_present_option")]
pub(crate) current: Option<CommittedGenerationBytes>,
}
impl LedgerCommitStore {
pub(crate) fn recover(&self) -> Result<RecoveredLedger, LedgerCommitError> {
let committed = self.authoritative().map_err(LedgerCommitError::Recovery)?;
Self::recover_committed(committed)
}
#[cfg(any(test, feature = "test-support"))]
pub(crate) fn recover_with_diagnostic(
&self,
) -> (
Result<RecoveredLedger, LedgerCommitError>,
CommitSnapshotDiagnostic,
) {
let (committed, diagnostic) = self.authoritative_with_diagnostic();
let recovered = committed
.map_err(LedgerCommitError::Recovery)
.and_then(Self::recover_committed);
(recovered, diagnostic)
}
fn recover_committed(
committed: &CommittedGenerationBytes,
) -> Result<RecoveredLedger, LedgerCommitError> {
let ledger = decode_ledger(committed.payload(), committed.generation())
.map_err(LedgerCommitError::Codec)?;
ledger
.validate_integrity()
.map_err(LedgerCommitError::Integrity)?;
Ok(RecoveredLedger::from_trusted_ledger(ledger))
}
pub(crate) fn recover_or_genesis(&self) -> Result<RecoveredLedger, LedgerCommitError> {
self.recover()
.or_else(|error| RecoveredLedger::genesis_for_absent_snapshot(&error).ok_or(error))
}
#[cfg(test)]
pub fn commit(
&mut self,
ledger: &AllocationLedger,
) -> Result<RecoveredLedger, LedgerCommitError> {
self.commit_generation(ledger)?;
Ok(RecoveredLedger::from_trusted_ledger(ledger.clone()))
}
pub(crate) fn commit_generation(
&mut self,
ledger: &AllocationLedger,
) -> Result<(), LedgerCommitError> {
ledger
.validate_integrity()
.map_err(LedgerCommitError::Integrity)?;
let payload = codec::encode_ledger(ledger).map_err(LedgerCommitError::Integrity)?;
self.commit_payload_at_generation(ledger.current_generation, payload)
.map(|_| ())
.map_err(LedgerCommitError::Recovery)
}
#[cfg(test)]
pub fn write_corrupt_ledger(
&mut self,
ledger: &AllocationLedger,
) -> Result<(), LedgerCommitError> {
let payload = codec::encode_ledger(ledger).map_err(LedgerCommitError::Integrity)?;
self.write_corrupt_snapshot(ledger.current_generation, payload);
Ok(())
}
}
#[cfg(test)]
mod tests;