Skip to content

Commit

Permalink
concurrency: extend testing for waitQueueMaxLengthExceeded
Browse files Browse the repository at this point in the history
This patch adds a test for the rare scenario where a request re-scans
the lock table and finds itself already waiting at a lock. We test the
case where adding a new request to the lock's wait queue would cause
the waitQueueMaxLengthExceeded state to be triggered -- however, this
shouldn't happen, as the request has already been accounted for.

Note that this wasn't broken; we're only adding a test here to ensure
we don't regress this behavior as we go about refactoring
`tryActiveWait`. Tested using the diff below and confirmed the test does
indeed fail:

```
--- a/pkg/kv/kvserver/concurrency/lock_table.go
+++ b/pkg/kv/kvserver/concurrency/lock_table.go
@@ -1706,7 +1706,7 @@ func (l *lockState) tryActiveWait(
        defer g.mu.Unlock()
        if str == lock.Intent {
                var qg *queuedGuard
-               if _, inQueue := g.mu.locks[l]; inQueue {
+               if _, inQueue := g.mu.locks[l]; inQueue && false {
```

Release note: None

Informs: #102210
  • Loading branch information
arulajmani committed May 31, 2023
1 parent f0a23e1 commit 8372915
Showing 1 changed file with 73 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,76 @@ num=1
active: true req: 2, txn: 00000000-0000-0000-0000-000000000002
active: true req: 3, txn: 00000000-0000-0000-0000-000000000003
distinguished req: 2

# ------------------------------------------------------------------------------
# Write requests that are already waiting in a lock's wait queue should not
# throw an error when they rescan if adding one more request to the lock's wait
# queue puts them above the max-lock-wait-queue threshold. This is because
# the request has already been accounted for when it's performing a re-scan.
# ------------------------------------------------------------------------------

new-txn txn=txn6 ts=10 epoch=0
----

new-request r=req9 txn=txn6 ts=10 spans=intent@b
----

scan r=req9
----
start-waiting: false

acquire r=req9 k=b durability=u
----
num=2
lock: "a"
holder: txn: 00000000-0000-0000-0000-000000000001, ts: 10.000000000,0, info: unrepl epoch: 0, seqs: [0]
queued writers:
active: true req: 2, txn: 00000000-0000-0000-0000-000000000002
active: true req: 3, txn: 00000000-0000-0000-0000-000000000003
distinguished req: 2
lock: "b"
holder: txn: 00000000-0000-0000-0000-000000000006, ts: 10.000000000,0, info: unrepl epoch: 0, seqs: [0]

new-txn txn=txn7 ts=10 epoch=0
----

new-request r=req10 txn=txn7 ts=10 spans=intent@b max-lock-wait-queue-length=1
----

scan r=req10
----
start-waiting: true

guard-state r=req10
----
new: state=waitForDistinguished txn=txn6 key="b" held=true guard-strength=Intent

print
----
num=2
lock: "a"
holder: txn: 00000000-0000-0000-0000-000000000001, ts: 10.000000000,0, info: unrepl epoch: 0, seqs: [0]
queued writers:
active: true req: 2, txn: 00000000-0000-0000-0000-000000000002
active: true req: 3, txn: 00000000-0000-0000-0000-000000000003
distinguished req: 2
lock: "b"
holder: txn: 00000000-0000-0000-0000-000000000006, ts: 10.000000000,0, info: unrepl epoch: 0, seqs: [0]
queued writers:
active: true req: 10, txn: 00000000-0000-0000-0000-000000000007
distinguished req: 10

# Re-scan.
scan r=req10
----
start-waiting: true

# Note that the state here changed from waitForDistinguished to waitFor. This
# is because we're cheating slightly in this test by calling scan on a request
# that's already actively waiting at a lock, which is something that cannot
# happen outside of unit tests. tryActiveWait doesn't expect this, and doesn't
# handle this state transition -- we could teach it, but it would be just for
# this contrived test scenario.
guard-state r=req10
----
new: state=waitFor txn=txn6 key="b" held=true guard-strength=Intent

0 comments on commit 8372915

Please sign in to comment.