new-lock-table maxlocks=1000
----

new-txn txn=txn1 ts=10 epoch=0 seq=0
----

new-txn txn=txn2 ts=10 epoch=0 seq=0
----

new-txn txn=txn3 ts=10 epoch=0 seq=0
----

new-txn txn=txn4 ts=10 epoch=0 seq=0
----

# ------------------------------------------------------------------------------
# Ensure both shared and exclusive locks can be discovered and added to the
# lock table.
# ------------------------------------------------------------------------------

new-request r=req1 txn=txn1 ts=10 spans=exclusive@a+exclusive@b
----

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

add-discovered r=req1 k=a txn=txn2 strength=shared
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001

add-discovered r=req1 k=b txn=txn3 strength=exclusive
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001

# ------------------------------------------------------------------------------
# Test shared lock discovery on a key on which a shared lock is already held
# by a different transaction. For the already held shared lock, we test both the
# case when that lock is unreplicated and replicated.
# ------------------------------------------------------------------------------

# Acquire a shared lock on key C.
new-request r=req2 txn=txn2 ts=10 spans=shared@c
----

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

acquire r=req2 k=c durability=u strength=shared
----
num=3
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
 lock: "c"
  holder: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: unrepl [(str: Shared seq: 0)]

new-request r=req3 txn=txn1 ts=10 spans=exclusive@a+exclusive@c
----

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

add-discovered r=req3 k=a txn=txn3 strength=shared
----
num=3
 lock: "a"
  holders: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: repl [Shared]
           txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
    active: true req: 3, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
 lock: "c"
  holder: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: unrepl [(str: Shared seq: 0)]

add-discovered r=req3 k=c txn=txn3 strength=shared
----
num=3
 lock: "a"
  holders: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: repl [Shared]
           txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
    active: true req: 3, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
 lock: "c"
  holders: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: unrepl [(str: Shared seq: 0)]
           txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 3, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001

# ------------------------------------------------------------------------------
# Check we correctly return errors if a discovered lock is incompatible with the
# lock holder. Only locks from other transactions should be considered for
# incompatibility.
# ------------------------------------------------------------------------------

new-request r=req4 txn=txn1 ts=10 spans=intent@a+intent@b+intent@c
----

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

add-discovered r=req4 k=a txn=txn4 strength=intent
----
incompatibility detected; lock by transaction 00000000-0000-0000-0000-000000000004 with strength Intent incompatible with an already held lock by 00000000-0000-0000-0000-000000000002 with strength Shared

add-discovered r=req4 k=b txn=txn4 strength=shared
----
incompatibility detected; lock by transaction 00000000-0000-0000-0000-000000000004 with strength Shared incompatible with an already held lock by 00000000-0000-0000-0000-000000000003 with strength Exclusive

add-discovered r=req4 k=c txn=txn4 strength=exclusive
----
incompatibility detected; lock by transaction 00000000-0000-0000-0000-000000000004 with strength Exclusive incompatible with an already held lock by 00000000-0000-0000-0000-000000000002 with strength Shared

# Discovering an intent at key "b" that belongs to txn3 shouldn't be an
# assertion failure, as txn3 is the exclusive lock holder.

add-discovered r=req4 k=b txn=txn3 strength=intent
----
num=3
 lock: "a"
  holders: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: repl [Shared]
           txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
    active: true req: 3, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
    active: true req: 4, strength: Intent, txn: 00000000-0000-0000-0000-000000000001
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: repl [Intent, Exclusive]
   queued locking requests:
    active: false req: 1, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001
    active: false req: 4, strength: Intent, txn: 00000000-0000-0000-0000-000000000001
 lock: "c"
  holders: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: unrepl [(str: Shared seq: 0)]
           txn: 00000000-0000-0000-0000-000000000003 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 3, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000001

# ------------------------------------------------------------------------------
# Ensure a lock that's held unreplicated can be re-acquired as a replicated lock
# correctly, and vice versa. We do so for both shared and exclusive locks.
# ------------------------------------------------------------------------------

clear
----
num=0

new-request r=req5 txn=txn1 ts=10 spans=exclusive@a+shared@b
----

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

acquire r=req5 k=a durability=u strength=exclusive
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: unrepl [(str: Exclusive seq: 0)]

acquire r=req5 k=b durability=u strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: unrepl [(str: Exclusive seq: 0)]
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: unrepl [(str: Shared seq: 0)]

# Add a waiter on both these keys so that the replicated lock acquisition
# doesn't drop the lock.

