uqa_storage/mvcc/
receipts.rs1use super::{
10 CommitReceipt, CommitStatus, SerializableParticipant, SerializableTransactionId,
11 StorageTransactionId, VersionError, VersionResult,
12};
13
14pub const DEFAULT_RECEIPT_RETENTION_LIMIT: u64 = 65_536;
16
17pub fn receipt_lease_id(transaction: StorageTransactionId) -> SerializableTransactionId {
19 SerializableTransactionId::new(
20 transaction.database(),
21 *b"UQAReceiptLease1",
22 transaction.allocation(),
23 )
24 .expect("receipt allocation and namespace are nonzero")
25}
26
27pub struct RetainedTransactionAllocation {
29 transaction: StorageTransactionId,
30 lease: Option<SerializableParticipant>,
31}
32
33impl RetainedTransactionAllocation {
34 pub fn untracked(transaction: StorageTransactionId) -> Self {
35 Self {
36 transaction,
37 lease: None,
38 }
39 }
40
41 pub fn retain(
42 transaction: StorageTransactionId,
43 lease: SerializableParticipant,
44 ) -> VersionResult<Self> {
45 if lease.id() != receipt_lease_id(transaction) {
46 return Err(VersionError::InvalidEncoding(
47 "receipt owner lease identity mismatch",
48 ));
49 }
50 Ok(Self {
51 transaction,
52 lease: Some(lease),
53 })
54 }
55
56 pub fn transaction(&self) -> StorageTransactionId {
57 self.transaction
58 }
59
60 pub fn has_resolution_lease(&self) -> bool {
62 self.lease.is_some()
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum ReceiptAcknowledgement {
69 Committed(CommitReceipt),
70 Aborted(StorageTransactionId),
71}
72
73impl ReceiptAcknowledgement {
74 pub fn transaction(self) -> StorageTransactionId {
75 match self {
76 Self::Committed(receipt) => receipt.transaction,
77 Self::Aborted(transaction) => transaction,
78 }
79 }
80
81 pub fn validate(self, status: CommitStatus) -> VersionResult<()> {
83 match (self, status) {
84 (_, CommitStatus::Unknown) | (Self::Aborted(_), CommitStatus::Aborted) => Ok(()),
85 (Self::Committed(expected), CommitStatus::Committed(actual)) if expected == actual => {
86 Ok(())
87 }
88 (_, CommitStatus::Pending) => Err(VersionError::TransactionSealed),
89 (_, CommitStatus::Committed(receipt)) => Err(VersionError::AlreadyCommitted(receipt)),
90 (_, CommitStatus::Aborted) => Err(VersionError::AlreadyAborted(self.transaction())),
91 }
92 }
93}