Skip to content

Commit 4566a72

Browse files
committed
metamorphic: add changes to iterOpts in metamorphic settings for new SeekPrefix lazy positioning
Part of #2002 Previous #5256
1 parent fc77e75 commit 4566a72

File tree

7 files changed

+76
-14
lines changed

7 files changed

+76
-14
lines changed

metamorphic/cockroachkvs.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ func (kg *cockroachKeyGenerator) IncMaxSuffix() []byte {
162162
return kg.suffixSpace.ToMaterializedSuffix(s)
163163
}
164164

165+
// MaximumSuffixProperty returns the maximum suffix property.
166+
func (kg *cockroachKeyGenerator) MaximumSuffixProperty() pebble.MaximumSuffixProperty {
167+
return cockroachkvs.MaxMVCCTimestampProperty{}
168+
}
169+
165170
// SuffixRange generates a new uniformly random range of suffixes (low, high]
166171
// such that high is guaranteed to be strictly greater (as defined by
167172
// ComparePointSuffixes) than low.

metamorphic/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,4 +440,7 @@ type KeyGenerator interface {
440440
//
441441
// May return a nil suffix.
442442
UniformSuffix() []byte
443+
// MaximumSuffixProperty returns the maximum suffix property used during
444+
// the lazy position of SeekPrefixGE optimization.
445+
MaximumSuffixProperty() pebble.MaximumSuffixProperty
443446
}

metamorphic/generator.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,16 @@ type iterOpts struct {
4848
// see IterOptions.UseL6Filters.
4949
useL6Filters bool
5050

51+
// MaximumSuffixProperty is the maximum suffix property used during the lazy
52+
// position of SeekPrefixGE optimization.
53+
maximumSuffixProperty pebble.MaximumSuffixProperty
5154
// NB: If adding or removing fields, ensure IsZero is in sync.
5255
}
5356

5457
func (o iterOpts) IsZero() bool {
5558
return o.lower == nil && o.upper == nil && o.keyTypes == 0 &&
56-
o.maskSuffix == nil && o.filterMin == nil && o.filterMax == nil && !o.useL6Filters
59+
o.maskSuffix == nil && o.filterMin == nil && o.filterMax == nil && !o.useL6Filters &&
60+
o.maximumSuffixProperty == nil
5761
}
5862

5963
// GenerateOps generates n random operations, drawing randomness from the
@@ -566,6 +570,11 @@ func (g *generator) newIter() {
566570
opts.useL6Filters = true
567571
}
568572

573+
// With 20% probability, enable the lazy positioning SeekPrefixGE optimization.
574+
if g.rng.Float64() <= 0.2 {
575+
opts.maximumSuffixProperty = g.keyGenerator.MaximumSuffixProperty()
576+
}
577+
569578
g.itersLastOpts[iterID] = opts
570579
g.iterVisibleKeys[iterID] = g.keyManager.getSetOfVisibleKeys(readerID)
571580
g.iterReaderID[iterID] = readerID
@@ -1562,6 +1571,10 @@ func (g *generator) maybeMutateOptions(readerID objID, opts *iterOpts) {
15621571
if g.rng.Float64() <= 0.1 {
15631572
opts.useL6Filters = !opts.useL6Filters
15641573
}
1574+
// With 20% probability, clear existing maximum suffix property.
1575+
if opts.maximumSuffixProperty != nil && g.rng.IntN(5) == 0 {
1576+
opts.maximumSuffixProperty = nil
1577+
}
15651578
}
15661579
}
15671580

metamorphic/ops.go

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919

2020
"github.com/cockroachdb/errors"
2121
"github.com/cockroachdb/pebble"
22+
"github.com/cockroachdb/pebble/cockroachkvs"
2223
"github.com/cockroachdb/pebble/internal/base"
2324
"github.com/cockroachdb/pebble/internal/keyspan"
2425
"github.com/cockroachdb/pebble/internal/private"
@@ -564,6 +565,32 @@ func (o *rangeKeySetOp) diagramKeyRanges() []pebble.KeyRange {
564565
return []pebble.KeyRange{{Start: o.start, End: o.end}}
565566
}
566567

