Skip to content

Commit ba76a26

Browse files
committed
kvnemesis: fix CPut read validation in weak isolation levels
Previously, kvnemesis would attempt to validate the timestamp associated with a CPut's read regardless of the isolation level. Since the read component of CPut is non-locking, this validation is not correct because the CPut's read is not refreshed in weak-isolation transactions. This commit treats the read of CPut similarly to other non-locking reads; they are validated only for serializable transctions. Part of: #64810 Release note: None
1 parent 220787d commit ba76a26

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

pkg/kv/kvnemesis/validator.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,11 +489,13 @@ func (v *validator) processOp(op Operation) {
489489
break
490490
}
491491
readObservation := &observedRead{Key: t.Key}
492+
var shouldObserveRead bool
492493
writeObservation := &observedWrite{
493494
Key: t.Key,
494495
Seq: t.Seq,
495496
Value: roachpb.MakeValueFromString(t.Value()),
496497
}
498+
var shouldObserveWrite bool
497499
// Consider two cases based on whether the CPut hit a ConditionFailedError.
498500
err := errorFromResult(t.Result)
499501
if e := (*kvpb.ConditionFailedError)(nil); errors.As(err, &e) {
@@ -504,7 +506,7 @@ func (v *validator) processOp(op Operation) {
504506
observedVal.RawBytes = e.ActualValue.RawBytes
505507
}
506508
readObservation.Value = observedVal
507-
v.curObservations = append(v.curObservations, readObservation)
509+
shouldObserveRead = true
508510
} else {
509511
// If the CPut succeeded, the expected value is observed, and the CPut's
510512
// write is also observed.
@@ -517,11 +519,21 @@ func (v *validator) processOp(op Operation) {
517519
observedVal = roachpb.MakeValueFromBytes(t.ExpVal)
518520
}
519521
readObservation.Value = observedVal
520-
v.curObservations = append(v.curObservations, readObservation)
522+
shouldObserveRead = true
521523
}
522524
if sv, ok := v.tryConsumeWrite(t.Key, t.Seq); ok {
523525
writeObservation.Timestamp = sv.Timestamp
524526
}
527+
shouldObserveWrite = true
528+
}
529+
// The read observation should be added before the write observation, since
530+
// that's the order in which the CPut executed. Moreover, the CPut read is
531+
// always non-locking, so if the observation filter is observeLocking, we
532+
// won't be adding it.
533+
if shouldObserveRead && v.observationFilter != observeLocking {
534+
v.curObservations = append(v.curObservations, readObservation)
535+
}
536+
if shouldObserveWrite {
525537
v.curObservations = append(v.curObservations, writeObservation)
526538
}
527539
if v.buffering == bufferingSingle {

0 commit comments

Comments
 (0)