pub struct WriteTxn<'db, F: FileBackend> { /* private fields */ }Expand description
A write transaction.
Construct via WriteTxn::begin (or, to release a host lock
across the blocking acquire, WriteTxn::acquire +
WriteTxn::from_acquire). Holds, for its entire lifetime:
- A
WriteSerialGuardon the env’s in-process write- serialization gate — ensures at most oneWriteTxnper env per process. - An optional cross-process
WRITER_LOCKbyte — ensures at most oneWriteTxnacross the cluster of processes that have opened the same file.
WriteTxn::commit finalises the transaction through the pager’s
WAL; WriteTxn::rollback discards pending writes. Dropping an
uncommitted WriteTxn rolls back automatically (and logs a
tracing debug event, gated on the tracing feature, so the
caller learns about the silent rollback).
Send (issue #18): every field is Send — &TxnEnv is
Send + Sync, WriteSerialGuard owns an Arc<AtomicBool>, and
WriterLock / HeaderSnapshot are Send. Soundness rests on
the single-writer invariant: at most one WriteTxn exists per env
at a time (the gate enforces it), and every pager access re-locks
the pager Mutex per-op, so there is no thread-affine state to
violate when the handle moves between threads.
Generic over F: FileBackend (Rule 9: no dyn).
Implementations§
Source§impl<'db, F: FileBackend> WriteTxn<'db, F>
impl<'db, F: FileBackend> WriteTxn<'db, F>
Sourcepub fn begin(env: &'db TxnEnv<F>, timeout: Duration) -> Result<Self>
pub fn begin(env: &'db TxnEnv<F>, timeout: Duration) -> Result<Self>
Begin a new write transaction against env.
Equivalent to Self::from_acquire(env, Self::acquire
(env, timeout)?): it performs the two blocking lock acquires
(in-process gate, then cross-process WRITER_LOCK) and then
assembles the txn. Callers that need to release a host runtime
lock (e.g. the Python GIL) across the blocking wait should call
Self::acquire / Self::from_acquire directly so the
blocking step runs without the host lock held.
§Errors
Error::BusywithLockKind::Writerif the cross- process lock did not become available withintimeout.Error::BusywithLockKind::WriterInProcessif another thread in the same process is mid-write.Error::Ioon lock syscall failure.
Sourcepub fn acquire(
env: &'db TxnEnv<F>,
timeout: Duration,
) -> Result<WriteAcquire<F>>
pub fn acquire( env: &'db TxnEnv<F>, timeout: Duration, ) -> Result<WriteAcquire<F>>
Perform BOTH blocking write-lock acquires and return a Send
token, without touching the pager or borrowing the env’s
lifetime beyond the call.
Acquires the in-process serialization gate FIRST (bounded busy-
poll against timeout), THEN the cross-process WRITER_LOCK
(if env.lock_file is Some). This order is load-bearing:
the cross-process OFD lock is per-fd and the whole process
shares one lock-file fd, so two same-process threads would BOTH
pass the cross-process lock — the in-process gate is the
authoritative same-process serializer and must win first. On a
cross-process failure the in-process guard is dropped (releasing
the gate) before the error returns, exactly as begin did.
The returned WriteAcquire owns both guards and is Send,
so the caller may move it across threads (e.g. acquire on a
worker thread with the Python GIL released).
§Errors
As Self::begin.
Sourcepub fn from_acquire(env: &'db TxnEnv<F>, acq: WriteAcquire<F>) -> Result<Self>
pub fn from_acquire(env: &'db TxnEnv<F>, acq: WriteAcquire<F>) -> Result<Self>
Assemble a WriteTxn from a previously-acquired
token. This is the cheap, NON-blocking half of begin: it
briefly locks the pager to flip the txn-depth gauge and take the
header snapshot, then takes ownership of the token’s guards.
Holding the pager mutex here cannot deadlock: the caller already
owns the in-process gate (carried in acq), so no other
WriteTxn is alive, and the snapshot is cheap.
§Errors
Error::BusywithLockKind::WriterInProcessif the pager mutex is poisoned.
Sourcepub fn write_page(&self, id: PageId, page: &Page) -> Result<()>
pub fn write_page(&self, id: PageId, page: &Page) -> Result<()>
Write page at id through the pager.
§Errors
Error::InvalidArgumentifidis out of range.Error::Ioon syscall failure.
Sourcepub fn read_page(&self, id: PageId) -> Result<Page>
pub fn read_page(&self, id: PageId) -> Result<Page>
Read id through the pager (sees pending + committed +
main). Used inside a write txn that needs to read-modify-
write a page. Returns an owned Page because the borrow
chain through the pager’s mutex would otherwise tie the
returned reference to the guard.
§Errors
As Pager::read_page.
Sourcepub fn alloc_page(&self) -> Result<PageId>
pub fn alloc_page(&self) -> Result<PageId>
Sourcepub fn lock_pager(&self) -> Result<MutexGuard<'_, Pager<F>>>
pub fn lock_pager(&self) -> Result<MutexGuard<'_, Pager<F>>>
Acquire the pager mutex. Bubble a poisoned mutex up as
WriterInProcess — every txn method that takes the pager
goes through here so the failure mode is uniform.
§Errors
Returns Error::Busy with LockKind::WriterInProcess if
the mutex is poisoned by a previous panic.
Sourcepub fn env(&self) -> &'db TxnEnv<F>
pub fn env(&self) -> &'db TxnEnv<F>
Access the underlying env. Used by callers (e.g. obj
crate) that compose typed handles over the raw txn.