new-request r=req6 txn=txn2 ts=10 spans=exclusive@a
----

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

new-request r=req7 txn=txn2 ts=10 spans=exclusive@b
----

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

new-request r=req8 txn=txn1 ts=10 spans=exclusive@a+shared@b
----

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

acquire r=req8 k=a durability=r strength=exclusive
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: repl [Exclusive], unrepl [(str: Exclusive seq: 0)]
   queued locking requests:
    active: true req: 6, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: unrepl [(str: Shared seq: 0)]
   queued locking requests:
    active: true req: 7, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000002

acquire r=req8 k=b durability=r strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: repl [Exclusive], unrepl [(str: Exclusive seq: 0)]
   queued locking requests:
    active: true req: 6, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared], unrepl [(str: Shared seq: 0)]
   queued locking requests:
    active: true req: 7, strength: Exclusive, txn: 00000000-0000-0000-0000-000000000002


# Test the other way around. A replicated lock is held first, followed by
# unreplicated re-acquisition.

clear
----
num=0

new-request r=req9 txn=txn2 ts=10 spans=intent@a
----

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

add-discovered r=req9 k=a txn=txn1 strength=exclusive
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 9, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

new-request r=req10 txn=txn2 ts=10 spans=intent@b
----

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

add-discovered r=req10 k=b txn=txn1 strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 9, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 10, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

new-request r=req11 txn=txn1 ts=10 spans=exclusive@a+shared@b
----

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

acquire r=req11 k=a durability=u strength=exclusive
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: repl [Exclusive], unrepl [(str: Exclusive seq: 0)]
   queued locking requests:
    active: false req: 9, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 10, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

acquire r=req11 k=b durability=u strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: repl [Exclusive], unrepl [(str: Exclusive seq: 0)]
   queued locking requests:
    active: false req: 9, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared], unrepl [(str: Shared seq: 0)]
   queued locking requests:
    active: false req: 10, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# ------------------------------------------------------------------------------
# Ensure lock re-acquisition works correctly for replicated locks. Both for
# idempotent lock acquisitions (same strength, same timestamp) and non-idempotent
# ones.
# ------------------------------------------------------------------------------

# 1. Test idempotent lock acquisition of replicated locks for both Exclusive and
# Shared locks.

clear
----
num=0

new-request r=req12 txn=txn2 ts=10 spans=intent@a+intent@b
----

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

add-discovered r=req12 k=a txn=txn1 strength=exclusive
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002


add-discovered r=req12 k=b txn=txn1 strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

new-request r=req13 txn=txn1 spans=exclusive@a ts=10
----

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

acquire r=req13 k=a durability=r strength=exclusive
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

new-request r=req14 txn=txn1 spans=shared@b ts=10
----

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

acquire r=req14 k=b durability=r strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 2. Test non-idempotent lock acquisition of replicated locks for both Exclusive
# and Shared locks. For now, while we're tracking timestamps, the timestamp
# should be forwarded (and not regress). This behavior will change shortly.

# 2a. Lower timestamp; should not regress.

new-request r=req15 txn=txn1 spans=exclusive@a ts=8
----

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

acquire r=req15 k=a durability=r strength=exclusive
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

new-request r=req16 txn=txn1 spans=shared@b ts=7
----

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

acquire r=req16 k=b durability=r strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 2b. Higher timestamp; should be forwarded.

new-request r=req17 txn=txn1 spans=exclusive@a ts=15
----

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

acquire r=req17 k=a durability=r strength=exclusive
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

new-request r=req18 txn=txn1 spans=shared@b ts=20
----

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

acquire r=req18 k=b durability=r strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 12, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# reset txn1's write timestamp back to 10 for the other tests.
new-txn txn=txn1 ts=10 epoch=0 seq=0
----

# ------------------------------------------------------------------------------
# Test lock acquisition works correctly when a lock is already held on a key;
# in particular, if the lock being acquired isn't compatible with the held lock,
# an error is returned.
# ------------------------------------------------------------------------------

clear
----
num=0

new-request r=req19 txn=txn2 ts=10 spans=intent@a+intent@b
----

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

add-discovered r=req19 k=a txn=txn1 strength=exclusive
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 19, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

add-discovered r=req19 k=b txn=txn1 strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 19, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
   queued locking requests:
    active: false req: 19, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 1a. Another transaction should not be allowed to acquire an exclusive lock on
# key a.
new-request r=req20 txn=txn2 ts=10 spans=exclusive@a
----

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

