Skip to content

Commit 13091e1

Browse files
committed
kvstorage: add testing hook forcing ClearRange
Epic: none Release note: none
1 parent ad6528c commit 13091e1

File tree

3 files changed

+65
-37
lines changed

3 files changed

+65
-37
lines changed

pkg/kv/kvserver/client_merge_test.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3815,6 +3815,10 @@ func TestStoreRangeMergeRaftSnapshot(t *testing.T) {
38153815
defer leaktest.AfterTest(t)()
38163816
defer log.Scope(t).Close(t)
38173817

3818+
// The test expects replica destruction paths to use ranged clears rather than
3819+
// point clears.
3820+
defer kvstorage.TestingForceClearRange()()
3821+
38183822
testutils.RunTrueAndFalse(t, "rebalanceRHSAway", func(t *testing.T, rebalanceRHSAway bool) {
38193823
// We will be testing the SSTs written on store2's engine.
38203824
var receivingEng, sendingEng storage.Engine
@@ -3954,22 +3958,24 @@ func TestStoreRangeMergeRaftSnapshot(t *testing.T) {
39543958
sst := storage.MakeIngestionSSTWriter(ctx, st, sstFile)
39553959
defer sst.Close()
39563960
{
3957-
// The snapshot code will use ClearRangeWithHeuristic with a
3958-
// threshold of 1 to clear the range, but this will truncate
3959-
// the range tombstone to the first key. In this case, the
3960-
// first key is RangeGCThresholdKey, which doesn't yet exist
3961-
// in the engine, so we write the Pebble range tombstone
3962-
// manually.
3961+
// The snapshot code uses ClearRangeWithHeuristic with a threshold of
3962+
// 1 to clear the range, but it will truncate the range tombstone to
3963+
// the first key. In this case, the first key is RangeGCThresholdKey,
3964+
// which doesn't yet exist in the engine, so we set it manually.
39633965
sl := rditer.Select(rangeID, rditer.SelectOpts{
39643966
ReplicatedByRangeID: true,
39653967
})
39663968
require.Len(t, sl, 1)
39673969
s := sl[0]
39683970
require.NoError(t, sst.ClearRawRange(keys.RangeGCThresholdKey(rangeID), s.EndKey, true, false))
39693971
}
3972+
require.NoError(t, kvstorage.MakeStateLoader(rangeID).SetRangeTombstone(
3973+
context.Background(), &sst,
3974+
kvserverpb.RangeTombstone{NextReplicaID: math.MaxInt32},
3975+
))
39703976
{
3971-
// Ditto for the unreplicated version, where the first key
3972-
// happens to be the HardState.
3977+
// Ditto for the unreplicated version, where the first key happens to
3978+
// be the HardState.
39733979
sl := rditer.Select(rangeID, rditer.SelectOpts{
39743980
UnreplicatedByRangeID: true,
39753981
})
@@ -3978,10 +3984,6 @@ func TestStoreRangeMergeRaftSnapshot(t *testing.T) {
39783984
require.NoError(t, sst.ClearRawRange(keys.RaftHardStateKey(rangeID), s.EndKey, true, false))
39793985
}
39803986

3981-
require.NoError(t, kvstorage.MakeStateLoader(rangeID).SetRangeTombstone(
3982-
context.Background(), &sst,
3983-
kvserverpb.RangeTombstone{NextReplicaID: math.MaxInt32},
3984-
))
39853987
require.NoError(t, sst.Finish())
39863988
expectedSSTs = append(expectedSSTs, sstFile.Data())
39873989
}
@@ -3995,7 +3997,9 @@ func TestStoreRangeMergeRaftSnapshot(t *testing.T) {
39953997
EndKey: roachpb.RKey(keyEnd),
39963998
}
39973999
require.NoError(t, storage.ClearRangeWithHeuristic(
3998-
ctx, receivingEng, &sst, desc.StartKey.AsRawKey(), desc.EndKey.AsRawKey(), 64,
4000+
ctx, receivingEng, &sst,
4001+
desc.StartKey.AsRawKey(), desc.EndKey.AsRawKey(),
4002+
kvstorage.ClearRangeThresholdPointKeys(),
39994003
))
40004004
require.NoError(t, sst.Finish())
40014005
expectedSSTs = append(expectedSSTs, sstFile.Data())

pkg/kv/kvserver/kvstorage/destroy.go

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,37 @@ import (
1313
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/rditer"
1414
"github.com/cockroachdb/cockroach/pkg/roachpb"
1515
"github.com/cockroachdb/cockroach/pkg/storage"
16+
"github.com/cockroachdb/cockroach/pkg/util/buildutil"
1617
"github.com/cockroachdb/errors"
1718
)
1819

19-
const (
20-
// ClearRangeThresholdPointKeys is the threshold (as number of point keys)
21-
// beyond which we'll clear range data using a Pebble range tombstone rather
22-
// than individual Pebble point tombstones.
23-
//
24-
// It is expensive for there to be many Pebble range tombstones in the same
25-
// sstable because all of the tombstones in an sstable are loaded whenever the
26-
// sstable is accessed. So we avoid using range deletion unless there is some
27-
// minimum number of keys. The value here was pulled out of thin air. It might
28-
// be better to make this dependent on the size of the data being deleted. Or
29-
// perhaps we should fix Pebble to handle large numbers of range tombstones in
30-
// an sstable better.
31-
ClearRangeThresholdPointKeys = 64
32-
33-
// MergedTombstoneReplicaID is the replica ID written into the RangeTombstone
34-
// for replicas of a range which is known to have been merged. This value
35-
// should prevent any messages from stale replicas of that range from ever
36-
// resurrecting merged replicas. Whenever merging or subsuming a replica we
37-
// know new replicas can never be created so this value is used even if we
38-
// don't know the current replica ID.
39-
MergedTombstoneReplicaID roachpb.ReplicaID = math.MaxInt32
40-
)
20+
// MergedTombstoneReplicaID is the replica ID written into the RangeTombstone
21+
// for replicas of a range which is known to have been merged. This value
22+
// should prevent any messages from stale replicas of that range from ever
23+
// resurrecting merged replicas. Whenever merging or subsuming a replica we
24+
// know new replicas can never be created so this value is used even if we
25+
// don't know the current replica ID.
26+
const MergedTombstoneReplicaID roachpb.ReplicaID = math.MaxInt32
27+
28+
// clearRangeThresholdPointKeys is the value of ClearRangeThresholdPointKeys().
29+
// Can be overridden only in tests, in order to deterministically force using
30+
// ClearRawRange instead of point clears, when destroying replicas.
31+
var clearRangeThresholdPointKeys = 64
32+
33+
// ClearRangeThresholdPointKeys returns the threshold (as number of point keys)
34+
// beyond which we'll clear range data using a Pebble range tombstone rather
35+
// than individual Pebble point tombstones.
36+
//
37+
// It is expensive for there to be many Pebble range tombstones in the same
38+
// sstable because all of the tombstones in an sstable are loaded whenever the
39+
// sstable is accessed. So we avoid using range deletion unless there is some
40+
// minimum number of keys. The value here was pulled out of thin air. It might
41+
// be better to make this dependent on the size of the data being deleted. Or
42+
// perhaps we should fix Pebble to handle large numbers of range tombstones in
43+
// an sstable better.
44+
func ClearRangeThresholdPointKeys() int {
45+
return clearRangeThresholdPointKeys
46+
}
4147

4248
// clearRangeDataOptions specify which parts of a Replica are to be destroyed.
4349
type clearRangeDataOptions struct {
@@ -84,7 +90,7 @@ func clearRangeData(
8490
UnreplicatedByRangeID: opts.clearUnreplicatedByRangeID,
8591
})
8692

87-
pointKeyThreshold := ClearRangeThresholdPointKeys
93+
pointKeyThreshold := ClearRangeThresholdPointKeys()
8894
if opts.mustUseClearRange {
8995
pointKeyThreshold = 1
9096
}
@@ -252,3 +258,21 @@ func RemoveStaleRHSFromSplit(
252258
clearUnreplicatedByRangeID: true,
253259
})
254260
}
261+
262+
// TestingForceClearRange changes the value of ClearRangeThresholdPointKeys to
263+
// 1, which effectively forces ClearRawRange in the replica destruction path,
264+
// instead of point deletions. This can be used for making the storage
265+
// operations in tests deterministic.
266+
//
267+
// The caller must call the returned function at the end of the test, to restore
268+
// the default value.
269+
func TestingForceClearRange() func() {
270+
if !buildutil.CrdbTestBuild {
271+
panic("test-only function")
272+
}
273+
old := clearRangeThresholdPointKeys
274+
clearRangeThresholdPointKeys = 1 // forces ClearRawRange
275+
return func() {
276+
clearRangeThresholdPointKeys = old
277+
}
278+
}

pkg/kv/kvserver/snapshot_apply_prepare.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ func (s *snapWriteBuilder) clearResidualDataOnNarrowSnapshot(ctx context.Context
225225
}) {
226226
if err := s.writeSST(ctx, func(ctx context.Context, w storage.Writer) error {
227227
return storage.ClearRangeWithHeuristic(
228-
ctx, reader, w, span.Key, span.EndKey, kvstorage.ClearRangeThresholdPointKeys,
228+
ctx, reader, w, span.Key, span.EndKey, kvstorage.ClearRangeThresholdPointKeys(),
229229
)
230230
}); err != nil {
231231
return err

0 commit comments

Comments
 (0)