pub struct Kernel<S: Store, H: Host> {
pub journal: Journal<S>,
pub host: H,
pub me: OwnerId,
pub crash_at: Option<CrashPoint>,
pub worker_pid: Option<u32>,
held: BTreeMap<TxnId, u64>,
}Fields§
§journal: Journal<S>§host: H§me: OwnerId§crash_at: Option<CrashPoint>§worker_pid: Option<u32>The worker pid recorded in leases this handle takes.
held: BTreeMap<TxnId, u64>Epochs this handle holds, by transaction. Every record and backend call carries the handle’s own epoch, never the ledger’s current one, so a handle whose lease was taken is refused (I15).
Implementations§
Source§impl<S: Store, H: Host> Kernel<S, H>
impl<S: Store, H: Host> Kernel<S, H>
pub fn new(journal: Journal<S>, host: H, me: OwnerId) -> Self
fn live(&mut self, id: TxnId) -> Result<LiveTxn, KernelError>
fn epoch(&self, txn: TxnId) -> Result<u64, KernelError>
fn record(&mut self, r: Record) -> Result<(), KernelError>
fn advance( &mut self, txn: &Transaction, to: TxnState, note: &str, ) -> Result<(), KernelError>
fn advance_for( &mut self, txn: &Transaction, to: TxnState, note: &str, withdrawn_for: Option<TxnId>, ) -> Result<(), KernelError>
Sourcefn call(
&mut self,
txn: TxnId,
name: &'static str,
f: impl FnOnce(&H, &OpId) -> Outcome,
) -> Result<Outcome, KernelError>
fn call( &mut self, txn: TxnId, name: &'static str, f: impl FnOnce(&H, &OpId) -> Outcome, ) -> Result<Outcome, KernelError>
Journal a durable OpId, then make the mutating call tagged with it, then journal its outcome.
fn call_op( &mut self, txn: TxnId, name: &'static str, f: impl FnOnce(&H, &OpId) -> Outcome, ) -> Result<(OpId, Outcome), KernelError>
Sourcefn drain_op(
&mut self,
txn: TxnId,
op: &OpId,
) -> Result<Result<(), String>, KernelError>
fn drain_op( &mut self, txn: TxnId, op: &OpId, ) -> Result<Result<(), String>, KernelError>
After a call that did not report success, make sure the work it started has stopped before deciding anything from the observed state: wait for its tagged jobs, cancel what remains, and wait again.
Sourcefn wait_gone(&mut self, jobs: &[JobId]) -> Result<bool, KernelError>
fn wait_gone(&mut self, jobs: &[JobId]) -> Result<bool, KernelError>
Wait up to JOB_DRAIN for jobs to leave the supervisor’s queue.
Sourcepub fn prepare(&mut self, txn: Transaction) -> Result<TxnId, KernelError>
pub fn prepare(&mut self, txn: Transaction) -> Result<TxnId, KernelError>
Journal Prepared (§12 step 4) with this handle as owner at epoch 1.
The transaction’s id is assigned here.
Sourcepub fn reject(
&mut self,
id: TxnId,
reason: RejectReason,
) -> Result<TxnState, KernelError>
pub fn reject( &mut self, id: TxnId, reason: RejectReason, ) -> Result<TxnState, KernelError>
Terminal Rejected from a pre-mutation state (§12 step 5).
Sourcepub fn withdraw(
&mut self,
id: TxnId,
rollback: TxnId,
) -> Result<TxnState, KernelError>
pub fn withdraw( &mut self, id: TxnId, rollback: TxnId, ) -> Result<TxnState, KernelError>
§12f: withdraw id, waiting in Built, for the rollback rollback
(Rejected(Interrupted), naming it in the same record).
pub fn cancel(&mut self, id: TxnId, by: Actor) -> Result<TxnState, KernelError>
Sourcepub fn wait_built(
&mut self,
id: TxnId,
why: &str,
) -> Result<TxnState, KernelError>
pub fn wait_built( &mut self, id: TxnId, why: &str, ) -> Result<TxnState, KernelError>
A verified generation candidate waits in Built for an activation
window. It holds no lease-gated mutation and counts as active for I6;
run takes it on from there.
Sourcepub fn run_boot_only(&mut self, id: TxnId) -> Result<TxnState, KernelError>
pub fn run_boot_only(&mut self, id: TxnId) -> Result<TxnState, KernelError>
The boot-only path (§12 step 7): publish the candidate as a one-shot
next-boot entry, the base still the default, and wait in
AwaitingBoot; the boot it was published for confirms or reverts it
(await_boot).
Sourcefn recover_publishing(
&mut self,
txn: &Transaction,
ops: &[OpRecord],
) -> Result<TxnState, KernelError>
fn recover_publishing( &mut self, txn: &Transaction, ops: &[OpRecord], ) -> Result<TxnState, KernelError>
The crash table’s Publishing row (§12): the publish_boot_once op
acknowledged success → AwaitingBoot; no acknowledgement → ask the boot
loader whether the one-shot entry is armed: armed → AwaitingBoot, not
armed → Rejected(Interrupted); it cannot say → RecoveryFailed.
Sourcepub fn run(&mut self, id: TxnId) -> Result<TxnState, KernelError>
pub fn run(&mut self, id: TxnId) -> Result<TxnState, KernelError>
Execute a prepared (and, if AskFirst, approved) transaction to a terminal state.
fn run_reobserve(&mut self, txn: &Transaction) -> Result<TxnState, KernelError>
fn finish_reobserve( &mut self, txn: &Transaction, ) -> Result<TxnState, KernelError>
fn candidate(txn: &Transaction) -> Option<GenerationId>
fn run_generation(&mut self, txn: &Transaction) -> Result<TxnState, KernelError>
Sourcefn restop_suppressed(&mut self, txn: &Transaction) -> Result<(), KernelError>
fn restop_suppressed(&mut self, txn: &Transaction) -> Result<(), KernelError>
Activating a generation restarts every active target, and with them the services they want, including ones a user stopped on purpose. Stop those again (principle 9: don’t fight the user). Idempotent.
Sourcefn check_then_commit(
&mut self,
txn: &Transaction,
) -> Result<TxnState, KernelError>
fn check_then_commit( &mut self, txn: &Transaction, ) -> Result<TxnState, KernelError>
From Checking: probes decide.
Sourcefn commit_from_checking(
&mut self,
txn: &Transaction,
) -> Result<TxnState, KernelError>
fn commit_from_checking( &mut self, txn: &Transaction, ) -> Result<TxnState, KernelError>
publish_boot → Published → promote → Promoted → Committed. Each step is idempotent. Only after this owner’s own probes passed (check_then_commit).
fn promote_and_commit( &mut self, txn: &Transaction, ) -> Result<TxnState, KernelError>
Sourcepub fn boot_only(&self, id: TxnId) -> bool
pub fn boot_only(&self, id: TxnId) -> bool
The transaction took the boot-only path (§12 step 7): its journal path passed AwaitingBoot.
Sourcefn admit_boot_only(
&mut self,
txn: &Transaction,
cand: GenerationId,
) -> Result<TxnState, KernelError>
fn admit_boot_only( &mut self, txn: &Transaction, cand: GenerationId, ) -> Result<TxnState, KernelError>
§10 admission of a boot-only candidate that booted and passed its Readiness probes: it becomes the default and its override is promoted; the transaction is Promoted (admitted, not confirmed) until the 10-minute confirmation checkpoint of this boot.
Sourcepub fn confirm_boot_only(
&mut self,
id: TxnId,
healthy: bool,
) -> Result<TxnState, KernelError>
pub fn confirm_boot_only( &mut self, id: TxnId, healthy: bool, ) -> Result<TxnState, KernelError>
§10 confirmation, at the 10-minute checkpoint of the boot that admitted a boot-only candidate (only the daemon calls this): the candidate still runs and the canonical probes pass → bookkeeping and Committed; otherwise it is withdrawn (§12 step 7).
Sourcefn withdraw_boot_only(
&mut self,
txn: &Transaction,
promoted: bool,
why: &str,
) -> Result<TxnState, KernelError>
fn withdraw_boot_only( &mut self, txn: &Transaction, promoted: bool, why: &str, ) -> Result<TxnState, KernelError>
Withdraw an admitted or published boot-only candidate (§12 step 7): the publishing generation is the boot default again and the base override is restored; nothing is activated live, so the machine runs the candidate until the next restart, which completes it.
Sourcefn readmit_boot_only(
&mut self,
txn: &Transaction,
same_boot: bool,
) -> Result<TxnState, KernelError>
fn readmit_boot_only( &mut self, txn: &Transaction, same_boot: bool, ) -> Result<TxnState, KernelError>
A boot-only Promoted found at startup (§12 crash table). The same boot (a daemon restart): leave it for this boot’s checkpoint. A later boot: the AwaitingBoot row, admission again: the candidate booted and passes → still Promoted, confirmed at this boot’s checkpoint; otherwise withdrawn.
Sourcepub fn await_boot(&mut self, txn: &Transaction) -> Result<TxnState, KernelError>
pub fn await_boot(&mut self, txn: &Transaction) -> Result<TxnState, KernelError>
The crash table’s AwaitingBoot row (§12): no reboot since the one-shot entry was published (it is still pending), leave it; after a reboot, the candidate booted → the boot-confirmation probes decide (pass: it becomes the default, Promoted, Committed; fail: revert); it did not boot → Reverted.
Sourcefn write_committed(
&mut self,
txn: &Transaction,
) -> Result<TxnState, KernelError>
fn write_committed( &mut self, txn: &Transaction, ) -> Result<TxnState, KernelError>
Post-commit bookkeeping, then Committed (I25), on every path that
commits a generation: the daemon’s, the watchdog’s, the boot-only
confirmation’s. The floor record precedes Committed; if the floor
cannot be derived or journaled, the transaction stays where it is
(Promoted) and is completed later, never committed without it.
Sourcefn swap_override(
&mut self,
txn: &Transaction,
from: Option<Hash>,
to: Option<Hash>,
) -> Result<Swap, KernelError>
fn swap_override( &mut self, txn: &Transaction, from: Option<Hash>, to: Option<Hash>, ) -> Result<Swap, KernelError>
Hash-compared, idempotent override replacement (§9 step 4): if the live
file already hashes to to, done; if it hashes to from, swap; anything
else means a third party changed it.
fn revert_generation( &mut self, txn: &Transaction, why: &str, ) -> Result<TxnState, KernelError>
fn recovery_failed( &mut self, txn: &Transaction, why: &str, ) -> Result<TxnState, KernelError>
fn run_device(&mut self, txn: &Transaction) -> Result<TxnState, KernelError>
fn check_device(&mut self, txn: &Transaction) -> Result<TxnState, KernelError>
Sourcefn revert_device(
&mut self,
txn: &Transaction,
why: &str,
) -> Result<TxnState, KernelError>
fn revert_device( &mut self, txn: &Transaction, why: &str, ) -> Result<TxnState, KernelError>
Unbind and rebind the previously bound driver; never a generation rollback.
Sourcepub fn watchdog_should_take_over(&self, txn: &Transaction) -> bool
pub fn watchdog_should_take_over(&self, txn: &Transaction) -> bool
Whether the watchdog should take this transaction over (§12 recovery watchdog).
Sourcepub fn take_over(
&mut self,
id: TxnId,
seen_epoch: u64,
) -> Result<Option<Lease>, KernelError>
pub fn take_over( &mut self, id: TxnId, seen_epoch: u64, ) -> Result<Option<Lease>, KernelError>
Take the lease (epoch + 1), fence the old owner, establish confirmed
quiescence. Returns the lease this handle now holds, or Ok(None) if
quiescence could not be confirmed (RecoveryFailed has been written).
seen_epoch is the epoch the caller based its decision on; if another
owner took over since, this one backs off with LostLease.
Sourcefn quiesce(
&mut self,
l: &LiveTxn,
old: &Lease,
) -> Result<Result<(), String>, KernelError>
fn quiesce( &mut self, l: &LiveTxn, old: &Lease, ) -> Result<Result<(), String>, KernelError>
Kill the old worker; cancel every job in the old lease and every job tagged with an unacknowledged OpId; wait for them to leave the queue.
Sourcepub fn supersede_unacked(&mut self, ops: &[OpId]) -> Result<(), KernelError>
pub fn supersede_unacked(&mut self, ops: &[OpId]) -> Result<(), KernelError>
Acknowledge, as superseded by the takeover, each of ops that is
still unacknowledged. Decided under the journal’s lock: the old owner,
fenced but not necessarily dead, may have journaled its own ack since
the takeover (its call returned just then), and that one stands
(run 109’s crash-slow-worker-overlap: a second ack was DuplicateOp
and left the transaction in flight).
Sourcepub fn recover(
&mut self,
id: TxnId,
seen_epoch: u64,
) -> Result<TxnState, KernelError>
pub fn recover( &mut self, id: TxnId, seen_epoch: u64, ) -> Result<TxnState, KernelError>
Take over (from seen_epoch) and run the crash-recovery table.
Sourcefn recover_steps(&mut self, id: TxnId) -> Result<TxnState, KernelError>
fn recover_steps(&mut self, id: TxnId) -> Result<TxnState, KernelError>
The crash-recovery table (§12), as recovery_action gives it.
Assumes this handle holds the lease.
Sourcepub fn reconcile(&mut self) -> Result<Vec<TxnId>, KernelError>
pub fn reconcile(&mut self) -> Result<Vec<TxnId>, KernelError>
Daemon start (§12 daemon restart reconciliation): wait out transactions a live watchdog holds, recover the rest, and journal what was found and done. Returns the transactions left to a live watchdog.
Sourcepub fn reconcile_deferring(
&mut self,
defer: bool,
) -> Result<(Vec<TxnId>, Vec<TxnId>), KernelError>
pub fn reconcile_deferring( &mut self, defer: bool, ) -> Result<(Vec<TxnId>, Vec<TxnId>), KernelError>
As reconcile, but with defer, a generation transaction found in a
state whose recovery may run an activation (Activating, Checking,
Publishing, Published, Reverting) is only taken over: its recovery is
left to finish_deferred, which the daemon runs after ready, so an
activation that reloads a unit ordered after planarian-ready.target
does not wait on the daemon’s own start (#9). The lease is this
handle’s from here, so the watchdog does not take it while ready is
reached; the boot report and integrity checks still come before ready.
Returns the transactions left to a live watchdog, and those deferred.
Sourcepub fn finish_deferred(&mut self, ids: &[TxnId]) -> Result<(), KernelError>
pub fn finish_deferred(&mut self, ids: &[TxnId]) -> Result<(), KernelError>
After ready: the recoveries reconcile_deferring left, with this
handle already holding their leases; journalled as one reconciliation.