acquire r=req20 k=a durability=r strength=exclusive
----
incompatibility detected; lock by transaction 00000000-0000-0000-0000-000000000002 with strength Exclusive incompatible with an already held lock by 00000000-0000-0000-0000-000000000001 with strength Exclusive

# 1b. Another transaction should not be allowed to acquire a shared lock on
# key a.

new-request r=req21 txn=txn2 ts=10 spans=shared@a
----

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

acquire r=req21 k=a durability=r strength=shared
----
incompatibility detected; lock by transaction 00000000-0000-0000-0000-000000000002 with strength Shared incompatible with an already held lock by 00000000-0000-0000-0000-000000000001 with strength Exclusive

# 2a. Another transaction should not be allowed to acquire an exclusive lock on
# key b.

new-request r=req22 txn=txn2 ts=10 spans=exclusive@b
----

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

acquire r=req22 k=b durability=r strength=exclusive
----
incompatibility detected; lock by transaction 00000000-0000-0000-0000-000000000002 with strength Exclusive incompatible with an already held lock by 00000000-0000-0000-0000-000000000001 with strength Shared

# 2a. Another transaction should be allowed to acquire an shared lock on key b.

new-request r=req23 txn=txn2 ts=10 spans=shared@b
----

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

acquire r=req23 k=b durability=r strength=shared
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
 lock: "b"
  holders: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Shared]
           txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, info: repl [Shared]

# ------------------------------------------------------------------------------
# Ensure non-locking reads do not conflict with replicated exclusive locks. We
# also ensure if both a replicated exclusive lock and an unreplicated one exists
# on a key, then non-locking reads do conflict with it depending on the read's
# timestamp.
# ------------------------------------------------------------------------------

clear
----
num=0

new-request r=req24 txn=txn2 ts=10 spans=intent@a+intent@b
----

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

add-discovered r=req24 k=a txn=txn1 strength=exclusive
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 24, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

add-discovered r=req24 k=b txn=txn1 strength=exclusive
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 24, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 24, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# Re-acquire an unreplicated exclusive lock on key b.
new-request r=req25 txn=txn1 ts=10 spans=exclusive@b
----

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

acquire r=req25 k=b durability=u strength=exclusive
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 24, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: repl [Exclusive], unrepl [(str: Exclusive seq: 0)]
   queued locking requests:
    active: false req: 24, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 1. Non-locking reads below the exclusive lock's timestamp.
new-request r=req26 txn=txn3 ts=8 spans=none@a
----

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

new-request r=req27 txn=txn3 ts=8 spans=none@b
----

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

# 2. Non-locking reads at the exclusive lock's timestamp.
new-request r=req28 txn=txn3 ts=10 spans=none@a
----

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

new-request r=req29 txn=txn3 ts=10 spans=none@b
----

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

# 3. Non-locking reads above the exclusive lock's timestamp.
new-request r=req30 txn=txn3 ts=15 spans=none@a
----

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

new-request r=req31 txn=txn3 ts=15 spans=none@b
----

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

print
----
num=2
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, info: repl [Exclusive]
   queued locking requests:
    active: false req: 24, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
 lock: "b"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: repl [Exclusive], unrepl [(str: Exclusive seq: 0)]
   waiting readers:
    req: 31, txn: 00000000-0000-0000-0000-000000000003
    req: 29, txn: 00000000-0000-0000-0000-000000000003
   queued locking requests:
    active: false req: 24, strength: Intent, txn: 00000000-0000-0000-0000-000000000002


# ------------------------------------------------------------------------------
# Ensure timestamp tracking works correctly for replicated locks. We test that:
# 1. It corresponds to intents.
# 2. It never regresses.
# 3. It isn't updated when {shared, exclusive} locks are acquired/discovered.
# ------------------------------------------------------------------------------

clear
----
num=0

new-request r=req32 txn=txn2 ts=10 spans=intent@a
----

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

# 1. Ensure the timestamp corresponds to the intent.
add-discovered r=req32 k=a txn=txn1 strength=intent
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: repl [Intent]
   queued locking requests:
    active: false req: 32, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 2a. Try re-acquiring the lock with strength lock.Intent at a lower timestamp.
new-request r=req33 txn=txn1 ts=7 spans=intent@a
----

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

acquire r=req33 k=a durability=r strength=intent
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: repl [Intent]
   queued locking requests:
    active: false req: 32, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 2b. Try re-acquiring the lock with strength lock.Intent at a higher timestamp.
