Skip to content

Commit

Permalink
[dnm] use scans in kvnemeses
Browse files Browse the repository at this point in the history
Hack up just enough support for scans to see if we can perhaps tickle
the release blocker here:

cockroachdb#46652

No validation was added. We're just using kvnemeses to send random
scans for us.

Release note: None
  • Loading branch information
tbg committed Apr 7, 2020
1 parent 6365a3f commit 655c9ea
Show file tree
Hide file tree
Showing 7 changed files with 513 additions and 106 deletions.
31 changes: 30 additions & 1 deletion pkg/kv/kvnemesis/applier.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (a *Applier) getNextDBRoundRobin() (*kv.DB, int32) {

func applyOp(ctx context.Context, db *kv.DB, op *Operation) {
switch o := op.GetValue().(type) {
case *GetOperation, *PutOperation, *BatchOperation:
case *ScanOperation, *GetOperation, *PutOperation, *BatchOperation:
applyClientOp(ctx, db, op)
case *SplitOperation:
err := db.AdminSplit(ctx, o.Key, o.Key, hlc.MaxTimestamp)
Expand Down Expand Up @@ -121,13 +121,26 @@ func applyOp(ctx context.Context, db *kv.DB, op *Operation) {
}

type clientI interface {
Scan(_ context.Context, _, _ interface{}, maxRows int64) ([]kv.KeyValue, error)
Get(context.Context, interface{}) (kv.KeyValue, error)
Put(context.Context, interface{}, interface{}) error
Run(context.Context, *kv.Batch) error
}

func applyClientOp(ctx context.Context, db clientI, op *Operation) {
switch o := op.GetValue().(type) {
case *ScanOperation:
results, err := db.Scan(ctx, o.Key, o.EndKey, o.MaxRows)
if err != nil {
o.Result = resultError(ctx, err)
} else {
// TODO(tbg): need more than one value. For now just pretend there's
// at most one.
o.Result.Type = ResultType_Value
if len(results) != 0 {
o.Result.Value = results[0].Value.RawBytes
}
}
case *GetOperation:
result, err := db.Get(ctx, o.Key)
if err != nil {
Expand All @@ -154,6 +167,8 @@ func applyBatchOp(
) {
for i := range o.Ops {
switch subO := o.Ops[i].GetValue().(type) {
case *ScanOperation:
b.Scan(subO.Key, subO.EndKey) // can't use MaxRows here
case *GetOperation:
b.Get(subO.Key)
case *PutOperation:
Expand All @@ -166,6 +181,20 @@ func applyBatchOp(
o.Result = resultError(ctx, runErr)
for i := range o.Ops {
switch subO := o.Ops[i].GetValue().(type) {
case *ScanOperation:
if b.Results[i].Err != nil {
subO.Result = resultError(ctx, b.Results[i].Err)
} else {
// TODO(tbg): reflect fact that more than one result may have
// been returned. This just picks the first one.
subO.Result.Type = ResultType_Value
if len(b.Results[i].Rows) > 0 {
result := b.Results[i].Rows[0]
if result.Value != nil {
subO.Result.Value = result.Value.RawBytes
}
}
}
case *GetOperation:
if b.Results[i].Err != nil {
subO.Result = resultError(ctx, b.Results[i].Err)
Expand Down
23 changes: 21 additions & 2 deletions pkg/kv/kvnemesis/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ type ClosureTxnConfig struct {
// bread-and-butter kv operations such as Get/Put/Delete/etc. These can all be
// run on a DB, a Txn, or a Batch.
type ClientOperationConfig struct {
// Scan a random (nonempty) key range.
Scan int
// GetMissing is an operation that Gets a key that definitely doesn't exist.
GetMissing int
// GetExisting is an operation that Gets a key that likely exists.
Expand Down Expand Up @@ -130,8 +132,9 @@ type ChangeReplicasConfig struct {
// yet pass (for example, if the new operation finds a kv bug or edge case).
func newAllOperationsConfig() GeneratorConfig {
clientOpConfig := ClientOperationConfig{
GetMissing: 1,
GetExisting: 1,
Scan: 1,
GetMissing: 0, // HACK(tbg)
GetExisting: 0, // HACK(tbg)
PutMissing: 1,
PutExisting: 1,
}
Expand Down Expand Up @@ -351,6 +354,7 @@ func (g *generator) selectOp(rng *rand.Rand, contextuallyValid []opGen) Operatio
func (g *generator) registerClientOps(allowed *[]opGen, c *ClientOperationConfig) {
addOpGen(allowed, randGetMissing, c.GetMissing)
addOpGen(allowed, randPutMissing, c.PutMissing)
addOpGen(allowed, randScan, c.Scan)
if len(g.keys) > 0 {
addOpGen(allowed, randGetExisting, c.GetExisting)
addOpGen(allowed, randPutExisting, c.PutExisting)
Expand All @@ -361,6 +365,17 @@ func (g *generator) registerBatchOps(allowed *[]opGen, c *BatchOperationConfig)
addOpGen(allowed, makeRandBatch(&c.Ops), c.Batch)
}

func randScan(g *generator, rng *rand.Rand) Operation {
from, to := randKey(rng), randKey(rng)
if to < from {
from, to = to, from
} else if from == to {
to += "\x00"
}
maxRows := rng.Intn(1 + len(g.keys)/2)
return scan(from, to, maxRows)
}

func randGetMissing(_ *generator, rng *rand.Rand) Operation {
return get(randKey(rng))
}
Expand Down Expand Up @@ -548,6 +563,10 @@ func closureTxnCommitInBatch(commitInBatch []Operation, ops ...Operation) Operat
return o
}

func scan(from, to string, n int) Operation {
return Operation{Scan: &ScanOperation{Key: []byte(from), EndKey: []byte(to), MaxRows: int64(n)}}
}

func get(key string) Operation {
return Operation{Get: &GetOperation{Key: []byte(key)}}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/kv/kvnemesis/kvnemesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func RunNemesis(
config GeneratorConfig,
dbs ...*kv.DB,
) ([]error, error) {
const concurrency, numSteps = 5, 30
const concurrency, numSteps = 5, 300

g, err := MakeGenerator(config, newGetReplicasFn(dbs...))
if err != nil {
Expand Down
28 changes: 28 additions & 0 deletions pkg/kv/kvnemesis/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
// Result returns the Result field of the given Operation.
func (op Operation) Result() *Result {
switch o := op.GetValue().(type) {
case *ScanOperation:
return &o.Result
case *GetOperation:
return &o.Result
case *PutOperation:
Expand Down Expand Up @@ -90,6 +92,8 @@ func (op Operation) String() string {

func (op Operation) format(w *strings.Builder, fctx formatCtx) {
switch o := op.GetValue().(type) {
case *ScanOperation:
o.format(w, fctx)
case *GetOperation:
o.format(w, fctx)
case *PutOperation:
Expand Down Expand Up @@ -154,6 +158,30 @@ func (op Operation) format(w *strings.Builder, fctx formatCtx) {
}
}

func (op ScanOperation) format(w *strings.Builder, fctx formatCtx) {
fmt.Fprintf(w, `%s.Scan(ctx, %s, %s, %d)`,
fctx.receiver,
roachpb.Key(op.Key),
roachpb.Key(op.EndKey),
op.MaxRows)
switch op.Result.Type {
case ResultType_Error:
err := errors.DecodeError(context.TODO(), *op.Result.Err)
fmt.Fprintf(w, ` // (nil, %s)`, err.Error())
case ResultType_Value:
v := `nil`
if len(op.Result.Value) > 0 {
value, err := roachpb.Value{RawBytes: op.Result.Value}.GetBytes()
if err != nil {
v = fmt.Sprintf(`<err:%s>`, err.Error())
} else {
v = `"` + string(value) + `"`
}
}
fmt.Fprintf(w, ` // (%s, nil)`, v)
}
}

func (op GetOperation) format(w *strings.Builder, fctx formatCtx) {
fmt.Fprintf(w, `%s.Get(ctx, %s)`, fctx.receiver, roachpb.Key(op.Key))
switch op.Result.Type {
Expand Down
Loading

0 comments on commit 655c9ea

Please sign in to comment.