Skip to content

Commit 8f92259

Browse files
craig[bot]RaduBerinde
andcommitted
Merge #144604
144604: kv: update uses of btree r=RaduBerinde a=RaduBerinde Use the newer btree implementation with generics. Informs: #144504 Release note: None Co-authored-by: Radu Berinde <[email protected]>
2 parents 5db957e + e5a2335 commit 8f92259

16 files changed

+180
-221
lines changed

pkg/kv/kvclient/kvcoord/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ go_library(
9898
"@com_github_cockroachdb_logtags//:logtags",
9999
"@com_github_cockroachdb_redact//:redact",
100100
"@com_github_gogo_protobuf//proto",
101-
"@com_github_raduberinde_btree//:btree",
101+
"@com_github_google_btree//:btree",
102102
"@io_opentelemetry_go_otel//attribute",
103103
],
104104
)

pkg/kv/kvclient/kvcoord/txn_interceptor_pipeliner.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"math"
1111
"sort"
1212

13-
gbtree "github.com/RaduBerinde/btree" // TODO(#144504): switch to the newer btree
1413
"github.com/cockroachdb/cockroach/pkg/kv/kvpb"
1514
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/concurrency/lock"
1615
"github.com/cockroachdb/cockroach/pkg/roachpb"
@@ -22,6 +21,7 @@ import (
2221
"github.com/cockroachdb/cockroach/pkg/util/log"
2322
"github.com/cockroachdb/errors"
2423
"github.com/cockroachdb/redact"
24+
gbtree "github.com/google/btree"
2525
)
2626

2727
// The degree of the inFlightWrites btree.
@@ -1048,13 +1048,12 @@ func makeInFlightWrite(key roachpb.Key, seq enginepb.TxnSeq, str lock.Strength)
10481048
}}
10491049
}
10501050