# The timestamp should be forwarded.
new-request r=req34 txn=txn1 ts=25 spans=intent@a
----

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

acquire r=req34 k=a durability=r strength=intent
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 25.000000000,0, info: repl [Intent]
   queued locking requests:
    active: false req: 32, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 3. Ensure shared/exclusive lock discovery/acquisition does not forward the
# timestamp.

# 3a. Exclusive lock acquisition.
new-request r=req35 txn=txn1 ts=30 spans=exclusive@a
----

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

acquire r=req35 k=a durability=r strength=exclusive
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 25.000000000,0, info: repl [Intent, Exclusive]
   queued locking requests:
    active: false req: 32, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 3b. Shared lock acquisition.
new-request r=req36 txn=txn1 ts=35 spans=shared@a
----

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

acquire r=req36 k=a durability=r strength=shared
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 25.000000000,0, info: repl [Intent, Exclusive, Shared]
   queued locking requests:
    active: false req: 32, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 3c. Lock discovery; strength = Exclusive.
new-request r=req37 txn=txn2 ts=10 spans=intent@a
----

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

# Bump txn1s timestamp to a value higher than the what the intent was written at.
new-txn txn=txn1 ts=50 epoch=0 seq=0
----

add-discovered r=req37 k=a txn=txn1 strength=exclusive
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 25.000000000,0, info: repl [Intent, Exclusive, Shared]
   queued locking requests:
    active: false req: 32, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
    active: true req: 37, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# 3d. Lock discovery; strength = Shared.
new-request r=req38 txn=txn2 ts=10 spans=intent@a
----

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

# Bump txn1s timestamp to a value higher than the what the intent was written at.
new-txn txn=txn1 ts=80 epoch=0 seq=0
----

add-discovered r=req38 k=a txn=txn1 strength=shared
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000001 epoch: 0, iso: Serializable, ts: 25.000000000,0, info: repl [Intent, Exclusive, Shared]
   queued locking requests:
    active: false req: 32, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
    active: true req: 37, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
    active: true req: 38, strength: Intent, txn: 00000000-0000-0000-0000-000000000002

# ------------------------------------------------------------------------------
# Test the case where both an unreplicated exclusive lock and an intent exists
# on a key. We test interactions with non-locking readers. Non-locking readers
# should use the intent's timestamp when deciding whether to wait on the lock or
# not.
# ------------------------------------------------------------------------------

clear
----
num=0

new-request r=req39 txn=txn2 ts=10 spans=exclusive@a
----

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

acquire k=a r=req39 durability=u strength=exclusive
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, ts: 10.000000000,0, info: unrepl [(str: Exclusive seq: 0)]

# add a waiter so the replicated lock acquisition doesn't drop the lock.
new-request r=req40 txn=txn1 ts=10 spans=intent@a
----

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

new-request r=req41 txn=txn2 ts=20 spans=intent@a
----

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

acquire k=a r=req41 durability=r strength=intent
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, ts: 20.000000000,0, info: repl [Intent], unrepl [(str: Exclusive seq: 0)]
   queued locking requests:
    active: false req: 41 promoting: true, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
    active: true req: 40, strength: Intent, txn: 00000000-0000-0000-0000-000000000001

# Ensure non-locking readers at various timestamps -- below the exclusive lock
# (10), at the exclusive lock (10), between exclusive and intent (20),
# at the intent (20), and above the intent (20). Only non-locking reads at or
# above the intent's timestamp should block.

new-request r=req42 txn=txn1 ts=5 spans=none@a
----

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

new-request r=req43 txn=txn1 ts=10 spans=none@a
----

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

new-request r=req44 txn=txn1 ts=15 spans=none@a
----

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

new-request r=req45 txn=txn1 ts=20 spans=none@a
----

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

new-request r=req46 txn=txn1 ts=25 spans=none@a
----

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

print
----
num=1
 lock: "a"
  holder: txn: 00000000-0000-0000-0000-000000000002 epoch: 0, iso: Serializable, ts: 20.000000000,0, info: repl [Intent], unrepl [(str: Exclusive seq: 0)]
   waiting readers:
    req: 46, txn: 00000000-0000-0000-0000-000000000001
    req: 45, txn: 00000000-0000-0000-0000-000000000001
   queued locking requests:
    active: false req: 41 promoting: true, strength: Intent, txn: 00000000-0000-0000-0000-000000000002
    active: true req: 40, strength: Intent, txn: 00000000-0000-0000-0000-000000000001
