pub struct Journal<S: Store> {
store: S,
ledger: Ledger,
offset: u64,
checkpoint_seq: u64,
head: Hash,
pending_sentinel: Option<(TxnId, Vec<u8>)>,
}Fields§
§store: S§ledger: Ledger§offset: u64Byte offset of the next record in the log.
checkpoint_seq: u64The checkpoint seq this handle’s ledger incorporates.
head: HashThe hash chain’s head after the last record this handle has read (I18).
pending_sentinel: Option<(TxnId, Vec<u8>)>During a reload: the sentinel’s transaction and bytes, not yet applied
(§12c). Its interlock is applied just before a Resolved that names it,
or after the scan.
Implementations§
Source§impl<S: Store> Journal<S>
impl<S: Store> Journal<S>
Sourcepub fn open(store: S) -> Result<Journal<S>, JournalError>
pub fn open(store: S) -> Result<Journal<S>, JournalError>
Load the checkpoint, replay the log, truncate a torn tail.
fn load_checkpoint(&self) -> Result<Option<(u64, Ledger, Hash)>, JournalError>
fn checkpoint_seq_on_disk(&self) -> Result<u64, JournalError>
fn reload(&mut self) -> Result<(), JournalError>
Sourcefn clear_resolved_sentinel(&mut self) -> Result<(), JournalError>
fn clear_resolved_sentinel(&mut self) -> Result<(), JournalError>
At compaction: the checkpoint now carries the resolution, so the sentinel of a resolved transaction is zeroed and a reload does not set the interlock again. (A crash before the zeroing leaves it set: the safe side; resolving again clears it.)
Sourcefn scan(&mut self, reload: bool) -> Result<(), JournalError>
fn scan(&mut self, reload: bool) -> Result<(), JournalError>
Read records from self.offset onward; the first frame that is not
intact, or whose seq does not follow, ends the scan.
reload (scanning from offset 0 after loading the checkpoint) differs in
two ways. A leading run of frames at or below the checkpoint’s seq is
skipped, which happens only if a crash came between writing a checkpoint
and resetting the log. And the frame that ends the scan has its header
zeroed (torn-tail truncation). When catching up from a later offset,
nothing is skipped: a frame there with an old seq is a leftover from
before a compaction, and skipping it would move the write offset past it.
Sourcefn stop_at_tail(&mut self, truncate: bool) -> Result<(), JournalError>
fn stop_at_tail(&mut self, truncate: bool) -> Result<(), JournalError>
The scan stopped at self.offset. On reload that is the torn tail,
truncated, unless an intact record with a later seq follows it: then a
record before the tail was damaged or edited (I18), and nothing is
truncated.
Sourcefn later_record(&self) -> Result<Option<u64>, JournalError>
fn later_record(&self) -> Result<Option<u64>, JournalError>
An intact frame after self.offset whose seq is past the ledger’s: the
sign of a damaged record rather than a torn tail. Bytes left over from
before a compaction all carry seqs at or below the checkpoint’s.
Sourcepub fn verify_chain(&mut self) -> Result<(), JournalError>
pub fn verify_chain(&mut self) -> Result<(), JournalError>
Re-read the whole segment from the checkpoint and check that it still chains to the head this handle holds (I18): catches a retained record edited on disk after it was read. Read-only.
Sourcepub fn head(&self) -> Hash
pub fn head(&self) -> Hash
The chain head after the last record (carried by the next checkpoint).
Sourcefn refresh(&mut self) -> Result<(), JournalError>
fn refresh(&mut self) -> Result<(), JournalError>
Catch up on records written by other handles since this one last looked.
pub fn ledger(&self) -> &Ledger
pub fn store(&self) -> &S
Sourcepub fn sync_ledger(&mut self) -> Result<&Ledger, JournalError>
pub fn sync_ledger(&mut self) -> Result<&Ledger, JournalError>
Re-read the shared journal and return the current ledger.
Sourcepub fn append(
&mut self,
at: Timestamp,
record: Record,
) -> Result<Entry, JournalError>
pub fn append( &mut self, at: Timestamp, record: Record, ) -> Result<Entry, JournalError>
Validate, write, fsync, then apply (write-ahead). Returns the entry.
Sourcepub fn locked<R>(
&mut self,
f: impl FnOnce(&mut Locked<'_, S>) -> R,
) -> Result<R, JournalError>
pub fn locked<R>( &mut self, f: impl FnOnce(&mut Locked<'_, S>) -> R, ) -> Result<R, JournalError>
Run f with the store lock held, after catching up. Used for
read-decide-append sequences that must not interleave with another
handle (lease takeover).
fn append_locked( &mut self, at: Timestamp, record: Record, ) -> Result<Entry, JournalError>
Sourcepub fn segment(&mut self) -> Result<Vec<Entry>, JournalError>
pub fn segment(&mut self) -> Result<Vec<Entry>, JournalError>
The entries in the current log segment (everything since the last checkpoint), in order.
Sourcepub fn usage_permille(&self) -> u64
pub fn usage_permille(&self) -> u64
Fraction of the preallocation in use, in per-mille.
Sourcepub fn needs_compaction(&self) -> bool
pub fn needs_compaction(&self) -> bool
Compaction triggers at 75% full (§12c).
Sourcepub fn compact(&mut self) -> Result<(), JournalError>
pub fn compact(&mut self) -> Result<(), JournalError>
Checkpoint-then-truncate. If the checkpoint write fails, nothing changes.
Sourcepub fn write_sentinel(
&mut self,
txn: TxnId,
note: &str,
) -> Result<(), JournalError>
pub fn write_sentinel( &mut self, txn: TxnId, note: &str, ) -> Result<(), JournalError>
The fixed-size fallback when a recovery-path record cannot be written (§12c): marks the transaction RecoveryFailed outside the journal and sets the interlock.