Skip to content

Commit b4026d8

Browse files
committed
kvserver: add directives to make replica destruction more interesting
Here, we add directives to add some dummy Raft log entries and state machine keys to the replica on n1/s1 before it is destroyed. Epic: none Release note: None
1 parent fb795c4 commit b4026d8

File tree

4 files changed

+169
-12
lines changed

4 files changed

+169
-12
lines changed

pkg/kv/kvserver/replica_lifecycle_datadriven_test.go

Lines changed: 106 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,19 @@ import (
1212
"cmp"
1313
"context"
1414
"fmt"
15+
"strconv"
1516
"strings"
1617
"testing"
1718
"time"
1819

20+
"github.com/cockroachdb/cockroach/pkg/keys"
21+
"github.com/cockroachdb/cockroach/pkg/kv/kvpb"
1922
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/abortspan"
2023
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/batcheval"
24+
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/concurrency/lock"
2125
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverpb"
2226
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvstorage"
27+
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/logstore"
2328
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/print"
2429
"github.com/cockroachdb/cockroach/pkg/raft/raftpb"
2530
"github.com/cockroachdb/cockroach/pkg/roachpb"
@@ -31,6 +36,7 @@ import (
3136
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
3237
"github.com/cockroachdb/cockroach/pkg/util/log"
3338
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
39+
"github.com/cockroachdb/cockroach/pkg/util/uuid"
3440
"github.com/cockroachdb/datadriven"
3541
"github.com/cockroachdb/errors"
3642
"github.com/stretchr/testify/require"
@@ -87,6 +93,20 @@ import (
8793
// Destroys the replica on n1 for the specified range. The replica's state
8894
// must have already been created via create-replica.
8995
//
96+
// append-raft-entries range-id=<int> num-entries=<int>
97+
// ----
98+
//
99+
// Appends the specified number of dummy raft entries to the raft log for
100+
// the replica on n1/s1. The replica must have already been created via
101+
// create-replica.
102+
//
103+
// create-range-data range-id=<int> [num-user-keys=<int>] [num-system-keys=<int>] [num-lock-table-keys=<int>]
104+
// ----
105+
//
106+
// Creates the specified number of user, system, and lock table keys for the
107+
// range. At least one parameter should be non-zero to ensure this directive is
108+
// not nonsensical.
109+
//
90110
// print-range-state [sort-keys=<bool>]
91111
// ----
92112
//
@@ -97,6 +117,8 @@ func TestReplicaLifecycleDataDriven(t *testing.T) {
97117
defer leaktest.AfterTest(t)()
98118
defer log.Scope(t).Close(t)
99119

120+
storage.DisableMetamorphicSimpleValueEncoding(t) // for deterministic output
121+
100122
datadriven.Walk(t, "testdata/replica_lifecycle", func(t *testing.T, path string) {
101123
tc := newTestCtx()
102124
defer tc.close()
@@ -303,7 +325,7 @@ func TestReplicaLifecycleDataDriven(t *testing.T) {
303325
kvstorage.TODOReadWriter(batch),
304326
kvstorage.DestroyReplicaInfo{
305327
FullReplicaID: rs.replica.FullReplicaID,
306-
Keys: roachpb.RSpan{Key: rs.desc.StartKey, EndKey: rs.desc.EndKey},
328+
Keys: rs.desc.RSpan(),
307329
},
308330
rs.desc.NextReplicaID,
309331
)
@@ -317,6 +339,80 @@ func TestReplicaLifecycleDataDriven(t *testing.T) {
317339
rs.replica = nil
318340
return output
319341

342+
case "append-raft-entries":
343+
rangeID := dd.ScanArg[roachpb.RangeID](t, d, "range-id")
344+
numEntries := dd.ScanArg[int](t, d, "num-entries")
345+
rs := tc.mustGetRangeState(t, rangeID)
346+
require.NotNil(t, rs.replica, "replica must be created before appending entries")
347+
348+
batch := tc.storage.NewBatch()
349+
defer batch.Close()
350+
351+
sl := logstore.NewStateLoader(rangeID)
352+
lastIndex := rs.replica.lastIdx
353+
rs.replica.lastIdx += kvpb.RaftIndex(numEntries)
354+
term := rs.replica.hs.Term
355+
356+
for i := 0; i < numEntries; i++ {
357+
entryIndex := lastIndex + 1 + kvpb.RaftIndex(i)
358+
require.NoError(t, storage.MVCCBlindPutProto(
359+
ctx, batch,
360+
sl.RaftLogKey(entryIndex), hlc.Timestamp{},
361+
&raftpb.Entry{Index: uint64(entryIndex), Term: term},
362+
storage.MVCCWriteOptions{},
363+
))
364+
}
365+
366+
output, err := print.DecodeWriteBatch(batch.Repr())
367+
require.NoError(t, err)
368+
err = batch.Commit(true)
369+
require.NoError(t, err)
370+
return strings.ReplaceAll(output, "\n\n", "\n")
371+
372+
case "create-range-data":
373+
rangeID := dd.ScanArg[roachpb.RangeID](t, d, "range-id")
374+
numUserKeys := dd.ScanArgOr(t, d, "num-user-keys", 0)
375+
numSystemKeys := dd.ScanArgOr(t, d, "num-system-keys", 0)
376+
numLockTableKeys := dd.ScanArgOr(t, d, "num-lock-table-keys", 0)
377+
require.True(t, numUserKeys > 0 || numSystemKeys > 0 || numLockTableKeys > 0)
378+
379+
rs := tc.mustGetRangeState(t, rangeID)
380+
batch := tc.storage.NewBatch()
381+
defer batch.Close()
382+
383+
ts := hlc.Timestamp{WallTime: 1}
384+
385+
getUserKey := func(i int) roachpb.Key {
386+
return append(rs.desc.StartKey.AsRawKey(), strconv.Itoa(i)...)
387+
}
388+
389+
// 1. User keys.
390+
for i := 0; i < numUserKeys; i++ {
391+
require.NoError(t, batch.PutMVCC(
392+
storage.MVCCKey{Key: getUserKey(i), Timestamp: ts}, storage.MVCCValue{},
393+
))
394+
}
395+
// 2. System keys.
396+
for i := 0; i < numSystemKeys; i++ {
397+
key := keys.TransactionKey(getUserKey(i), uuid.NamespaceDNS)
398+
require.NoError(t, batch.PutMVCC(
399+
storage.MVCCKey{Key: key, Timestamp: ts}, storage.MVCCValue{},
400+
))
401+
}
402+
// 3. Lock table keys.
403+
for i := 0; i < numLockTableKeys; i++ {
404+
ek, _ := storage.LockTableKey{
405+
Key: getUserKey(i), Strength: lock.Intent, TxnUUID: uuid.UUID{},
406+
}.ToEngineKey(nil)
407+
require.NoError(t, batch.PutEngineKey(ek, nil))
408+
}
409+
410+
output, err := print.DecodeWriteBatch(batch.Repr())
411+
require.NoError(t, err)
412+
err = batch.Commit(true)
413+
require.NoError(t, err)
414+
return output
415+
320416
case "print-range-state":
321417
var sb strings.Builder
322418
if len(tc.ranges) == 0 {
@@ -363,8 +459,9 @@ type rangeState struct {
363459
// engine (both raft log and state machine) state.
364460
type replicaInfo struct {
365461
roachpb.FullReplicaID
366-
hs raftpb.HardState
367-
ts kvserverpb.RaftTruncatedState
462+
hs raftpb.HardState
463+
ts kvserverpb.RaftTruncatedState
464+
lastIdx kvpb.RaftIndex
368465
}
369466

370467
// testCtx is a single test's context. It tracks the state of all ranges and any
@@ -442,8 +539,9 @@ func (tc *testCtx) updatePostReplicaCreateState(
442539
RangeID: rs.desc.RangeID,
443540
ReplicaID: replID.ReplicaID,
444541
},
445-
hs: hs,
446-
ts: ts,
542+
hs: hs,
543+
ts: ts,
544+
lastIdx: ts.Index,
447545
}
448546
}
449547

@@ -504,8 +602,9 @@ func (r *replicaInfo) String() string {
504602
if r.hs == (raftpb.HardState{}) {
505603
sb.WriteString("uninitialized")
506604
} else {
507-
sb.WriteString(fmt.Sprintf("HardState={Term:%d,Vote:%d,Commit:%d} ", r.hs.Term, r.hs.Vote, r.hs.Commit))
508-
sb.WriteString(fmt.Sprintf("TruncatedState={Index:%d,Term:%d}", r.ts.Index, r.ts.Term))
605+
sb.WriteString(fmt.Sprintf("HardState={Term:%d,Vote:%d,Commit:%d}", r.hs.Term, r.hs.Vote, r.hs.Commit))
606+
sb.WriteString(fmt.Sprintf(" TruncatedState={Index:%d,Term:%d}", r.ts.Index, r.ts.Term))
607+
sb.WriteString(fmt.Sprintf(" LastIdx=%d", r.lastIdx))
509608
}
510609
return sb.String()
511610
}

pkg/kv/kvserver/testdata/replica_lifecycle/create_replica.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ print-range-state
2929
range desc: r1:{a-d} [(n1,s1):1, (n2,s2):2, (n3,s3):3, next=4, gen=0]
3030
replica (n1/s1): id=1 uninitialized
3131
range desc: r2:{d-k} [(n1,s1):1, (n2,s2):2, (n3,s3):3, next=4, gen=0]
32-
replica (n1/s1): id=1 HardState={Term:5,Vote:0,Commit:10} TruncatedState={Index:10,Term:5}
32+
replica (n1/s1): id=1 HardState={Term:5,Vote:0,Commit:10} TruncatedState={Index:10,Term:5} LastIdx=10

pkg/kv/kvserver/testdata/replica_lifecycle/destroy_replica.txt

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
create-descriptor start=a end=z replicas=(1,2,3)
1+
create-descriptor start=a end=c replicas=(1,2,3)
22
----
3-
created descriptor: r1:{a-z} [(n1,s1):1, (n2,s2):2, (n3,s3):3, next=4, gen=0]
3+
created descriptor: r1:{a-c} [(n1,s1):1, (n2,s2):2, (n3,s3):3, next=4, gen=0]
44

55
create-replica range-id=1 initialized
66
----
@@ -25,3 +25,61 @@ Put: 0,0 /Local/RangeID/1/u/RangeTombstone (0x016989757266746200): next_replica_
2525
Delete (Sized at 38): 0,0 /Local/RangeID/1/u/RaftHardState (0x016989757266746800):
2626
Delete: 0,0 /Local/RangeID/1/u/RaftReplicaID (0x016989757266747200):
2727
Delete (Sized at 32): 0,0 /Local/RangeID/1/u/RaftTruncatedState (0x016989757266747400):
28+
29+
create-descriptor start=c end=f replicas=(1,2,3,4,5)
30+
----
31+
created descriptor: r2:{c-f} [(n1,s1):1, (n2,s2):2, (n3,s3):3, (n4,s4):4, (n5,s5):5, next=6, gen=0]
32+
33+
create-replica range-id=2 initialized
34+
----
35+
created replica: (n1,s1):1
36+
Put: 0,0 /Local/RangeID/2/r/RangeLease (0x01698a72726c6c2d00): <empty>
37+
Put: 0,0 /Local/RangeID/2/r/RangeGCThreshold (0x01698a726c67632d00): 0,0
38+
Put: 0,0 /Local/RangeID/2/r/RangeGCHint (0x01698a727267636800): latest_range_delete_timestamp:<> gc_timestamp:<> gc_timestamp_next:<>
39+
Put: 0,0 /Local/RangeID/2/r/RangeVersion (0x01698a727276657200): 10.8-upgrading-step-007
40+
Put: 0,0 /Local/RangeID/2/r/RangeAppliedState (0x01698a727261736b00): raft_applied_index:10 lease_applied_index:10 range_stats:<sys_bytes:142 sys_count:4 > raft_closed_timestamp:<> raft_applied_index_term:5
41+
Put: 0,0 /Local/RangeID/2/u/RaftReplicaID (0x01698a757266747200): replica_id:1
42+
Put: 0,0 /Local/RangeID/2/u/RaftHardState (0x01698a757266746800): term:5 vote:0 commit:10 lead:0 lead_epoch:0
43+
Put: 0,0 /Local/RangeID/2/u/RaftTruncatedState (0x01698a757266747400): index:10 term:5
44+
45+
append-raft-entries range-id=2 num-entries=3
46+
----
47+
Put: 0,0 /Local/RangeID/2/u/RaftLog/logIndex:11 (0x01698a757266746c000000000000000b00): Term:5 Index:11 Type:EntryNormal : EMPTY
48+
Put: 0,0 /Local/RangeID/2/u/RaftLog/logIndex:12 (0x01698a757266746c000000000000000c00): Term:5 Index:12 Type:EntryNormal : EMPTY
49+
Put: 0,0 /Local/RangeID/2/u/RaftLog/logIndex:13 (0x01698a757266746c000000000000000d00): Term:5 Index:13 Type:EntryNormal : EMPTY
50+
51+
create-range-data range-id=2 num-user-keys=2 num-system-keys=3 num-lock-table-keys=4
52+
----
53+
Put: 0.000000001,0 "c0" (0x633000000000000000000109): ""
54+
Put: 0.000000001,0 "c1" (0x633100000000000000000109): ""
55+
Put: 0.000000001,0 /Local/Range"c0"/Transaction/"6ba7b810-9dad-11d1-80b4-00c04fd430c8" (0x016b126330000174786e2d6ba7b8109dad11d180b400c04fd430c800000000000000000109): ""
56+
Put: 0.000000001,0 /Local/Range"c1"/Transaction/"6ba7b810-9dad-11d1-80b4-00c04fd430c8" (0x016b126331000174786e2d6ba7b8109dad11d180b400c04fd430c800000000000000000109): ""
57+
Put: 0.000000001,0 /Local/Range"c2"/Transaction/"6ba7b810-9dad-11d1-80b4-00c04fd430c8" (0x016b126332000174786e2d6ba7b8109dad11d180b400c04fd430c800000000000000000109): ""
58+
Put: "c0"/Intent/00000000-0000-0000-0000-000000000000:
59+
Put: "c1"/Intent/00000000-0000-0000-0000-000000000000:
60+
Put: "c2"/Intent/00000000-0000-0000-0000-000000000000:
61+
Put: "c3"/Intent/00000000-0000-0000-0000-000000000000:
62+
63+
destroy-replica range-id=2
64+
----
65+
Delete (Sized at 28): 0,0 /Local/RangeID/2/r/RangeGCThreshold (0x01698a726c67632d00):
66+
Delete (Sized at 43): 0,0 /Local/RangeID/2/r/RangeAppliedState (0x01698a727261736b00):
67+
Delete (Sized at 34): 0,0 /Local/RangeID/2/r/RangeGCHint (0x01698a727267636800):
68+
Delete (Sized at 44): 0,0 /Local/RangeID/2/r/RangeLease (0x01698a72726c6c2d00):
69+
Delete (Sized at 36): 0,0 /Local/RangeID/2/r/RangeVersion (0x01698a727276657200):
70+
Put: 0,0 /Local/RangeID/2/u/RangeTombstone (0x01698a757266746200): next_replica_id:6
71+
Delete (Sized at 38): 0,0 /Local/RangeID/2/u/RaftHardState (0x01698a757266746800):
72+
Delete (Sized at 42): 0,0 /Local/RangeID/2/u/RaftLog/logIndex:11 (0x01698a757266746c000000000000000b00):
73+
Delete (Sized at 42): 0,0 /Local/RangeID/2/u/RaftLog/logIndex:12 (0x01698a757266746c000000000000000c00):
74+
Delete (Sized at 42): 0,0 /Local/RangeID/2/u/RaftLog/logIndex:13 (0x01698a757266746c000000000000000d00):
75+
Delete: 0,0 /Local/RangeID/2/u/RaftReplicaID (0x01698a757266747200):
76+
Delete (Sized at 32): 0,0 /Local/RangeID/2/u/RaftTruncatedState (0x01698a757266747400):
77+
Delete (Sized at 37): 0.000000001,0 /Local/Range"c0"/Transaction/"6ba7b810-9dad-11d1-80b4-00c04fd430c8" (0x016b126330000174786e2d6ba7b8109dad11d180b400c04fd430c800000000000000000109):
78+
Delete (Sized at 37): 0.000000001,0 /Local/Range"c1"/Transaction/"6ba7b810-9dad-11d1-80b4-00c04fd430c8" (0x016b126331000174786e2d6ba7b8109dad11d180b400c04fd430c800000000000000000109):
79+
Delete (Sized at 37): 0.000000001,0 /Local/Range"c2"/Transaction/"6ba7b810-9dad-11d1-80b4-00c04fd430c8" (0x016b126332000174786e2d6ba7b8109dad11d180b400c04fd430c800000000000000000109):
80+
Delete (Sized at 27): /Local/Lock"c0" 0300000000000000000000000000000000 (0x017a6b126330000100030000000000000000000000000000000012):
81+
Delete (Sized at 27): /Local/Lock"c1" 0300000000000000000000000000000000 (0x017a6b126331000100030000000000000000000000000000000012):
82+
Delete (Sized at 27): /Local/Lock"c2" 0300000000000000000000000000000000 (0x017a6b126332000100030000000000000000000000000000000012):
83+
Delete (Sized at 27): /Local/Lock"c3" 0300000000000000000000000000000000 (0x017a6b126333000100030000000000000000000000000000000012):
84+
Delete (Sized at 12): 0.000000001,0 "c0" (0x633000000000000000000109):
85+
Delete (Sized at 12): 0.000000001,0 "c1" (0x633100000000000000000109):

pkg/kv/kvserver/testdata/replica_lifecycle/split_trigger.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Put: 0,0 /Local/RangeID/2/r/RangeAppliedState (0x01698a727261736b00): raft_appli
3939
print-range-state
4040
----
4141
range desc: r1:{a-m} [(n1,s1):1, (n2,s2):2, (n3,s3):3, next=4, gen=0]
42-
replica (n1/s1): id=1 HardState={Term:5,Vote:0,Commit:10} TruncatedState={Index:10,Term:5}
42+
replica (n1/s1): id=1 HardState={Term:5,Vote:0,Commit:10} TruncatedState={Index:10,Term:5} LastIdx=10
4343
lease: repl=(n2,s2):2 seq=0 start=0,0 type=LeaseLeader term=10 min-exp=0.000000100,0 pro=0,0 acq=Unspecified
4444
range desc: r2:{m-z} [(n1,s1):1, (n2,s2):2, (n3,s3):3, next=4, gen=0]
4545
lease: repl=(n2,s2):2 seq=0 start=0,0 type=LeaseExpiration exp=0.000000109,0 pro=0,0 acq=Unspecified
@@ -88,7 +88,7 @@ Put: 0,0 /Local/RangeID/4/r/RangeAppliedState (0x01698c727261736b00): raft_appli
8888
print-range-state sort-keys=true
8989
----
9090
range desc: r1:{a-f} [(n1,s1):1, (n2,s2):2, (n3,s3):3, next=4, gen=0]
91-
replica (n1/s1): id=1 HardState={Term:5,Vote:0,Commit:10} TruncatedState={Index:10,Term:5}
91+
replica (n1/s1): id=1 HardState={Term:5,Vote:0,Commit:10} TruncatedState={Index:10,Term:5} LastIdx=10
9292
lease: repl=(n1,s1):1 seq=0 start=0,0 type=LeaseEpoch epo=20 min-exp=0,0 pro=0,0 acq=Unspecified
9393
range desc: r3:{f-m} [(n1,s1):1, (n2,s2):2, (n3,s3):3, next=4, gen=0]
9494
lease: repl=(n1,s1):1 seq=0 start=0,0 type=LeaseEpoch epo=20 min-exp=0,0 pro=0,0 acq=Unspecified

0 commit comments

Comments
 (0)