use super::{
CommitReceipt, CommitStatus, SerializableParticipant, SerializableTransactionId,
StorageTransactionId, VersionError, VersionResult,
};
pub const DEFAULT_RECEIPT_RETENTION_LIMIT: u64 = 65_536;
pub fn receipt_lease_id(transaction: StorageTransactionId) -> SerializableTransactionId {
SerializableTransactionId::new(
transaction.database(),
*b"UQAReceiptLease1",
transaction.allocation(),
)
.expect("receipt allocation and namespace are nonzero")
}
pub struct RetainedTransactionAllocation {
transaction: StorageTransactionId,
_lease: Option<SerializableParticipant>,
}
impl RetainedTransactionAllocation {
pub fn untracked(transaction: StorageTransactionId) -> Self {
Self {
transaction,
_lease: None,
}
}
pub fn retain(
transaction: StorageTransactionId,
lease: SerializableParticipant,
) -> VersionResult<Self> {
if lease.id() != receipt_lease_id(transaction) {
return Err(VersionError::InvalidEncoding(
"receipt owner lease identity mismatch",
));
}
Ok(Self {
transaction,
_lease: Some(lease),
})
}
pub fn transaction(&self) -> StorageTransactionId {
self.transaction
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReceiptAcknowledgement {
Committed(CommitReceipt),
Aborted(StorageTransactionId),
}
impl ReceiptAcknowledgement {
pub fn transaction(self) -> StorageTransactionId {
match self {
Self::Committed(receipt) => receipt.transaction,
Self::Aborted(transaction) => transaction,
}
}
pub fn validate(self, status: CommitStatus) -> VersionResult<()> {
match (self, status) {
(_, CommitStatus::Unknown) | (Self::Aborted(_), CommitStatus::Aborted) => Ok(()),
(Self::Committed(expected), CommitStatus::Committed(actual)) if expected == actual => {
Ok(())
}
(_, CommitStatus::Pending) => Err(VersionError::TransactionSealed),
(_, CommitStatus::Committed(receipt)) => Err(VersionError::AlreadyCommitted(receipt)),
(_, CommitStatus::Aborted) => Err(VersionError::AlreadyAborted(self.transaction())),
}
}
}