# -------------------------------------------------------------
# A transactional (txn2) read-only request runs into a replicated
# intent below its read timestamp. It informs the lock table and
# pushes the intent's transaction (txn1) above its uncertainty
# window. The push succeeds and the request is able to proceed.
# -------------------------------------------------------------

new-txn name=txn1 ts=10,1 epoch=0
----

new-txn name=txn2 ts=12,1 epoch=0 uncertainty-limit=15,1
----

new-request name=req1 txn=txn2 ts=12,1
  get key=k
----

sequence req=req1
----
[1] sequence req1: sequencing request
[1] sequence req1: acquiring latches
[1] sequence req1: scanning lock table for conflicting locks
[1] sequence req1: sequencing complete, returned guard

handle-lock-conflict-error req=req1 lease-seq=1
  lock txn=txn1 key=k
----
[2] handle lock conflict error req1: handled conflicting locks on ‹"k"›, released latches

debug-lock-table
----
num=1
 lock: "k"
  holder: txn: 00000001-0000-0000-0000-000000000000 epoch: 0, iso: Serializable, ts: 10.000000000,1, info: repl [Intent]

sequence req=req1
----
[3] sequence req1: re-sequencing request
[3] sequence req1: acquiring latches
[3] sequence req1: scanning lock table for conflicting locks
[3] sequence req1: waiting in lock wait-queues
[3] sequence req1: lock wait-queue event: wait for txn 00000001 holding lock @ key ‹"k"› (queuedLockingRequests: 0, queuedReaders: 1)
[3] sequence req1: pushing after 0s for: deadlock/liveness detection = true, timeout enforcement = false, priority enforcement = false, wait policy error = false
[3] sequence req1: pushing timestamp of txn 00000001 above 15.000000000,1
[3] sequence req1: blocked on select in concurrency_test.(*cluster).PushTransaction

on-txn-updated txn=txn1 status=pending ts=15,2
----
[-] update txn: increasing timestamp of txn1
[3] sequence req1: resolving intent ‹"k"› for txn 00000001 with PENDING status and clock observation {1 123.000000000,1}
[3] sequence req1: lock wait-queue event: done waiting
[3] sequence req1: conflicted with ‹00000001-0000-0000-0000-000000000000› on ‹"k"› for 0.000s
[3] sequence req1: acquiring latches
[3] sequence req1: scanning lock table for conflicting locks
[3] sequence req1: sequencing complete, returned guard

finish req=req1
----
[-] finish req1: finishing request

reset namespace
----

# -------------------------------------------------------------
# Same situation as above, only here, the read-only transaction
# has an uncertainty interval that extends past present time.
# The transaction only pushes to present time, not all the way
# to its uncertainty limit. See lockTableWaiterImpl.pushHeader.
# -------------------------------------------------------------

debug-set-clock ts=135
----

new-txn name=txn1 ts=100,1 epoch=0
----

new-txn name=txn2 ts=120,1 epoch=0 uncertainty-limit=150,1
----

new-request name=req1 txn=txn2 ts=120,1
  get key=k
----

sequence req=req1
----
[1] sequence req1: sequencing request
[1] sequence req1: acquiring latches
[1] sequence req1: scanning lock table for conflicting locks
[1] sequence req1: sequencing complete, returned guard

handle-lock-conflict-error req=req1 lease-seq=1
  lock txn=txn1 key=k
----
[2] handle lock conflict error req1: handled conflicting locks on ‹"k"›, released latches

debug-lock-table
----
num=1
 lock: "k"
  holder: txn: 00000001-0000-0000-0000-000000000000 epoch: 0, iso: Serializable, ts: 100.000000000,1, info: repl [Intent]

sequence req=req1
----
[3] sequence req1: re-sequencing request
[3] sequence req1: acquiring latches
[3] sequence req1: scanning lock table for conflicting locks
[3] sequence req1: waiting in lock wait-queues
[3] sequence req1: lock wait-queue event: wait for txn 00000001 holding lock @ key ‹"k"› (queuedLockingRequests: 0, queuedReaders: 1)
[3] sequence req1: pushing after 0s for: deadlock/liveness detection = true, timeout enforcement = false, priority enforcement = false, wait policy error = false
[3] sequence req1: pushing timestamp of txn 00000001 above 135.000000000,0
[3] sequence req1: blocked on select in concurrency_test.(*cluster).PushTransaction

on-txn-updated txn=txn1 status=pending ts=135,1
----
[-] update txn: increasing timestamp of txn1
[3] sequence req1: resolving intent ‹"k"› for txn 00000001 with PENDING status and clock observation {1 135.000000000,1}
[3] sequence req1: lock wait-queue event: done waiting
[3] sequence req1: conflicted with ‹00000001-0000-0000-0000-000000000000› on ‹"k"› for 0.000s
[3] sequence req1: acquiring latches
[3] sequence req1: scanning lock table for conflicting locks
[3] sequence req1: sequencing complete, returned guard

finish req=req1
----
[-] finish req1: finishing request

reset namespace
----