568+
// Helper functions to serialize/deserialize MaximumSuffixProperty for metamorphic tests
569+
func serializeMaximumSuffixProperty(prop pebble.MaximumSuffixProperty) string {
570+
if prop == nil {
571+
return "nil"
572+
}
573+
switch prop.(type) {
574+
case sstable.MaxTestKeysSuffixProperty:
575+
return "testkeys"
576+
default:
577+
return "cockroachkvs"
578+
}
579+
}
580+
581+
func deserializeMaximumSuffixProperty(s string) pebble.MaximumSuffixProperty {
582+
switch s {
583+
case "nil":
584+
return nil
585+
case "testkeys":
586+
return sstable.MaxTestKeysSuffixProperty{}
587+
case "cockroachkvs":
588+
return cockroachkvs.MaxMVCCTimestampProperty{}
589+
default:
590+
return nil
591+
}
592+
}
593+
567594
// rangeKeyUnsetOp models a Write.RangeKeyUnset operation.
568595
type rangeKeyUnsetOp struct {
569596
writerID objID
@@ -1206,10 +1233,10 @@ func (o *newIterOp) run(t *Test, h historyRecorder) {
12061233
}
12071234

12081235
func (o *newIterOp) formattedString(kf KeyFormat) string {
1209-
return fmt.Sprintf("%s = %s.NewIter(%q, %q, %d /* key types */, %q, %q, %t /* use L6 filters */, %q /* masking suffix */)",
1236+
return fmt.Sprintf("%s = %s.NewIter(%q, %q, %d /* key types */, %q, %q, %t /* use L6 filters */, %q /* masking suffix */, %q /* maximum suffix property */)",
12101237
o.iterID, o.readerID, kf.FormatKey(o.lower), kf.FormatKey(o.upper),
12111238
o.keyTypes, kf.FormatKeySuffix(o.filterMax), kf.FormatKeySuffix(o.filterMin),
1212-
o.useL6Filters, kf.FormatKeySuffix(o.maskSuffix))
1239+
o.useL6Filters, kf.FormatKeySuffix(o.maskSuffix), serializeMaximumSuffixProperty(o.maximumSuffixProperty))
12131240
}
12141241

12151242
func (o *newIterOp) receiver() objID { return o.readerID }
@@ -1273,10 +1300,10 @@ func (o *newIterUsingCloneOp) run(t *Test, h historyRecorder) {
12731300
}
12741301

12751302
func (o *newIterUsingCloneOp) formattedString(kf KeyFormat) string {
1276-
return fmt.Sprintf("%s = %s.Clone(%t, %q, %q, %d /* key types */, %q, %q, %t /* use L6 filters */, %q /* masking suffix */)",
1303+
return fmt.Sprintf("%s = %s.Clone(%t, %q, %q, %d /* key types */, %q, %q, %t /* use L6 filters */, %q /* masking suffix */, %q /* maximum suffix property */)",
12771304
o.iterID, o.existingIterID, o.refreshBatch, kf.FormatKey(o.lower),
12781305
kf.FormatKey(o.upper), o.keyTypes, kf.FormatKeySuffix(o.filterMax),
1279-
kf.FormatKeySuffix(o.filterMin), o.useL6Filters, kf.FormatKeySuffix(o.maskSuffix))
1306+
kf.FormatKeySuffix(o.filterMin), o.useL6Filters, kf.FormatKeySuffix(o.maskSuffix), serializeMaximumSuffixProperty(o.maximumSuffixProperty))
12801307
}
12811308

12821309
func (o *newIterUsingCloneOp) receiver() objID { return o.existingIterID }
@@ -1370,10 +1397,10 @@ func (o *iterSetOptionsOp) run(t *Test, h historyRecorder) {
13701397
}
13711398

13721399
func (o *iterSetOptionsOp) formattedString(kf KeyFormat) string {
1373-
return fmt.Sprintf("%s.SetOptions(%q, %q, %d /* key types */, %q, %q, %t /* use L6 filters */, %q /* masking suffix */)",
1400+
return fmt.Sprintf("%s.SetOptions(%q, %q, %d /* key types */, %q, %q, %t /* use L6 filters */, %q /* masking suffix */, %q /* maximum suffix property */)",
13741401
o.iterID, kf.FormatKey(o.lower), kf.FormatKey(o.upper),
13751402
o.keyTypes, kf.FormatKeySuffix(o.filterMax), kf.FormatKeySuffix(o.filterMin),
1376-
o.useL6Filters, kf.FormatKeySuffix(o.maskSuffix))
1403+
o.useL6Filters, kf.FormatKeySuffix(o.maskSuffix), serializeMaximumSuffixProperty(o.maximumSuffixProperty))
13771404
}
13781405

13791406
func iterOptions(kf KeyFormat, o iterOpts) *pebble.IterOptions {
@@ -1394,8 +1421,9 @@ func iterOptions(kf KeyFormat, o iterOpts) *pebble.IterOptions {
13941421
RangeKeyMasking: pebble.RangeKeyMasking{
13951422
Suffix: o.maskSuffix,
13961423
},
1397-
UseL6Filters: o.useL6Filters,
1398-
DebugRangeKeyStack: debugIterators,
1424+
UseL6Filters: o.useL6Filters,
1425+
DebugRangeKeyStack: debugIterators,
1426+
MaximumSuffixProperty: o.maximumSuffixProperty,
13991427
}
14001428
if opts.RangeKeyMasking.Suffix != nil {
14011429
opts.RangeKeyMasking.Filter = kf.NewSuffixFilterMask

metamorphic/parser.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ func opArgs(op op) (receiverID *objID, targetID *objID, args []interface{}) {
9393
case *newIndexedBatchOp:
9494
return &t.dbID, &t.batchID, nil
9595
case *newIterOp:
96-
return &t.readerID, &t.iterID, []interface{}{&t.lower, &t.upper, &t.keyTypes, &t.filterMax, &t.filterMin, &t.useL6Filters, &t.maskSuffix}
96+
return &t.readerID, &t.iterID, []interface{}{&t.lower, &t.upper, &t.keyTypes, &t.filterMax, &t.filterMin, &t.useL6Filters, &t.maskSuffix, &t.maximumSuffixProperty}
9797
case *newIterUsingCloneOp:
98-
return &t.existingIterID, &t.iterID, []interface{}{&t.refreshBatch, &t.lower, &t.upper, &t.keyTypes, &t.filterMax, &t.filterMin, &t.useL6Filters, &t.maskSuffix}
98+
return &t.existingIterID, &t.iterID, []interface{}{&t.refreshBatch, &t.lower, &t.upper, &t.keyTypes, &t.filterMax, &t.filterMin, &t.useL6Filters, &t.maskSuffix, &t.maximumSuffixProperty}
9999
case *newSnapshotOp:
100100
return &t.dbID, &t.snapID, []interface{}{&t.bounds}
101101
case *newExternalObjOp:
@@ -119,7 +119,7 @@ func opArgs(op op) (receiverID *objID, targetID *objID, args []interface{}) {
119119
case *iterSetBoundsOp:
120120
return &t.iterID, nil, []interface{}{&t.lower, &t.upper}
121121
case *iterSetOptionsOp:
122-
return &t.iterID, nil, []interface{}{&t.lower, &t.upper, &t.keyTypes, &t.filterMax, &t.filterMin, &t.useL6Filters, &t.maskSuffix}
122+
return &t.iterID, nil, []interface{}{&t.lower, &t.upper, &t.keyTypes, &t.filterMax, &t.filterMin, &t.useL6Filters, &t.maskSuffix, &t.maximumSuffixProperty}
123123
case *singleDeleteOp:
124124
return &t.writerID, nil, []interface{}{&t.key, &t.maybeReplaceDelete}
125125
case *rangeKeyDeleteOp:
@@ -408,6 +408,14 @@ func (p *parser) parseArgs(op op, methodName string, args []interface{}) {
408408
}
409409
*t = pebble.FormatMajorVersion(val)
410410

411+
case *pebble.MaximumSuffixProperty:
412+
elem.expectToken(p, token.STRING)
413+
s, err := strconv.Unquote(elem.lit)
414+
if err != nil {
415+
panic(p.errorf(elem.pos, "error parsing %q: %s", elem.lit, err))
416+
}
417+
*t = deserializeMaximumSuffixProperty(s)
418+
411419
default:
412420
panic(p.errorf(pos, "%s: unsupported arg[%d] type: %T", methodName, i, args[i]))
413421
}

metamorphic/testdata/diagram

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ snap9 = db2.NewSnapshot("a", "z")
55
db2.RangeKeyDelete("d", "f")
66
db2.Compact("g", "i", true /* parallelize */)
77
db2.Replicate(db1, "b", "f")
8-
iter25 = db1.NewIter("", "", 2 /* key types */, "", "", false /* use L6 filters */, "@7" /* masking suffix */)
8+
iter25 = db1.NewIter("", "", 2 /* key types */, "", "", false /* use L6 filters */, "@7" /* masking suffix */, "nil" /* maximum suffix property */)
99
iter25.SeekGE("e", "")
1010
----
1111
Init(2 /* dbs */, 49 /* batches */, 63 /* iters */, 45 /* snapshots */, 0 /* externalObjs */)
@@ -14,7 +14,7 @@ iter25.SeekGE("e", "")
1414
|-----------| db2.RangeKeyDelete("d", "f")
1515
|-----------| db2.Compact("g", "i", true /* parallelize */)
1616
|-----------------------| db2.Replicate(db1, "b", "f")
17-
iter25 = db1.NewIter("", "", 2 /* key types */, "", "", false /* use L6 filters */, "@7" /* masking suffix */)
17+
iter25 = db1.NewIter("", "", 2 /* key types */, "", "", false /* use L6 filters */, "@7" /* masking suffix */, "nil" /* maximum suffix property */)
1818
| iter25.SeekGE("e", "")
1919
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
2020
a b c d e f g h i z

metamorphic/testkeys.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ func (kg *testkeyKeyGenerator) IncMaxSuffix() []byte {
156156
return testkeys.Suffix(int64(kg.cfg.writeSuffixDist.Max()))
157157
}
158158

159+
// MaximumSuffixProperty returns the maximum suffix property.
160+
func (kg *testkeyKeyGenerator) MaximumSuffixProperty() pebble.MaximumSuffixProperty {
161+
return sstable.MaxTestKeysSuffixProperty{}
162+
}
163+
159164
// SuffixRange generates a new uniformly random range of suffixes (low, high]
160165
// such that high is guaranteed to be strictly greater (as defined by
161166
// ComparePointSuffixes) than low.

0 commit comments

Comments
 (0)