1051-
// Less implements the gbtree.Item interface.
1051+
// less is the ordering function used by the B tree.
10521052
//
10531053
// inFlightWrites are ordered by Key, then by Sequence, then by Strength. Two
10541054
// inFlightWrites with the same Key but different Sequences and/or Strengths are
10551055
// not considered equal and are maintained separately in the inFlightWritesSet.
1056-
func (a *inFlightWrite) Less(bItem gbtree.Item) bool {
1057-
b := bItem.(*inFlightWrite)
1056+
func (a *inFlightWrite) less(b *inFlightWrite) bool {
10581057
kCmp := a.Key.Compare(b.Key)
10591058
if kCmp != 0 {
10601059
// Different Keys.
@@ -1077,7 +1076,7 @@ func (a *inFlightWrite) Less(bItem gbtree.Item) bool {
10771076
// writes, O(log n) removal of existing in-flight writes, and O(m + log n)
10781077
// retrieval over m in-flight writes that overlap with a given key.
10791078
type inFlightWriteSet struct {
1080-
t *gbtree.BTree
1079+
t *gbtree.BTreeG[*inFlightWrite]
10811080
bytes int64
10821081

10831082
// Avoids allocs.
@@ -1090,15 +1089,15 @@ type inFlightWriteSet struct {
10901089
func (s *inFlightWriteSet) insert(key roachpb.Key, seq enginepb.TxnSeq, str lock.Strength) {
10911090
if s.t == nil {
10921091
// Lazily initialize btree.
1093-
s.t = gbtree.New(txnPipelinerBtreeDegree)
1092+
s.t = gbtree.NewG[*inFlightWrite](txnPipelinerBtreeDegree, (*inFlightWrite).less)
10941093
}
10951094

10961095
w := s.alloc.alloc(key, seq, str)
1097-
delItem := s.t.ReplaceOrInsert(w)
1096+
delItem, _ := s.t.ReplaceOrInsert(w)
10981097
if delItem != nil {
10991098
// An in-flight write with the same key and sequence already existed in the
11001099
// set. We replaced it with an identical in-flight write.
1101-
*delItem.(*inFlightWrite) = inFlightWrite{} // for GC
1100+
*delItem = inFlightWrite{} // for GC
11021101
} else {
11031102
s.bytes += keySize(key)
11041103
}
@@ -1114,12 +1113,12 @@ func (s *inFlightWriteSet) remove(key roachpb.Key, seq enginepb.TxnSeq, str lock
11141113

11151114
// Delete the write from the in-flight writes set.
11161115
s.tmp1 = makeInFlightWrite(key, seq, str)
1117-
delItem := s.t.Delete(&s.tmp1)
1116+
delItem, _ := s.t.Delete(&s.tmp1)
11181117
if delItem == nil {
11191118
// The write was already proven or the txn epoch was incremented.
11201119
return
11211120
}
1122-
*delItem.(*inFlightWrite) = inFlightWrite{} // for GC
1121+
*delItem = inFlightWrite{} // for GC
11231122
s.bytes -= keySize(key)
11241123

11251124
// Assert that the byte accounting is believable.
@@ -1136,8 +1135,8 @@ func (s *inFlightWriteSet) ascend(f func(w *inFlightWrite)) {
11361135
// Set is empty.
11371136
return
11381137
}
1139-
s.t.Ascend(func(i gbtree.Item) bool {
1140-
f(i.(*inFlightWrite))
1138+
s.t.Ascend(func(i *inFlightWrite) bool {
1139+
f(i)
11411140
return true
11421141
})
11431142
}
@@ -1157,8 +1156,8 @@ func (s *inFlightWriteSet) ascendRange(start, end roachpb.Key, f func(w *inFligh
11571156
// Range lookup.
11581157
s.tmp2 = makeInFlightWrite(end, 0, 0)
11591158
}
1160-
s.t.AscendRange(&s.tmp1, &s.tmp2, func(i gbtree.Item) bool {
1161-
f(i.(*inFlightWrite))
1159+
s.t.AscendRange(&s.tmp1, &s.tmp2, func(i *inFlightWrite) bool {
1160+
f(i)
11621161
return true
11631162
})
11641163
}

pkg/kv/kvclient/kvcoord/txn_interceptor_pipeliner_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func TestTxnPipelinerTrackInFlightWrites(t *testing.T) {
208208
require.NotNil(t, br)
209209
require.Equal(t, 1, tp.ifWrites.len())
210210

211-
w := tp.ifWrites.t.Min().(*inFlightWrite)
211+
w, _ := tp.ifWrites.t.Min()
212212
require.Equal(t, putArgs.Key, w.Key)
213213
require.Equal(t, putArgs.Sequence, w.Sequence)
214214

@@ -266,10 +266,10 @@ func TestTxnPipelinerTrackInFlightWrites(t *testing.T) {
266266
require.Nil(t, pErr)
267267
require.Equal(t, 4, tp.ifWrites.len())
268268

269-
wMin := tp.ifWrites.t.Min().(*inFlightWrite)
269+
wMin, _ := tp.ifWrites.t.Min()
270270
require.Equal(t, cputArgs.Key, wMin.Key)
271271
require.Equal(t, cputArgs.Sequence, wMin.Sequence)
272-
wMax := tp.ifWrites.t.Max().(*inFlightWrite)
272+
wMax, _ := tp.ifWrites.t.Max()
273273
require.Equal(t, delArgs.Key, wMax.Key)
274274
require.Equal(t, delArgs.Sequence, wMax.Sequence)
275275

@@ -384,10 +384,10 @@ func TestTxnPipelinerTrackInFlightWritesPaginatedResponse(t *testing.T) {
384384
require.NotNil(t, br)
385385
require.Equal(t, 2, tp.ifWrites.len())
386386

387-
w := tp.ifWrites.t.Min().(*inFlightWrite)
387+
w, _ := tp.ifWrites.t.Min()
388388
require.Equal(t, putArgs1.Key, w.Key)
389389
require.Equal(t, putArgs1.Sequence, w.Sequence)
390-
w = tp.ifWrites.t.Max().(*inFlightWrite)
390+
w, _ = tp.ifWrites.t.Max()
391391
require.Equal(t, putArgs2.Key, w.Key)
392392
require.Equal(t, putArgs2.Sequence, w.Sequence)
393393

@@ -434,7 +434,7 @@ func TestTxnPipelinerTrackInFlightWritesPaginatedResponse(t *testing.T) {
434434
require.Nil(t, pErr)
435435
require.Equal(t, 1, tp.ifWrites.len())
436436

437-
w = tp.ifWrites.t.Min().(*inFlightWrite)
437+
w, _ = tp.ifWrites.t.Min()
438438
require.Equal(t, putArgs2.Key, w.Key)
439439
require.Equal(t, putArgs2.Sequence, w.Sequence)
440440
}

pkg/kv/kvserver/BUILD.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ go_library(
263263
"@com_github_kr_pretty//:pretty",
264264
"@com_github_prometheus_client_golang//prometheus",
265265
"@com_github_prometheus_client_model//go",
266-
"@com_github_raduberinde_btree//:btree",
266+
"@com_github_raduberinde_btreemap//:btreemap",
267267
"@io_opentelemetry_go_otel//attribute",
268268
"@org_golang_google_grpc//:grpc",
269269
"@org_golang_x_time//rate",
@@ -577,7 +577,7 @@ go_test(
577577
"@com_github_lib_pq//:pq",
578578
"@com_github_olekukonko_tablewriter//:tablewriter",
579579
"@com_github_prometheus_common//expfmt",
580-
"@com_github_raduberinde_btree//:btree",
580+
"@com_github_raduberinde_btreemap//:btreemap",
581581
"@com_github_stretchr_testify//assert",
582582
"@com_github_stretchr_testify//require",
583583
"@org_golang_google_grpc//:grpc",

pkg/kv/kvserver/asim/state/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ go_library(
4242
"//pkg/util/metric",
4343
"//pkg/util/stop",
4444
"//pkg/util/timeutil",
45-
"@com_github_raduberinde_btree//:btree",
45+
"@com_github_google_btree//:btree",
4646
"@org_golang_google_protobuf//proto",
4747
],
4848
)

pkg/kv/kvserver/asim/state/change.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import (
99
"fmt"
1010
"time"
1111

12-
"github.com/RaduBerinde/btree" // TODO(#144504): switch to the newer btree
1312
"github.com/cockroachdb/cockroach/pkg/kv/kvpb"
1413
"github.com/cockroachdb/cockroach/pkg/kv/kvserver"
1514
"github.com/cockroachdb/cockroach/pkg/roachpb"
15+
"github.com/google/btree"
1616
)
1717

1818
// Change is a state change for a range, to a target store that has some delay.
@@ -404,7 +404,7 @@ func (rc *ReplicaChange) Blocking() bool {
404404
// pushed before a change.
405405
type replicaChanger struct {
406406
lastTicket int
407-
completeAt *btree.BTree
407+
completeAt *btree.BTreeG[*pendingChange]
408408
pendingTickets map[int]Change
409409
pendingTarget map[StoreID]time.Time
410410
pendingRange map[RangeID]int
@@ -414,7 +414,7 @@ type replicaChanger struct {
414414
// replica changes.
415415
func NewReplicaChanger() Changer {
416416
return &replicaChanger{
417-
completeAt: btree.New(8),
417+
completeAt: btree.NewG[*pendingChange](8, (*pendingChange).Less),
418418
pendingTickets: make(map[int]Change),
419419
pendingTarget: make(map[StoreID]time.Time),
420420
pendingRange: make(map[RangeID]int),
@@ -426,11 +426,10 @@ type pendingChange struct {
426426
completeAt time.Time
427427
}
428428

429-
// Less is part of the btree.Item interface.
430-
func (pc *pendingChange) Less(than btree.Item) bool {
431-
// Targettal order on (completeAt, ticket)
432-
return pc.completeAt.Before(than.(*pendingChange).completeAt) ||
433-
(pc.completeAt.Equal(than.(*pendingChange).completeAt) && pc.ticket < than.(*pendingChange).ticket)
429+
func (pc *pendingChange) Less(than *pendingChange) bool {
430+
// Order on (completeAt, ticket).
431+
return pc.completeAt.Before(than.completeAt) ||
432+
(pc.completeAt.Equal(than.completeAt) && pc.ticket < than.ticket)
434433
}
435434

436435
// Push appends a state change to occur. There must not be more than one
@@ -477,8 +476,7 @@ func (rc *replicaChanger) Tick(tick time.Time, state State) {
477476
// NB: Add the smallest unit of time, in order to find all items in
478477
// [smallest, tick].
479478
pivot := &pendingChange{completeAt: tick.Add(time.Nanosecond)}
480-
rc.completeAt.AscendLessThan(pivot, func(i btree.Item) bool {
481-
nextChange, _ := i.(*pendingChange)
479+
rc.completeAt.AscendLessThan(pivot, func(nextChange *pendingChange) bool {
482480
changeList = append(changeList, nextChange)
483481
return true
484482
})

pkg/kv/kvserver/asim/state/impl.go

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"strings"
1818
"time"
1919

20-
"github.com/RaduBerinde/btree" // TODO(#144504): switch to the newer btree
2120
"github.com/cockroachdb/cockroach/pkg/kv/kvserver"
2221
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/allocator"
2322
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/allocator/allocatorimpl"
@@ -34,6 +33,7 @@ import (
3433
"github.com/cockroachdb/cockroach/pkg/spanconfig/spanconfigreporter"
3534
"github.com/cockroachdb/cockroach/pkg/util/hlc"
3635
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
36+
"github.com/google/btree"
3737
)
3838

3939
type state struct {
@@ -88,28 +88,26 @@ func newState(settings *config.SimulationSettings) *state {
8888
type rmap struct {
8989
// NB: Both rangeTree and rangeMap hold references to ranges. They must
9090
// both be updated on insertion and deletion to maintain consistent state.
91-
rangeTree *btree.BTree
91+
rangeTree *btree.BTreeG[*rng]
9292
rangeMap map[RangeID]*rng
9393

9494
// Unique ID generator for Ranges.
9595
rangeSeqGen RangeID
9696
}
9797

9898
func newRMap() *rmap {
99+
lessFn := func(a, b *rng) bool {
100+
return a.startKey < b.startKey
101+
}
99102
rmap := &rmap{
100-
rangeTree: btree.New(8),
103+
rangeTree: btree.NewG[*rng](8, lessFn),
101104
rangeMap: make(map[RangeID]*rng),
102105
}
103106

104107
rmap.initFirstRange()
105108
return rmap
106109
}
107110

108-
// Less is part of the btree.Item interface.
109-
func (r *rng) Less(than btree.Item) bool {
110-
return r.startKey < than.(*rng).startKey
111-
}
112-
113111
// initFirstRange initializes the first range within the rangemap, with
114112
// [MinKey, MaxKey) start and end key. All other ranges are split from this.
115113
func (rm *rmap) initFirstRange() {
@@ -164,8 +162,7 @@ func (s *state) String() string {
164162
builder := &strings.Builder{}
165163

166164
orderedRanges := []*rng{}
167-
s.ranges.rangeTree.Ascend(func(i btree.Item) bool {
168-
r := i.(*rng)
165+
s.ranges.rangeTree.Ascend(func(r *rng) bool {
169166
orderedRanges = append(orderedRanges, r)
170167
return !r.desc.EndKey.Equal(MaxKey.ToRKey())
171168
})
@@ -330,8 +327,8 @@ func (s *state) rangeFor(key Key) *rng {
330327
var r *rng
331328
// If keyToFind equals to MinKey of the range, we found the right range, if
332329
// the range is less than keyToFind then this is the right range also.
333-
s.ranges.rangeTree.DescendLessOrEqual(keyToFind, func(i btree.Item) bool {
334-
r = i.(*rng)
330+
s.ranges.rangeTree.DescendLessOrEqual(keyToFind, func(i *rng) bool {
331+
r = i
335332
return false
336333
})
337334
return r
@@ -688,8 +685,7 @@ func (s *state) SetSpanConfig(span roachpb.Span, config *roachpb.SpanConfig) {
688685
// [f, z) - keeps old span config from [c,z)
689686

690687
splitsRequired := []Key{}
691-
s.ranges.rangeTree.DescendLessOrEqual(&rng{startKey: startKey}, func(i btree.Item) bool {
692-
cur, _ := i.(*rng)
688+
s.ranges.rangeTree.DescendLessOrEqual(&rng{startKey: startKey}, func(cur *rng) bool {
693689
rStart := cur.startKey
694690
// There are two cases we handle:
695691
// (1) rStart == startKey: We don't need to split.
@@ -702,8 +698,7 @@ func (s *state) SetSpanConfig(span roachpb.Span, config *roachpb.SpanConfig) {
702698
return false
703699
})
704700

705-
s.ranges.rangeTree.DescendLessOrEqual(&rng{startKey: endKey}, func(i btree.Item) bool {
706-
cur, _ := i.(*rng)
701+
s.ranges.rangeTree.DescendLessOrEqual(&rng{startKey: endKey}, func(cur *rng) bool {
707702
rEnd := cur.endKey
708703
rStart := cur.startKey
709704
if rStart == endKey {
@@ -732,8 +727,7 @@ func (s *state) SetSpanConfig(span roachpb.Span, config *roachpb.SpanConfig) {
732727
}
733728

734729
// Apply the span config to all the ranges affected.
735-
s.ranges.rangeTree.AscendGreaterOrEqual(&rng{startKey: startKey}, func(i btree.Item) bool {
736-
cur, _ := i.(*rng)
730+
s.ranges.rangeTree.AscendGreaterOrEqual(&rng{startKey: startKey}, func(cur *rng) bool {
737731
if cur.startKey == endKey {
738732
return false
739733
}
@@ -800,16 +794,15 @@ func (s *state) SplitRange(splitKey Key) (Range, Range, bool) {
800794
endKey := Key(math.MaxInt32)
801795
failed := false
802796
// Find the sucessor range in the range map, to determine the endkey.
803-
ranges.rangeTree.AscendGreaterOrEqual(r, func(i btree.Item) bool {
797+
ranges.rangeTree.AscendGreaterOrEqual(r, func(i *rng) bool {
804798
// The min key already exists in the range map, we cannot return a new
805799
// range.
806-
if !r.Less(i) {
800+
if r.startKey == i.startKey {
807801
failed = true
808802
return false
809803
}
810804

811-
successorRange, _ := i.(*rng)
812-
endKey = successorRange.startKey
805+
endKey = i.startKey
813806
return false
814807
})
815808

@@ -822,10 +815,10 @@ func (s *state) SplitRange(splitKey Key) (Range, Range, bool) {
822815
var predecessorRange *rng
823816
// Find the predecessor range, to update it's endkey to the new range's min
824817
// key.
825-
ranges.rangeTree.DescendLessOrEqual(r, func(i btree.Item) bool {
818+
ranges.rangeTree.DescendLessOrEqual(r, func(i *rng) bool {
826819
// The case where the min key already exists cannot occur here, as the
827820
// failed flag will have been set above.
828-
predecessorRange, _ = i.(*rng)
821+
predecessorRange = i
829822
return false
830823
})
831824

@@ -998,8 +991,7 @@ func (s *state) ApplyLoad(lb workload.LoadBatch) {
998991
// that range is not larger than the any key of the remaining load events.
999992
iter := n - 1
1000993
max := &rng{startKey: Key(lb[iter].Key)}
1001-
s.ranges.rangeTree.DescendLessOrEqual(max, func(i btree.Item) bool {
1002-
next, _ := i.(*rng)
994+
s.ranges.rangeTree.DescendLessOrEqual(max, func(next *rng) bool {
1003995
for iter > -1 && lb[iter].Key >= int64(next.startKey) {
1004996
s.applyLoad(next, lb[iter])
1005997
iter--

pkg/kv/kvserver/asim/state/state_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ func TestRangeMap(t *testing.T) {
8484
// Assert that the first range is correctly initialized upon creation of a
8585
// new state.
8686
require.Len(t, s.ranges.rangeMap, 1)
87-
require.Equal(t, s.ranges.rangeTree.Max(), s.ranges.rangeTree.Min())
87+
maxRes, _ := s.ranges.rangeTree.Max()
88+
minRes, _ := s.ranges.rangeTree.Min()
89+
require.Equal(t, maxRes, minRes)
8890
firstRange := s.ranges.rangeMap[1]
8991
require.Equal(t, s.rangeFor(MinKey), firstRange)
9092
require.Equal(t, firstRange.startKey, MinKey)

0 commit comments

Comments
 (0)