Skip to content

Commit bb59d45

Browse files
committed
kvcoord: rename transformation to requestRecord in the write buffer
Now that we keep tranck of all requests as transformations, the term "transformation" doesn't make sense because some of the requests aren't actually transformed. This commit renames all transformation-related terms and replaces "transformation" with "requestRecord", while also adding a new `transformed` boolean field in `requestRecord` to indicate if a request was actually transformed. Part of: #146103 Release note: None
1 parent 65476fc commit bb59d45

File tree

1 file changed

+71
-60
lines changed

1 file changed

+71
-60
lines changed

pkg/kv/kvclient/kvcoord/txn_interceptor_write_buffer.go

Lines changed: 71 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ func (twb *txnWriteBuffer) SendLocked(
242242
return nil, kvpb.NewError(err)
243243
}
244244

245-
transformedBa, ts, pErr := twb.applyTransformations(ctx, ba)
245+
transformedBa, rr, pErr := twb.applyTransformations(ctx, ba)
246246
if pErr != nil {
247247
return nil, pErr
248248
}
@@ -253,8 +253,8 @@ func (twb *txnWriteBuffer) SendLocked(
253253
// left with an empty batch after applying transformations, eschew sending
254254
// anything to KV.
255255
br := ba.CreateReply()
256-
for i, t := range ts {
257-
br.Responses[i], pErr = t.toResp(ctx, twb, kvpb.ResponseUnion{}, ba.Txn)
256+
for i, record := range rr {
257+
br.Responses[i], pErr = record.toResp(ctx, twb, kvpb.ResponseUnion{}, ba.Txn)
258258
if pErr != nil {
259259
return nil, pErr
260260
}
@@ -265,10 +265,10 @@ func (twb *txnWriteBuffer) SendLocked(
265265

266266
br, pErr := twb.wrapped.SendLocked(ctx, transformedBa)
267267
if pErr != nil {
268-
return nil, twb.adjustError(ctx, transformedBa, ts, pErr)
268+
return nil, twb.adjustError(ctx, transformedBa, rr, pErr)
269269
}
270270

271-
return twb.mergeResponseWithTransformations(ctx, ts, br)
271+
return twb.mergeResponseWithRequestRecords(ctx, rr, br)
272272
}
273273

274274
func (twb *txnWriteBuffer) batchRequiresFlush(ctx context.Context, ba *kvpb.BatchRequest) bool {
@@ -442,7 +442,7 @@ func (twb *txnWriteBuffer) estimateSize(ba *kvpb.BatchRequest) int64 {
442442
// adjustError adjusts the provided error based on the transformations made by
443443
// the txnWriteBuffer to the batch request before sending it to KV.
444444
func (twb *txnWriteBuffer) adjustError(
445-
ctx context.Context, ba *kvpb.BatchRequest, ts transformations, pErr *kvpb.Error,
445+
ctx context.Context, ba *kvpb.BatchRequest, rr requestRecords, pErr *kvpb.Error,
446446
) *kvpb.Error {
447447
// Fix the error index to hide the impact of any requests that were
448448
// transformed.
@@ -452,12 +452,12 @@ func (twb *txnWriteBuffer) adjustError(
452452
// therefore weren't sent to the KV layer. We can then adjust the error
453453
// index accordingly.
454454
numStripped := int32(0)
455-
numOriginalRequests := len(ba.Requests) + len(ts)
455+
numOriginalRequests := len(ba.Requests) + len(rr)
456456
baIdx := int32(0)
457457
for i := range numOriginalRequests {
458-
if len(ts) > 0 && ts[0].index == i {
459-
curTs := ts[0]
460-
ts = ts[1:]
458+
if len(rr) > 0 && rr[0].index == i {
459+
curTs := rr[0]
460+
rr = rr[1:]
461461
if curTs.stripped {
462462
numStripped++
463463
} else {
@@ -639,61 +639,64 @@ func (twb *txnWriteBuffer) closeLocked() {}
639639

640640
// applyTransformations applies any applicable transformations to the supplied
641641
// batch request. In doing so, a new batch request with transformations applied
642-
// along with a list of transformations that were applied is returned. The
643-
// caller must handle these transformations on the response path.
642+
// along with a list of requestRecords is returned. The caller must handle the
643+
// transformations on the response path.
644644
//
645645
// Some examples of transformations include:
646646
//
647-
// 1. Blind writes (Put/Delete requests) are buffered locally. When they the
648-
// original request has MustAcquireExclusiveLock set, a locking Get is used to
649-
// acquire the lock.
647+
// 1. Blind writes (Put/Delete requests) are buffered locally. When the original
648+
// request has MustAcquireExclusiveLock set, a locking Get is used to acquire
649+
// the lock.
650650
// 2. Point reads (Get requests) are served from the buffer and stripped from
651651
// the batch iff the key has seen a buffered write.
652652
// 3. Scans are always sent to the KV layer, but if the key span being scanned
653653
// overlaps with any buffered writes, then the response from the KV layer needs
654-
// to be merged with buffered writes. These are collected as transformations.
654+
// to be merged with buffered writes. These are collected as requestRecords.
655655
// 4. ReverseScans, similar to scans, are also always sent to the KV layer and
656656
// their response needs to be merged with any buffered writes. The only
657657
// difference is the direction in which the buffer is iterated when doing the
658-
// merge. As a result, they're also collected as tranformations.
658+
// merge. As a result, they're also collected as requestRecords.
659659
// 5. Conditional Puts are decomposed into a locking Get followed by a Put. The
660660
// Put is buffered locally if the condition evaluates successfully using the
661661
// Get's response. Otherwise, a ConditionFailedError is returned.
662662
//
663663
// TODO(arul): Augment this comment as these expand.
664664
func (twb *txnWriteBuffer) applyTransformations(
665665
ctx context.Context, ba *kvpb.BatchRequest,
666-
) (*kvpb.BatchRequest, transformations, *kvpb.Error) {
666+
) (*kvpb.BatchRequest, requestRecords, *kvpb.Error) {
667667
baRemote := ba.ShallowCopy()
668668
// TODO(arul): We could improve performance here by pre-allocating
669669
// baRemote.Requests to the correct size by counting the number of Puts/Dels
670-
// in ba.Requests. The same for the transformations slice. We could also
670+
// in ba.Requests. The same for the requestRecords slice. We could also
671671
// allocate the right number of ResponseUnion, PutResponse, and DeleteResponse
672672
// objects as well.
673673
baRemote.Requests = nil
674674

675-
ts := make(transformations, 0, len(ba.Requests))
675+
rr := make(requestRecords, 0, len(ba.Requests))
676676
for i, ru := range ba.Requests {
677677
req := ru.GetInner()
678-
// Track a transformation for the request regardless of the type, and
679-
// regardless of whether it was served from the buffer or not. For truly
678+
// Track a requestRecord for the request regardless of the type, and
679+
// regardless of whether it was served from the buffer or not. For
680680
// transformed requests (e.g. CPut) this is expected. For Gets and Scans, we
681-
// need to track a transformation because we haven't buffered any writes
681+
// need to track a requestRecord because we haven't buffered any writes
682682
// from our current batch in the buffer yet, so checking the buffer here, at
683683
// request time, isn't sufficient to determine whether the request needs to
684684
// serve a read from the buffer before returning a response or not.
685685
//
686686
// Only QueryLocksRequest and LeaseInfoRequest don't require a tracking
687-
// transformation, but it's harmless to add one, and it simplifies the code.
687+
// requestRecord, but it's harmless to add one, and it simplifies the code.
688688
//
689-
// The stripped field will be set below for specific stripped requests.
690-
tr := transformation{
689+
// The stripped and transformed fields will be set below for specific
690+
// requests.
691+
record := requestRecord{
691692
stripped: false,
693+
transformed: false,
692694
index: i,
693695
origRequest: req,
694696
}
695697
switch t := req.(type) {
696698
case *kvpb.ConditionalPutRequest:
699+
record.transformed = true
697700
// NB: Regardless of whether there is already a buffered write on
698701
// this key or not, we need to send a locking Get to the KV layer to
699702
// acquire a lock. However, if we had knowledge of what locks the
@@ -732,7 +735,8 @@ func (twb *txnWriteBuffer) applyTransformations(
732735
})
733736
baRemote.Requests = append(baRemote.Requests, getReqU)
734737
}
735-
tr.stripped = !t.MustAcquireExclusiveLock
738+
record.stripped = !t.MustAcquireExclusiveLock
739+
record.transformed = t.MustAcquireExclusiveLock
736740

737741
case *kvpb.DeleteRequest:
738742
// If MustAcquireExclusiveLock flag is set on the DeleteRequest,
@@ -752,7 +756,8 @@ func (twb *txnWriteBuffer) applyTransformations(
752756
})
753757
baRemote.Requests = append(baRemote.Requests, getReqU)
754758
}
755-
tr.stripped = !t.MustAcquireExclusiveLock
759+
record.stripped = !t.MustAcquireExclusiveLock
760+
record.transformed = t.MustAcquireExclusiveLock
756761

757762
case *kvpb.GetRequest:
758763
// If the key is in the buffer, we must serve the read from the buffer.
@@ -783,7 +788,7 @@ func (twb *txnWriteBuffer) applyTransformations(
783788
// Wasn't served locally; send the request to the KV layer.
784789
baRemote.Requests = append(baRemote.Requests, ru)
785790
}
786-
tr.stripped = stripped
791+
record.stripped = stripped
787792

788793
case *kvpb.ScanRequest, *kvpb.ReverseScanRequest:
789794
// Regardless of whether the scan overlaps with any writes in the buffer
@@ -799,9 +804,9 @@ func (twb *txnWriteBuffer) applyTransformations(
799804
default:
800805
return nil, nil, kvpb.NewError(unsupportedMethodError(t.Method()))
801806
}
802-
ts = append(ts, tr)
807+
rr = append(rr, record)
803808
}
804-
return baRemote, ts, nil
809+
return baRemote, rr, nil
805810
}
806811

807812
// seekItemForSpan returns a bufferedWrite appropriate for use with a
@@ -1001,47 +1006,47 @@ func (twb *txnWriteBuffer) mergeBufferAndResp(
10011006
}
10021007
}
10031008

1004-
// mergeResponsesWithTransformations merges responses from the KV layer with the
1005-
// transformations that were applied by the txnWriteBuffer before sending the
1006-
// batch request. As a result, interceptors above the txnWriteBuffer remain
1007-
// oblivious to its decision to buffer any writes.
1008-
func (twb *txnWriteBuffer) mergeResponseWithTransformations(
1009-
ctx context.Context, ts transformations, br *kvpb.BatchResponse,
1009+
// mergeResponseWithRequestRecords merges responses from the KV layer with the
1010+
// requestRecords and potential transformations applied by the txnWriteBuffer
1011+
// before sending the batch request. As a result, interceptors above the
1012+
// txnWriteBuffer remain oblivious to its decision to buffer any writes.
1013+
func (twb *txnWriteBuffer) mergeResponseWithRequestRecords(
1014+
ctx context.Context, rr requestRecords, br *kvpb.BatchResponse,
10101015
) (_ *kvpb.BatchResponse, pErr *kvpb.Error) {
1011-
if ts.Empty() && br == nil {
1016+
if rr.Empty() && br == nil {
10121017
log.Fatal(ctx, "unexpectedly found no transformations and no batch response")
1013-
} else if ts.Empty() {
1018+
} else if rr.Empty() {
10141019
return br, nil
10151020
}
10161021

10171022
// Figure out the length of the merged responses slice.
10181023
mergedRespsLen := len(br.Responses)
1019-
for _, t := range ts {
1024+
for _, t := range rr {
10201025
if t.stripped {
10211026
mergedRespsLen++
10221027
}
10231028
}
10241029
mergedResps := make([]kvpb.ResponseUnion, mergedRespsLen)
10251030
for i := range mergedResps {
1026-
if len(ts) > 0 && ts[0].index == i {
1027-
if !ts[0].stripped {
1031+
if len(rr) > 0 && rr[0].index == i {
1032+
if !rr[0].stripped {
10281033
// If the transformation wasn't stripped from the batch we sent to KV,
10291034
// we received a response for it, which then needs to be combined with
10301035
// what's in the write buffer.
10311036
resp := br.Responses[0]
1032-
mergedResps[i], pErr = ts[0].toResp(ctx, twb, resp, br.Txn)
1037+
mergedResps[i], pErr = rr[0].toResp(ctx, twb, resp, br.Txn)
10331038
if pErr != nil {
10341039
return nil, pErr
10351040
}
10361041
br.Responses = br.Responses[1:]
10371042
} else {
1038-
mergedResps[i], pErr = ts[0].toResp(ctx, twb, kvpb.ResponseUnion{}, br.Txn)
1043+
mergedResps[i], pErr = rr[0].toResp(ctx, twb, kvpb.ResponseUnion{}, br.Txn)
10391044
if pErr != nil {
10401045
return nil, pErr
10411046
}
10421047
}
10431048

1044-
ts = ts[1:]
1049+
rr = rr[1:]
10451050
continue
10461051
}
10471052

@@ -1053,26 +1058,32 @@ func (twb *txnWriteBuffer) mergeResponseWithTransformations(
10531058
return br, nil
10541059
}
10551060

1056-
// transformation is a modification applied by the txnWriteBuffer on a batch
1057-
// request that needs to be accounted for when returning the response.
1058-
type transformation struct {
1061+
// requestRecord stores a set of metadata fields about potential transformations
1062+
// applied by the txnWriteBuffer on a batch request that needs to be accounted
1063+
// for when returning the response.
1064+
type requestRecord struct {
10591065
// stripped, if true, indicates that the request was stripped from the batch
10601066
// and never sent to the KV layer.
10611067
stripped bool
1062-
// index of the request in the original batch to which the transformation
1068+
// transformed, if true, indicates that the request was transformed into a
1069+
// different request to be sent to the KV layer. If stripped is true, then
1070+
// transformed is always false; i.e. if the request was completely dropped,
1071+
// then it's not considered transformed.
1072+
transformed bool
1073+
// index of the request in the original batch to which the requestRecord
10631074
// applies.
10641075
index int
10651076
// origRequest is the original request that was transformed.
10661077
origRequest kvpb.Request
10671078
}
10681079

10691080
// toResp returns the response that should be added to the batch response as
1070-
// a result of applying the transformation.
1071-
func (t transformation) toResp(
1081+
// a result of applying the requestRecord.
1082+
func (rr requestRecord) toResp(
10721083
ctx context.Context, twb *txnWriteBuffer, br kvpb.ResponseUnion, txn *roachpb.Transaction,
10731084
) (kvpb.ResponseUnion, *kvpb.Error) {
10741085
var ru kvpb.ResponseUnion
1075-
switch req := t.origRequest.(type) {
1086+
switch req := rr.origRequest.(type) {
10761087
case *kvpb.ConditionalPutRequest:
10771088
// Evaluate the condition.
10781089
evalFn := mvcceval.MaybeConditionFailedError
@@ -1098,7 +1109,7 @@ func (t transformation) toResp(
10981109
)
10991110
if condFailedErr != nil {
11001111
pErr := kvpb.NewErrorWithTxn(condFailedErr, txn)
1101-
pErr.SetErrorIndex(int32(t.index))
1112+
pErr.SetErrorIndex(int32(rr.index))
11021113
return kvpb.ResponseUnion{}, pErr
11031114
}
11041115
// The condition was satisfied; buffer the write and return a
@@ -1157,13 +1168,13 @@ func (t transformation) toResp(
11571168
} else {
11581169
// The request wasn't served from the buffer; return the response from the
11591170
// KV layer.
1160-
assertTrue(!t.stripped, "we shouldn't be stripping requests that aren't served from the buffer")
1171+
assertTrue(!rr.stripped, "we shouldn't be stripping requests that aren't served from the buffer")
11611172
ru = br
11621173
}
11631174

11641175
case *kvpb.ScanRequest:
11651176
scanResp, err := twb.mergeWithScanResp(
1166-
t.origRequest.(*kvpb.ScanRequest), br.GetInner().(*kvpb.ScanResponse),
1177+
rr.origRequest.(*kvpb.ScanRequest), br.GetInner().(*kvpb.ScanResponse),
11671178
)
11681179
if err != nil {
11691180
return kvpb.ResponseUnion{}, kvpb.NewError(err)
@@ -1172,7 +1183,7 @@ func (t transformation) toResp(
11721183

11731184
case *kvpb.ReverseScanRequest:
11741185
reverseScanResp, err := twb.mergeWithReverseScanResp(
1175-
t.origRequest.(*kvpb.ReverseScanRequest), br.GetInner().(*kvpb.ReverseScanResponse),
1186+
rr.origRequest.(*kvpb.ReverseScanRequest), br.GetInner().(*kvpb.ReverseScanResponse),
11761187
)
11771188
if err != nil {
11781189
return kvpb.ResponseUnion{}, kvpb.NewError(err)
@@ -1190,11 +1201,11 @@ func (t transformation) toResp(
11901201
return ru, nil
11911202
}
11921203

1193-
// transformations is a list of transformations applied by the txnWriteBuffer.
1194-
type transformations []transformation
1204+
// requestRecords is a slice of requestRecord.
1205+
type requestRecords []requestRecord
11951206

1196-
func (t transformations) Empty() bool {
1197-
return len(t) == 0
1207+
func (rr requestRecords) Empty() bool {
1208+
return len(rr) == 0
11981209
}
11991210

12001211
// addToBuffer adds a write to the given key to the buffer.

0 commit comments

Comments
 (0)