@@ -2865,12 +2865,18 @@ func TestTxnWriteBufferElidesUnnecessaryLockingRequests(t *testing.T) {
2865
2865
// it locks. Every place where this is false represents a missed opportunity
2866
2866
// to avoid a locking request.
2867
2867
buffersLock bool
2868
+ // bufferedLockStr indicates the strength of the lock that is buffered. Used
2869
+ // in conjunction with buffersLock above.
2870
+ bufferedLockStr lock.Strength
2868
2871
// isFullyCovered, when true, indicates that this request can be served
2869
- // completely from the buffer if a previous request locked the value. This
2870
- // is different from requiresValue as it indicates that requests that aren't
2871
- // fully covered must always be sent to KV since there is no way to know if
2872
- // the buffer has all required required values.
2873
- isFullyCovered bool
2872
+ // completely from the buffer if a previous request locked the value at an
2873
+ // equal or higher lock strength. If the request is never fully covered, use
2874
+ // lock.None.
2875
+ //
2876
+ // This is different from requiresValue as it
2877
+ // indicates that requests that aren't fully covered must always be sent to
2878
+ // KV since there is no way to know if the buffer has all required values.
2879
+ isFullyCoveredByLockStrength lock.Strength
2874
2880
2875
2881
generateRequest func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction )
2876
2882
optionalGenSecondRequest func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction )
@@ -2884,24 +2890,26 @@ func TestTxnWriteBufferElidesUnnecessaryLockingRequests(t *testing.T) {
2884
2890
keyC := roachpb .Key ("c" )
2885
2891
2886
2892
// A number of the requests expect a single locking get to be produced. This
2887
- // validate function is shared across them.
2888
- validateLockingGet := func (t * testing.T , ba * kvpb.BatchRequest ) * kvpb.BatchResponse {
2889
- getReq := ba .Requests [0 ].GetGet ()
2890
- require .NotNil (t , getReq )
2891
- require .Equal (t , lock .Exclusive , getReq .KeyLockingStrength )
2892
- require .Equal (t , lock .Unreplicated , getReq .KeyLockingDurability )
2893
- resp := ba .CreateReply ()
2894
- resp .Txn = ba .Txn
2895
- return resp
2893
+ // validator function is shared across them.
2894
+ validateLockingGetOfStr := func (str lock.Strength ) func (t * testing.T , ba * kvpb.BatchRequest ) * kvpb.BatchResponse {
2895
+ return func (t * testing.T , ba * kvpb.BatchRequest ) * kvpb.BatchResponse {
2896
+ getReq := ba .Requests [0 ].GetGet ()
2897
+ require .NotNil (t , getReq )
2898
+ require .Equal (t , str , getReq .KeyLockingStrength )
2899
+ require .Equal (t , lock .Unreplicated , getReq .KeyLockingDurability ) // NB: always Unreplicated
2900
+ resp := ba .CreateReply ()
2901
+ resp .Txn = ba .Txn
2902
+ return resp
2903
+ }
2896
2904
}
2897
2905
2898
2906
reqs := []lockingRequests {
2899
2907
{
2900
- name : "ReplicatedLockingScanScanFormat=KEY_VALUES" ,
2901
- buffersLock : false ,
2902
- buffersValue : false ,
2903
- requiresValue : true ,
2904
- isFullyCovered : false ,
2908
+ name : "ReplicatedLockingScanScanFormat=KEY_VALUES" ,
2909
+ buffersLock : false ,
2910
+ buffersValue : false ,
2911
+ requiresValue : true ,
2912
+ isFullyCoveredByLockStrength : lock . None , // Scans are never covered
2905
2913
generateRequest : func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction ) {
2906
2914
ba .Add (& kvpb.ScanRequest {
2907
2915
KeyLockingStrength : lock .Exclusive ,
@@ -2923,11 +2931,11 @@ func TestTxnWriteBufferElidesUnnecessaryLockingRequests(t *testing.T) {
2923
2931
},
2924
2932
},
2925
2933
{
2926
- name : "ReplicatedLockingScanScanFormat=BATCH_RESPONSE" ,
2927
- buffersLock : false ,
2928
- buffersValue : false ,
2929
- requiresValue : true ,
2930
- isFullyCovered : false ,
2934
+ name : "ReplicatedLockingScanScanFormat=BATCH_RESPONSE" ,
2935
+ buffersLock : false ,
2936
+ buffersValue : false ,
2937
+ requiresValue : true ,
2938
+ isFullyCoveredByLockStrength : lock . None , // Scans are never covered
2931
2939
generateRequest : func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction ) {
2932
2940
ba .Add (& kvpb.ScanRequest {
2933
2941
KeyLockingStrength : lock .Exclusive ,
@@ -2953,11 +2961,11 @@ func TestTxnWriteBufferElidesUnnecessaryLockingRequests(t *testing.T) {
2953
2961
},
2954
2962
},
2955
2963
{
2956
- name : "ReplicatedLockingReverseScan" ,
2957
- buffersLock : false ,
2958
- buffersValue : false ,
2959
- requiresValue : true ,
2960
- isFullyCovered : false ,
2964
+ name : "ReplicatedLockingReverseScan" ,
2965
+ buffersLock : false ,
2966
+ buffersValue : false ,
2967
+ requiresValue : true ,
2968
+ isFullyCoveredByLockStrength : lock . None , // ReverseScans are never covered
2961
2969
generateRequest : func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction ) {
2962
2970
ba .Add (& kvpb.ReverseScanRequest {
2963
2971
KeyLockingStrength : lock .Exclusive ,
@@ -2980,11 +2988,11 @@ func TestTxnWriteBufferElidesUnnecessaryLockingRequests(t *testing.T) {
2980
2988
},
2981
2989
},
2982
2990
{
2983
- name : "ReplicatedLockingGet" ,
2984
- buffersLock : false ,
2985
- buffersValue : false ,
2986
- requiresValue : true ,
2987
- isFullyCovered : true ,
2991
+ name : "ReplicatedLockingGet(Strength=Exclusive) " ,
2992
+ buffersLock : false ,
2993
+ buffersValue : false ,
2994
+ requiresValue : true ,
2995
+ isFullyCoveredByLockStrength : lock . Exclusive ,
2988
2996
generateRequest : func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction ) {
2989
2997
getReq := & kvpb.GetRequest {
2990
2998
RequestHeader : kvpb.RequestHeader {Key : keyA , Sequence : txn .Sequence },
@@ -2993,42 +3001,77 @@ func TestTxnWriteBufferElidesUnnecessaryLockingRequests(t *testing.T) {
2993
3001
getReq .KeyLockingStrength = lock .Exclusive
2994
3002
ba .Add (getReq )
2995
3003
},
2996
- validateAndGenerateResponse : validateLockingGet ,
3004
+ validateAndGenerateResponse : validateLockingGetOfStr (lock .Exclusive ),
3005
+ },
3006
+ {
3007
+ name : "UnReplicatedLockingGet(Strength=Exclusive)" ,
3008
+ buffersLock : false ,
3009
+ buffersValue : false ,
3010
+ requiresValue : true ,
3011
+ isFullyCoveredByLockStrength : lock .Exclusive ,
3012
+ generateRequest : func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction ) {
3013
+ getReq := & kvpb.GetRequest {
3014
+ RequestHeader : kvpb.RequestHeader {Key : keyA , Sequence : txn .Sequence },
3015
+ }
3016
+ getReq .KeyLockingDurability = lock .Unreplicated
3017
+ getReq .KeyLockingStrength = lock .Exclusive
3018
+ ba .Add (getReq )
3019
+ },
3020
+ validateAndGenerateResponse : validateLockingGetOfStr (lock .Exclusive ),
3021
+ },
3022
+ {
3023
+ name : "ReplicatedLockingGet(Strength=Shared)" ,
3024
+ buffersLock : false ,
3025
+ buffersValue : false ,
3026
+ requiresValue : true ,
3027
+ isFullyCoveredByLockStrength : lock .Shared ,
3028
+ generateRequest : func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction ) {
3029
+ getReq := & kvpb.GetRequest {
3030
+ RequestHeader : kvpb.RequestHeader {Key : keyA , Sequence : txn .Sequence },
3031
+ }
3032
+ getReq .KeyLockingDurability = lock .Replicated
3033
+ getReq .KeyLockingStrength = lock .Shared
3034
+ ba .Add (getReq )
3035
+ },
3036
+ validateAndGenerateResponse : validateLockingGetOfStr (lock .Shared ),
2997
3037
},
2998
3038
{
2999
- name : "PutMustAcquireExclusive" ,
3000
- buffersLock : true ,
3001
- buffersValue : true ,
3002
- requiresValue : false ,
3003
- isFullyCovered : true ,
3039
+ name : "PutMustAcquireExclusive" ,
3040
+ buffersLock : true ,
3041
+ bufferedLockStr : lock .Exclusive ,
3042
+ buffersValue : true ,
3043
+ requiresValue : false ,
3044
+ isFullyCoveredByLockStrength : lock .Exclusive ,
3004
3045
generateRequest : func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction ) {
3005
3046
putReq := putArgs (keyA , valueAStr , txn .Sequence )
3006
3047
putReq .MustAcquireExclusiveLock = true
3007
3048
ba .Add (putReq )
3008
3049
},
3009
- validateAndGenerateResponse : validateLockingGet ,
3050
+ validateAndGenerateResponse : validateLockingGetOfStr ( lock . Exclusive ) ,
3010
3051
},
3011
3052
{
3012
- name : "DeleteMustAcquireExclusive" ,
3013
- buffersLock : true ,
3014
- buffersValue : true ,
3053
+ name : "DeleteMustAcquireExclusive" ,
3054
+ buffersLock : true ,
3055
+ bufferedLockStr : lock .Exclusive ,
3056
+ buffersValue : true ,
3015
3057
// Delete requires a value to correctly return the number of deleted row.
3016
- requiresValue : true ,
3017
- isFullyCovered : true ,
3058
+ requiresValue : true ,
3059
+ isFullyCoveredByLockStrength : lock . Exclusive ,
3018
3060
generateRequest : func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction ) {
3019
3061
delReq := delArgs (keyA , txn .Sequence )
3020
3062
delReq .MustAcquireExclusiveLock = true
3021
3063
ba .Add (delReq )
3022
3064
},
3023
- validateAndGenerateResponse : validateLockingGet ,
3065
+ validateAndGenerateResponse : validateLockingGetOfStr ( lock . Exclusive ) ,
3024
3066
},
3025
3067
{
3026
- name : "ConditionalPut" ,
3027
- buffersLock : true ,
3028
- buffersValue : true ,
3068
+ name : "ConditionalPut" ,
3069
+ buffersLock : true ,
3070
+ bufferedLockStr : lock .Exclusive ,
3071
+ buffersValue : true ,
3029
3072
// ConditionalPut requires a value to evaluate its expected bytes condition.
3030
- requiresValue : true ,
3031
- isFullyCovered : true ,
3073
+ requiresValue : true ,
3074
+ isFullyCoveredByLockStrength : lock . Exclusive ,
3032
3075
generateRequest : func (t * testing.T , ba * kvpb.BatchRequest , txn * roachpb.Transaction ) {
3033
3076
ba .Add (cputArgs (keyA , valueAStr , "" , txn .Sequence ))
3034
3077
},
@@ -3039,7 +3082,7 @@ func TestTxnWriteBufferElidesUnnecessaryLockingRequests(t *testing.T) {
3039
3082
cput .AllowIfDoesNotExist = true
3040
3083
ba .Add (cput )
3041
3084
},
3042
- validateAndGenerateResponse : validateLockingGet ,
3085
+ validateAndGenerateResponse : validateLockingGetOfStr ( lock . Exclusive ) ,
3043
3086
},
3044
3087
}
3045
3088
@@ -3080,8 +3123,12 @@ func TestTxnWriteBufferElidesUnnecessaryLockingRequests(t *testing.T) {
3080
3123
secondReq .generateRequest (t , ba , & txn )
3081
3124
}
3082
3125
3126
+ // The second request is fully covered if the first request has already
3127
+ // acquired a lock at a sufficient lock strength.
3128
+ isFullyCovered := secondReq .isFullyCoveredByLockStrength != lock .None &&
3129
+ firstReq .bufferedLockStr >= secondReq .isFullyCoveredByLockStrength
3083
3130
mockSender .MockSend (func (ba * kvpb.BatchRequest ) (* kvpb.BatchResponse , * kvpb.Error ) {
3084
- if secondReq . isFullyCovered {
3131
+ if isFullyCovered {
3085
3132
resp := ba .CreateReply ()
3086
3133
resp .Txn = ba .Txn
3087
3134
return resp , nil
@@ -3092,7 +3139,7 @@ func TestTxnWriteBufferElidesUnnecessaryLockingRequests(t *testing.T) {
3092
3139
})
3093
3140
3094
3141
expectedCalls := 0
3095
- if ! secondReq . isFullyCovered {
3142
+ if ! isFullyCovered {
3096
3143
expectedCalls = 1
3097
3144
}
3098
3145
numCalled := mockSender .NumCalled ()
0 commit comments