Skip to content

Commit e5a2335

Browse files
committed
kvserver: switch to btreemap for store replica map
Epic: none Release note: None
1 parent 7459105 commit e5a2335

File tree

9 files changed

+125
-151
lines changed

9 files changed

+125
-151
lines changed

pkg/kv/kvserver/BUILD.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,10 @@ go_library(
260260
"@com_github_cockroachdb_pebble//vfs",
261261
"@com_github_cockroachdb_redact//:redact",
262262
"@com_github_gogo_protobuf//proto",
263-
"@com_github_google_btree//:btree",
264263
"@com_github_kr_pretty//:pretty",
265264
"@com_github_prometheus_client_golang//prometheus",
266265
"@com_github_prometheus_client_model//go",
266+
"@com_github_raduberinde_btreemap//:btreemap",
267267
"@io_opentelemetry_go_otel//attribute",
268268
"@org_golang_google_grpc//:grpc",
269269
"@org_golang_x_time//rate",
@@ -572,12 +572,12 @@ go_test(
572572
"@com_github_cockroachdb_redact//:redact",
573573
"@com_github_dustin_go_humanize//:go-humanize",
574574
"@com_github_gogo_protobuf//proto",
575-
"@com_github_google_btree//:btree",
576575
"@com_github_jackc_pgx_v5//:pgx",
577576
"@com_github_kr_pretty//:pretty",
578577
"@com_github_lib_pq//:pq",
579578
"@com_github_olekukonko_tablewriter//:tablewriter",
580579
"@com_github_prometheus_common//expfmt",
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/replica_placeholder.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,11 @@ type ReplicaPlaceholder struct {
8484
tainted int32 // atomic
8585
}
8686

87-
var _ rangeKeyItem = (*ReplicaPlaceholder)(nil)
88-
8987
// Desc returns the range Placeholder's descriptor.
9088
func (r *ReplicaPlaceholder) Desc() *roachpb.RangeDescriptor {
9189
return &r.rangeDesc
9290
}
9391

94-
func (r *ReplicaPlaceholder) key() roachpb.RKey {
95-
return r.Desc().StartKey
96-
}
97-
9892
func (r *ReplicaPlaceholder) String() string {
9993
tainted := ""
10094
if atomic.LoadInt32(&r.tainted) != 0 {

pkg/kv/kvserver/scanner_test.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"testing"
1212
"time"
1313

14+
"github.com/RaduBerinde/btreemap"
1415
"github.com/cockroachdb/cockroach/pkg/roachpb"
1516
"github.com/cockroachdb/cockroach/pkg/storage/enginepb"
1617
"github.com/cockroachdb/cockroach/pkg/testutils"
@@ -21,7 +22,6 @@ import (
2122
"github.com/cockroachdb/cockroach/pkg/util/syncutil"
2223
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
2324
"github.com/cockroachdb/errors"
24-
"github.com/google/btree"
2525
)
2626

2727
func makeAmbCtx() log.AmbientContext {
@@ -31,16 +31,15 @@ func makeAmbCtx() log.AmbientContext {
3131
// Test implementation of a range set backed by btree.BTree.
3232
type testRangeSet struct {
3333
syncutil.Mutex
34-
replicasByKey *btree.BTreeG[*Replica]
34+
replicasByKey *btreemap.BTreeMap[roachpb.RKey, *Replica]
3535
visited int
3636
}
3737

3838
// newTestRangeSet creates a new range set that has the count number of ranges.
3939
func newTestRangeSet(count int, t *testing.T) *testRangeSet {
40-
lessFn := func(a, b *Replica) bool {
41-
return a.startKey.Less(b.startKey)
40+
rs := &testRangeSet{
41+
replicasByKey: btreemap.New[roachpb.RKey, *Replica](64 /* degree */, roachpb.RKey.Compare),
4242
}
43-
rs := &testRangeSet{replicasByKey: btree.NewG[*Replica](64 /* degree */, lessFn)}
4443
for i := 0; i < count; i++ {
4544
desc := &roachpb.RangeDescriptor{
4645
RangeID: roachpb.RangeID(i),
@@ -59,7 +58,7 @@ func newTestRangeSet(count int, t *testing.T) *testRangeSet {
5958
}
6059
repl.shMu.state.Desc = desc
6160
repl.startKey = desc.StartKey // actually used by replicasByKey
62-
if exRngItem, _ := rs.replicasByKey.ReplaceOrInsert(repl); exRngItem != nil {
61+
if _, exRngItem, _ := rs.replicasByKey.ReplaceOrInsert(repl.startKey, repl); exRngItem != nil {
6362
t.Fatalf("failed to insert range %s", repl)
6463
}
6564
}
@@ -70,12 +69,15 @@ func (rs *testRangeSet) Visit(visitor func(*Replica) bool) {
7069
rs.Lock()
7170
defer rs.Unlock()
7271
rs.visited = 0
73-
rs.replicasByKey.Ascend(func(r *Replica) bool {
74-
rs.visited++
75-
rs.Unlock()
76-
defer rs.Lock()
77-
return visitor(r)
78-
})
72+
rs.replicasByKey.AscendFunc(
73+
btreemap.Min[roachpb.RKey](), btreemap.Max[roachpb.RKey](),
74+
func(_ roachpb.RKey, r *Replica) bool {
75+
rs.visited++
76+
rs.Unlock()
77+
defer rs.Lock()
78+
return visitor(r)
79+
},
80+
)
7981
}
8082

8183
func (rs *testRangeSet) EstimatedCount() int {
@@ -93,7 +95,7 @@ func (rs *testRangeSet) remove(index int, t *testing.T) *Replica {
9395
endKey := roachpb.RKey(fmt.Sprintf("%03d", index+1))
9496
rs.Lock()
9597
defer rs.Unlock()
96-
repl, _ := rs.replicasByKey.Delete(&Replica{startKey: endKey})
98+
_, repl, _ := rs.replicasByKey.Delete(endKey)
9799
if repl == nil {
98100
t.Fatalf("failed to delete range of end key %s", endKey)
99101
}

pkg/kv/kvserver/store_create_replica.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,13 @@ func (s *Store) addToReplicasByKeyLocked(repl *Replica, desc *roachpb.RangeDescr
264264
if got := s.GetReplicaIfExists(repl.RangeID); got != repl { // NB: got can be nil too
265265
return errors.Errorf("%s: replica %s not in replicasByRangeID; got %s", s, repl, got)
266266
}
267-
if it := s.getOverlappingKeyRangeLocked(desc); it.item != nil {
267+
if it := s.getOverlappingKeyRangeLocked(desc); !it.isEmpty() {
268268
return errors.Errorf(
269269
"%s: cannot add to replicasByKey: range %s overlaps with %s", s, repl, it.Desc())
270270
}
271-
if it := s.mu.replicasByKey.ReplaceOrInsertReplica(context.Background(), repl); it.item != nil {
271+
if it := s.mu.replicasByKey.ReplaceOrInsertReplica(context.Background(), repl); !it.isEmpty() {
272272
return errors.Errorf(
273-
"%s: cannot add to replicasByKey: key %v already exists in the btree", s, it.item.key())
273+
"%s: cannot add to replicasByKey: key %v already exists in the btree", s, it.key())
274274
}
275275
return nil
276276
}
@@ -279,8 +279,8 @@ func (s *Store) addToReplicasByKeyLocked(repl *Replica, desc *roachpb.RangeDescr
279279
// and the raftMu of the replica whose place is being held are locked.
280280
func (s *Store) addPlaceholderLocked(placeholder *ReplicaPlaceholder) error {
281281
rangeID := placeholder.Desc().RangeID
282-
if it := s.mu.replicasByKey.ReplaceOrInsertPlaceholder(context.Background(), placeholder); it.item != nil {
283-
return errors.Errorf("%s overlaps with existing replicaOrPlaceholder %+v in replicasByKey btree", placeholder, it.item)
282+
if it := s.mu.replicasByKey.ReplaceOrInsertPlaceholder(context.Background(), placeholder); !it.isEmpty() {
283+
return errors.Errorf("%s overlaps with existing replicaOrPlaceholder %+v in replicasByKey btree", placeholder, it.item())
284284
}
285285
if exRng, ok := s.mu.replicaPlaceholders[rangeID]; ok {
286286
return errors.Errorf("%s has ID collision with placeholder %+v", placeholder, exRng)

pkg/kv/kvserver/store_merge.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func (s *Store) maybeAssertNoHole(ctx context.Context, from, to roachpb.RKey) fu
6262
// TODO(tbg): this deadlocks, see #74384. By disabling this branch,
6363
// the only check that we perform is the one that the monitored
6464
// keyspace isn't all a gap.
65-
if last.item != nil {
65+
if !last.isEmpty() {
6666
gapStart, gapEnd := last.Desc().EndKey, cur.Desc().StartKey
6767
if !gapStart.Equal(gapEnd) {
6868
return errors.AssertionFailedf(
@@ -77,7 +77,7 @@ func (s *Store) maybeAssertNoHole(ctx context.Context, from, to roachpb.RKey) fu
7777
if err != nil {
7878
log.Fatalf(ctx, "%v", err)
7979
}
80-
if last.item == nil {
80+
if last.isEmpty() {
8181
log.Fatalf(ctx, "found hole in keyspace [%s,%s), during:\n%s", from, to, caller)
8282
}
8383
runtime.Gosched()

pkg/kv/kvserver/store_remove_replica.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func (s *Store) removeInitializedReplicaRaftMuLocked(
157157
// this far. This method will need some changes when we introduce GC of
158158
// uninitialized replicas.
159159
s.mu.Unlock()
160-
log.Fatalf(ctx, "replica %+v unexpectedly overlapped by %+v", rep, it.item)
160+
log.Fatalf(ctx, "replica %+v unexpectedly overlapped by %+v", rep, it.item())
161161
}
162162
// Adjust stats before calling Destroy. This can be called before or after
163163
// Destroy, but this configuration helps avoid races in stat verification
@@ -202,7 +202,7 @@ func (s *Store) removeInitializedReplicaRaftMuLocked(
202202
if it := s.mu.replicasByKey.ReplaceOrInsertPlaceholder(ctx, ph); it.repl != rep {
203203
// We already checked that our replica was present in replicasByKey
204204
// above. Nothing should have been able to change that.
205-
log.Fatalf(ctx, "replica %+v unexpectedly overlapped by %+v", rep, it.item)
205+
log.Fatalf(ctx, "replica %+v unexpectedly overlapped by %+v", rep, it.item())
206206
}
207207
if exPH, ok := s.mu.replicaPlaceholders[desc.RangeID]; ok {
208208
log.Fatalf(ctx, "cannot insert placeholder %s, already have %s", ph, exPH)
@@ -218,8 +218,8 @@ func (s *Store) removeInitializedReplicaRaftMuLocked(
218218

219219
s.mu.replicasByKey.DeletePlaceholder(ctx, ph)
220220
delete(s.mu.replicaPlaceholders, desc.RangeID)
221-
if it := s.getOverlappingKeyRangeLocked(desc); it.item != nil && it.item != ph {
222-
log.Fatalf(ctx, "corrupted replicasByKey map: %s and %s overlapped", rep, it.item)
221+
if it := s.getOverlappingKeyRangeLocked(desc); !it.isEmpty() && it.item() != ph {
222+
log.Fatalf(ctx, "corrupted replicasByKey map: %s and %s overlapped", rep, it.item())
223223
}
224224
return nil
225225
}()
@@ -400,8 +400,8 @@ func (s *Store) removePlaceholderLocked(
400400
return false, errors.AssertionFailedf("placeholder %+v not found, got %+v", placeholder, it)
401401
}
402402
delete(s.mu.replicaPlaceholders, rngID)
403-
if it := s.getOverlappingKeyRangeLocked(&placeholder.rangeDesc); it.item != nil {
404-
return false, errors.AssertionFailedf("corrupted replicasByKey map: %+v and %+v overlapped", it.ph, it.item)
403+
if it := s.getOverlappingKeyRangeLocked(&placeholder.rangeDesc); !it.isEmpty() {
404+
return false, errors.AssertionFailedf("corrupted replicasByKey map: %+v and %+v overlapped", it.ph, it.item())
405405
}
406406
switch typ {
407407
case removePlaceholderDropped:

0 commit comments

Comments
 (0)