* commitproxy: skip per-mutation lock check when no locks are held
Add anyExclusiveLockHeld_ flag on RangeLock, refreshed in
consumePendingRequest after each take/release, and an early return at
the top of rejectMutationsForReadLockOnRange that bypasses the
per-transaction x per-mutation loop when the flag is false. With the
knob enabled but no exclusive read locks active (the steady state
when no bulkload is running), the commit hot path now skips the entire
scan instead of constructing a KeyRange and walking the KeyRangeMap
for every mutation in every batch.
Add RangeLockFastPath / RangeLockSlowPath counters to ProxyMetrics so
operators can confirm the optimization is firing. Verified with
tests/fast/RangeLocking.toml and tests/fast/RangeLockCycle.toml; both
pass and both counters increment as expected.
* docs: document the no-locks-held fast path and ProxyMetrics counters
Extend documentation/sphinx/source/rangelock.rst with a "Steady-state cost
when no locks are held" subsection describing the anyExclusiveLockHeld_
flag introduced in this PR and the early return in
rejectMutationsForReadLockOnRange.
Also document the two new ProxyMetrics counters (RangeLockFastPath and
RangeLockSlowPath) so operators investigating commit-proxy performance
can find them without grepping the source. The counters are the
production observability hook for the silent-degradation case where the
flag fails to clear after a lock release.
* docs: explain how anyExclusiveLockHeld_ stays consistent across proxies
The previous doc commit described the fast-path flag and its counters
but skipped the correctness argument: the flag is per-proxy, never
directly synchronized, and convergence comes from the txnStateStore
mutation broadcast that already drives coreMap consistency.
A reviewer of the patch (or anyone debugging "are these proxies'
flags actually consistent?") will ask exactly this question. Spell
out the within-batch / across-batch / recovery cases plus the
asymmetric stuck-true vs stuck-false analysis (stuck-true is harmless
extra CPU and observable via RangeLockFastPath; stuck-false would
manifest as missing transaction_rejected_range_locked rejections,
which existing simulation tests already assert against).
* Formatting
* Potential fix for pull request finding
* docs: address Copilot review on rangelock.rst possessive escaping
Use the rST backslash-space escape after inline literals where a
possessive s follows, so Sphinx renders the possessives of "V" and
"consumePendingRequest" without a visible space before the apostrophe.
* docs: explain ENABLE_READ_LOCK_ON_RANGE knob in Knobs.h
Add a trailing comment block on the knob declaration explaining that
despite the name this is a write-exclusion lock (commit proxies reject
writes to a locked range, reads are unaffected). The name reflects
bulkloads perspective rather than describing what the lock blocks.
Mirrors the substantive trailing comments on neighbouring knobs like
MAX_READ_TRANSACTION_LIFE_VERSIONS so the pattern fits in.