Skip to content

Commit 04630a1

Browse files
craig[bot]pav-kv
andcommitted
Merge #144257
144257: logstore: add basic datadriven test r=tbg a=pav-kv This PR adds a basic datadriven test to the `logstore` package. Captures setting the `HardState`, appending entries to the log with/out overlaps, log truncation, and log size stats maintenance. Epic: CRDB-46488 Co-authored-by: Pavel Kalinnikov <[email protected]>
2 parents 8cd345b + 33885ac commit 04630a1

File tree

15 files changed

+289
-80
lines changed

15 files changed

+289
-80
lines changed

pkg/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ ALL_TESTS = [
273273
"//pkg/kv/kvserver/loqrecovery/loqrecoverypb:loqrecoverypb_test",
274274
"//pkg/kv/kvserver/loqrecovery:loqrecovery_test",
275275
"//pkg/kv/kvserver/multiqueue:multiqueue_test",
276+
"//pkg/kv/kvserver/print:print_test",
276277
"//pkg/kv/kvserver/protectedts/ptcache:ptcache_test",
277278
"//pkg/kv/kvserver/protectedts/ptreconcile:ptreconcile_test",
278279
"//pkg/kv/kvserver/protectedts/ptstorage:ptstorage_test",
@@ -1552,6 +1553,8 @@ GO_TARGETS = [
15521553
"//pkg/kv/kvserver/loqrecovery:loqrecovery_test",
15531554
"//pkg/kv/kvserver/multiqueue:multiqueue",
15541555
"//pkg/kv/kvserver/multiqueue:multiqueue_test",
1556+
"//pkg/kv/kvserver/print:print",
1557+
"//pkg/kv/kvserver/print:print_test",
15551558
"//pkg/kv/kvserver/protectedts/ptcache:ptcache",
15561559
"//pkg/kv/kvserver/protectedts/ptcache:ptcache_test",
15571560
"//pkg/kv/kvserver/protectedts/ptpb:ptpb",

pkg/cli/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ go_library(
135135
"//pkg/kv/kvserver/liveness/livenesspb",
136136
"//pkg/kv/kvserver/loqrecovery",
137137
"//pkg/kv/kvserver/loqrecovery/loqrecoverypb",
138+
"//pkg/kv/kvserver/print",
138139
"//pkg/kv/kvserver/rditer",
139140
"//pkg/kv/kvserver/stateloader",
140141
"//pkg/multitenant/mtinfopb",

pkg/cli/debug.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ import (
3131
"github.com/cockroachdb/cockroach/pkg/cloud"
3232
"github.com/cockroachdb/cockroach/pkg/gossip"
3333
"github.com/cockroachdb/cockroach/pkg/keys"
34-
"github.com/cockroachdb/cockroach/pkg/kv/kvserver"
3534
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/gc"
3635
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/liveness/livenesspb"
36+
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/print"
3737
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/rditer"
3838
"github.com/cockroachdb/cockroach/pkg/roachpb"
3939
"github.com/cockroachdb/cockroach/pkg/security/username"
@@ -312,13 +312,13 @@ func runDebugKeys(cmd *cobra.Command, args []string) error {
312312
}
313313
return strings.Join(pairs, ", "), nil
314314
}
315-
kvserver.DebugSprintMVCCKeyValueDecoders = append(kvserver.DebugSprintMVCCKeyValueDecoders, fn)
315+
print.DebugSprintMVCCKeyValueDecoders = append(print.DebugSprintMVCCKeyValueDecoders, fn)
316316
}
317317
printer := printKey
318318
rangeKeyPrinter := printRangeKey
319319
if debugCtx.values {
320-
printer = kvserver.PrintMVCCKeyValue
321-
rangeKeyPrinter = kvserver.PrintMVCCRangeKeyValue
320+
printer = print.PrintMVCCKeyValue
321+
rangeKeyPrinter = print.PrintMVCCRangeKeyValue
322322
}
323323

324324
keyTypeOptions := keyTypeParams[debugCtx.keyTypes]
@@ -509,7 +509,7 @@ func runDebugRangeData(cmd *cobra.Command, args []string) error {
509509
if err != nil {
510510
return err
511511
}
512-
kvserver.PrintEngineKeyValue(key, v)
512+
print.PrintEngineKeyValue(key, v)
513513
results++
514514
if results == debugCtx.maxResults {
515515
return iterutil.StopIteration()
@@ -522,7 +522,7 @@ func runDebugRangeData(cmd *cobra.Command, args []string) error {
522522
return err
523523
}
524524
for _, v := range iter.EngineRangeKeys() {
525-
kvserver.PrintEngineRangeKeyValue(bounds, v)
525+
print.PrintEngineRangeKeyValue(bounds, v)
526526
results++
527527
if results == debugCtx.maxResults {
528528
return iterutil.StopIteration()
@@ -553,7 +553,7 @@ func loadRangeDescriptor(
553553
// We only want values, not MVCCMetadata.
554554
return nil
555555
}
556-
if err := kvserver.IsRangeDescriptorKey(kv.Key); err != nil {
556+
if err := print.IsRangeDescriptorKey(kv.Key); err != nil {
557557
// Range descriptor keys are interleaved with others, so if it
558558
// doesn't parse as a range descriptor just skip it.
559559
return nil //nolint:returnerrcheck
@@ -609,10 +609,10 @@ func runDebugRangeDescriptors(cmd *cobra.Command, args []string) error {
609609
return db.MVCCIterate(cmd.Context(), start, end, storage.MVCCKeyAndIntentsIterKind,
610610
storage.IterKeyTypePointsOnly, fs.UnknownReadCategory,
611611
func(kv storage.MVCCKeyValue, _ storage.MVCCRangeKeyStack) error {
612-
if kvserver.IsRangeDescriptorKey(kv.Key) != nil {
612+
if print.IsRangeDescriptorKey(kv.Key) != nil {
613613
return nil
614614
}
615-
kvserver.PrintMVCCKeyValue(kv)
615+
print.PrintMVCCKeyValue(kv)
616616
return nil
617617
})
618618
}
@@ -693,7 +693,7 @@ Decode and print a hexadecimal-encoded key-value pair.
693693
// is already a roachpb.Key, so make a half-assed attempt to support both.
694694
if !isTS {
695695
if k, ok := storage.DecodeEngineKey(bs[0]); ok {
696-
kvserver.PrintEngineKeyValue(k, bs[1])
696+
print.PrintEngineKeyValue(k, bs[1])
697697
return nil
698698
}
699699
fmt.Printf("unable to decode key: %v, assuming it's a roachpb.Key with fake timestamp;\n"+
@@ -705,7 +705,7 @@ Decode and print a hexadecimal-encoded key-value pair.
705705
}
706706
}
707707

708-
kvserver.PrintMVCCKeyValue(storage.MVCCKeyValue{
708+
print.PrintMVCCKeyValue(storage.MVCCKeyValue{
709709
Key: k,
710710
Value: bs[1],
711711
})
@@ -787,7 +787,7 @@ func runDebugRaftLog(cmd *cobra.Command, args []string) error {
787787
return db.MVCCIterate(cmd.Context(), start, end, storage.MVCCKeyIterKind,
788788
storage.IterKeyTypePointsOnly, fs.UnknownReadCategory,
789789
func(kv storage.MVCCKeyValue, _ storage.MVCCRangeKeyStack) error {
790-
kvserver.PrintMVCCKeyValue(kv)
790+
print.PrintMVCCKeyValue(kv)
791791
return nil
792792
})
793793
}
@@ -1381,7 +1381,7 @@ func (m mvccValueFormatter) Format(f fmt.State, c rune) {
13811381
errors.FormatError(m.err, f, c)
13821382
return
13831383
}
1384-
fmt.Fprint(f, kvserver.SprintMVCCKeyValue(m.kv, false /* printKey */))
1384+
fmt.Fprint(f, print.SprintMVCCKeyValue(m.kv, false /* printKey */))
13851385
}
13861386

13871387
// lockValueFormatter is a fmt.Formatter for lock values.
@@ -1391,7 +1391,7 @@ type lockValueFormatter struct {
13911391

13921392
// Format implements the fmt.Formatter interface.
13931393
func (m lockValueFormatter) Format(f fmt.State, c rune) {
1394-
fmt.Fprint(f, kvserver.SprintIntent(m.value))
1394+
fmt.Fprint(f, print.SprintIntent(m.value))
13951395
}
13961396

13971397
// pebbleToolFS is the vfs.FS that the pebble tool should use.

pkg/kv/kvserver/BUILD.bazel

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ go_library(
99
"addressing.go",
1010
"app_batch.go",
1111
"consistency_queue.go",
12-
"debug_print.go",
1312
"doc.go",
1413
"flow_control_integration.go",
1514
"flow_control_raft_transport.go",
@@ -170,6 +169,7 @@ go_library(
170169
"//pkg/kv/kvserver/lockspanset",
171170
"//pkg/kv/kvserver/logstore",
172171
"//pkg/kv/kvserver/multiqueue",
172+
"//pkg/kv/kvserver/print",
173173
"//pkg/kv/kvserver/raftentry",
174174
"//pkg/kv/kvserver/raftlog",
175175
"//pkg/kv/kvserver/rafttrace",
@@ -307,7 +307,6 @@ go_test(
307307
"client_test.go",
308308
"closed_timestamp_test.go",
309309
"consistency_queue_test.go",
310-
"debug_print_test.go",
311310
"deleted_external_sstable_test.go",
312311
"errors_test.go",
313312
"flow_control_integration_test.go",

pkg/kv/kvserver/logstore/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,18 @@ go_test(
5151
srcs = [
5252
"bytes_tracker_test.go",
5353
"logstore_bench_test.go",
54+
"logstore_test.go",
5455
"sideload_test.go",
5556
"sync_waiter_test.go",
5657
],
58+
data = glob(["testdata/**"]),
5759
embed = [":logstore"],
5860
deps = [
61+
"//pkg/keys",
5962
"//pkg/kv/kvpb",
6063
"//pkg/kv/kvserver/kvserverbase",
6164
"//pkg/kv/kvserver/kvserverpb",
65+
"//pkg/kv/kvserver/print",
6266
"//pkg/kv/kvserver/raftentry",
6367
"//pkg/kv/kvserver/raftlog",
6468
"//pkg/raft",
@@ -68,6 +72,7 @@ go_test(
6872
"//pkg/storage",
6973
"//pkg/storage/fs",
7074
"//pkg/testutils",
75+
"//pkg/testutils/echotest",
7176
"//pkg/util/humanizeutil",
7277
"//pkg/util/leaktest",
7378
"//pkg/util/log",

pkg/kv/kvserver/logstore/logstore.go

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,28 @@ type RaftState struct {
8484
ByteSize int64
8585
}
8686

87+
// EntryStats contains stats about the appended log slice.
88+
type EntryStats struct {
89+
RegularEntries int
90+
RegularBytes int64
91+
SideloadedEntries int
92+
SideloadedBytes int64
93+
}
94+
95+
// Add increments the stats with the given delta.
96+
func (e *EntryStats) Add(delta EntryStats) {
97+
e.RegularEntries += delta.RegularEntries
98+
e.RegularBytes += delta.RegularBytes
99+
e.SideloadedEntries += delta.SideloadedEntries
100+
e.SideloadedBytes += delta.SideloadedBytes
101+
}
102+
87103
// AppendStats describes a completed log storage append operation.
88104
type AppendStats struct {
89105
Begin crtime.Mono
90106
End crtime.Mono
91107

92-
RegularEntries int
93-
RegularBytes int64
94-
SideloadedEntries int
95-
SideloadedBytes int64
108+
EntryStats
96109

97110
PebbleBegin crtime.Mono
98111
PebbleEnd crtime.Mono
@@ -186,39 +199,26 @@ func (s *LogStore) storeEntriesAndCommitBatch(
186199
stats.Begin = crtime.NowMono()
187200
// All of the entries are appended to distinct keys, returning a new
188201
// last index.
189-
thinEntries, numSideloaded, sideLoadedEntriesSize, otherEntriesSize, err := MaybeSideloadEntries(ctx, m.Entries, s.Sideload)
202+
thinEntries, entryStats, err := MaybeSideloadEntries(ctx, m.Entries, s.Sideload)
190203
if err != nil {
191204
const expl = "during sideloading"
192205
return RaftState{}, errors.Wrap(err, expl)
193206
}
194-
state.ByteSize += sideLoadedEntriesSize
207+
stats.EntryStats.Add(entryStats) // TODO(pav-kv): just return the stats.
208+
state.ByteSize += entryStats.SideloadedBytes
195209
if state, err = logAppend(
196210
ctx, s.StateLoader.RaftLogPrefix(), batch, state, thinEntries,
197211
); err != nil {
198212
const expl = "during append"
199213
return RaftState{}, errors.Wrap(err, expl)
200214
}
201-
stats.RegularEntries += len(thinEntries) - numSideloaded
202-
stats.RegularBytes += otherEntriesSize
203-
stats.SideloadedEntries += numSideloaded
204-
stats.SideloadedBytes += sideLoadedEntriesSize
205215
stats.End = crtime.NowMono()
206216
}
207217

208-
if hs := m.HardState; !raft.IsEmptyHardState(hs) {
209-
// NB: Note that without additional safeguards, it's incorrect to write
210-
// the HardState before appending m.Entries. When catching up, a follower
211-
// will receive Entries that are immediately Committed in the same
212-
// Ready. If we persist the HardState but happen to lose the Entries,
213-
// assertions can be tripped.
214-
//
215-
// We have both in the same batch, so there's no problem. If that ever
216-
// changes, we must write and sync the Entries before the HardState.
217-
if err := s.StateLoader.SetHardState(ctx, batch, hs); err != nil {
218-
const expl = "during setHardState"
219-
return RaftState{}, errors.Wrap(err, expl)
220-
}
218+
if err := storeHardState(ctx, batch, s.StateLoader, m.HardState); err != nil {
219+
return RaftState{}, err
221220
}
221+
222222
// Synchronously commit the batch with the Raft log entries and Raft hard
223223
// state as we're promising not to lose this data.
224224
//
@@ -376,6 +376,26 @@ var logAppendPool = sync.Pool{
376376
},
377377
}
378378

379+
func storeHardState(
380+
ctx context.Context, w storage.Writer, sl StateLoader, hs raftpb.HardState,
381+
) error {
382+
if raft.IsEmptyHardState(hs) {
383+
return nil
384+
}
385+
// NB: Note that without additional safeguards, it's incorrect to write the
386+
// HardState before appending m.Entries. When catching up, a follower will
387+
// receive Entries that are immediately Committed in the same Ready. If we
388+
// persist the HardState but happen to lose the Entries, assertions can be
389+
// tripped.
390+
//
391+
// We have both in the same batch, so there's no problem. If that ever
392+
// changes, we must write and sync the Entries before the HardState.
393+
if err := sl.SetHardState(ctx, w, hs); err != nil {
394+
return errors.Wrap(err, "during SetHardState")
395+
}
396+
return nil
397+
}
398+
379399
// logAppend adds the given entries to the raft log. Takes the previous log
380400
// state, and returns the updated state. It's the caller's responsibility to
381401
// maintain exclusive access to the raft log for the duration of the method

0 commit comments

Comments
 (0)