# -------------------------------------------------------------
# A transactional (txn2) read-only request runs into a replicated
# intent below its read timestamp and informs the lock table.
#
# A second transactional (txn3) read-only request does not wait
# on the intent in the lock table because its read timestamp is
# below the intent timestamp. However, the intent's provisional
# value is in txn3's uncertainty window. The read-only request
# returns a ReadWithinUncertaintyIntervalError and does not
# inform the lock table of the intent.
#
# This causes txn3 to restart with a higher read timestamp. At
# this point, since txn1's intent is still present, it begins
# waiting in the lock table.
# -------------------------------------------------------------

new-txn name=txn1 ts=14,1 epoch=0
----

new-txn name=txn2 ts=15,1 epoch=0
----

new-txn name=txn3 ts=12,1 epoch=0 uncertainty-limit=15,1
----

new-request name=req1 txn=txn2 ts=15,1
  get key=k
----

sequence req=req1
----
[1] sequence req1: sequencing request
[1] sequence req1: acquiring latches
[1] sequence req1: scanning lock table for conflicting locks
[1] sequence req1: sequencing complete, returned guard

handle-lock-conflict-error req=req1 lease-seq=1
  lock txn=txn1 key=k
----
[2] handle lock conflict error req1: handled conflicting locks on ‹"k"›, released latches

debug-lock-table
----
num=1
 lock: "k"
  holder: txn: 00000001-0000-0000-0000-000000000000 epoch: 0, iso: Serializable, ts: 14.000000000,1, info: repl [Intent]

sequence req=req1
----
[3] sequence req1: re-sequencing request
[3] sequence req1: acquiring latches
[3] sequence req1: scanning lock table for conflicting locks
[3] sequence req1: waiting in lock wait-queues
[3] sequence req1: lock wait-queue event: wait for txn 00000001 holding lock @ key ‹"k"› (queuedLockingRequests: 0, queuedReaders: 1)
[3] sequence req1: pushing after 0s for: deadlock/liveness detection = true, timeout enforcement = false, priority enforcement = false, wait policy error = false
[3] sequence req1: pushing timestamp of txn 00000001 above 15.000000000,1
[3] sequence req1: blocked on select in concurrency_test.(*cluster).PushTransaction

# txn3 does not wait on lock in lock table, but does end up throwing a
# ReadWithinUncertaintyIntervalError when it scans and finds txn1's
# provisional value in its uncertainty interval.
new-request name=req2 txn=txn3 ts=12,1
  get key=k
----

sequence req=req2
----
[4] sequence req2: sequencing request
[4] sequence req2: acquiring latches
[4] sequence req2: scanning lock table for conflicting locks
[4] sequence req2: sequencing complete, returned guard

finish req=req2
----
[-] finish req2: finishing request

# txn3 refreshes/restarts with a higher read timestamp than that of the
# value it saw in its uncertainty interval. It then retries its request.
on-txn-updated txn=txn3 status=pending ts=14,2
----
[-] update txn: increasing timestamp of txn3

new-request name=req2-retry txn=txn3 ts=14,2
  get key=k
----

sequence req=req2-retry
----
[5] sequence req2-retry: sequencing request
[5] sequence req2-retry: acquiring latches
[5] sequence req2-retry: scanning lock table for conflicting locks
[5] sequence req2-retry: waiting in lock wait-queues
[5] sequence req2-retry: lock wait-queue event: wait for txn 00000001 holding lock @ key ‹"k"› (queuedLockingRequests: 0, queuedReaders: 2)
[5] sequence req2-retry: pushing after 0s for: deadlock/liveness detection = true, timeout enforcement = false, priority enforcement = false, wait policy error = false
[5] sequence req2-retry: pushing timestamp of txn 00000001 above 15.000000000,1
[5] sequence req2-retry: blocked on select in concurrency_test.(*cluster).PushTransaction

# txn1 commits and lets both reads through.
on-txn-updated txn=txn1 status=committed
----
[-] update txn: committing txn1
[3] sequence req1: resolving intent ‹"k"› for txn 00000001 with COMMITTED status
[3] sequence req1: lock wait-queue event: done waiting
[3] sequence req1: conflicted with ‹00000001-0000-0000-0000-000000000000› on ‹"k"› for 0.000s
[3] sequence req1: acquiring latches
[3] sequence req1: scanning lock table for conflicting locks
[3] sequence req1: sequencing complete, returned guard
[5] sequence req2-retry: resolving intent ‹"k"› for txn 00000001 with COMMITTED status
[5] sequence req2-retry: lock wait-queue event: done waiting
[5] sequence req2-retry: conflicted with ‹00000001-0000-0000-0000-000000000000› on ‹"k"› for 0.000s
[5] sequence req2-retry: acquiring latches
[5] sequence req2-retry: scanning lock table for conflicting locks
[5] sequence req2-retry: sequencing complete, returned guard

finish req=req1
----
[-] finish req1: finishing request

finish req=req2-retry
----
[-] finish req2-retry: finishing request

reset namespace
----
