mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-27 09:05:18 +00:00
190 lines
5.4 KiB
Go
190 lines
5.4 KiB
Go
// Copyright 2019 The LevelDB-Go and Pebble Authors. All rights reserved. Use
|
|
// of this source code is governed by a BSD-style license that can be found in
|
|
// the LICENSE file.
|
|
|
|
package metamorphic
|
|
|
|
import "github.com/cockroachdb/pebble/internal/randvar"
|
|
|
|
type opType int
|
|
|
|
const (
|
|
batchAbort opType = iota
|
|
batchCommit
|
|
dbCheckpoint
|
|
dbClose
|
|
dbCompact
|
|
dbFlush
|
|
dbRatchetFormatMajorVersion
|
|
dbRestart
|
|
iterClose
|
|
iterFirst
|
|
iterLast
|
|
iterNext
|
|
iterNextWithLimit
|
|
iterNextPrefix
|
|
iterCanSingleDelete
|
|
iterPrev
|
|
iterPrevWithLimit
|
|
iterSeekGE
|
|
iterSeekGEWithLimit
|
|
iterSeekLT
|
|
iterSeekLTWithLimit
|
|
iterSeekPrefixGE
|
|
iterSetBounds
|
|
iterSetOptions
|
|
newBatch
|
|
newIndexedBatch
|
|
newIter
|
|
newIterUsingClone
|
|
newSnapshot
|
|
readerGet
|
|
replicate
|
|
snapshotClose
|
|
writerApply
|
|
writerDelete
|
|
writerDeleteRange
|
|
writerIngest
|
|
writerMerge
|
|
writerRangeKeyDelete
|
|
writerRangeKeySet
|
|
writerRangeKeyUnset
|
|
writerSet
|
|
writerSingleDelete
|
|
)
|
|
|
|
type config struct {
|
|
// Weights for the operation mix to generate. ops[i] corresponds to the
|
|
// weight for opType(i).
|
|
ops []int
|
|
|
|
// newPrefix configures the probability that when generating a new user key,
|
|
// the generated key uses a new key prefix rather than an existing prefix
|
|
// with a suffix.
|
|
newPrefix float64
|
|
// writeSuffixDist defines the distribution of key suffixes during writing.
|
|
// It's a dynamic randvar to roughly emulate workloads with MVCC timestamps,
|
|
// skewing towards most recent timestamps.
|
|
writeSuffixDist randvar.Dynamic
|
|
|
|
// numInstances defines the number of pebble instances created for this
|
|
// metamorphic test run.
|
|
numInstances int
|
|
|
|
// TODO(peter): unimplemented
|
|
// keyDist randvar.Dynamic
|
|
// keySizeDist randvar.Static
|
|
// valueSizeDist randvar.Static
|
|
// updateFrac float64
|
|
// lowerBoundFrac float64
|
|
// upperBoundFrac float64
|
|
}
|
|
|
|
func (c config) withNewPrefixProbability(p float64) config {
|
|
c.newPrefix = p
|
|
return c
|
|
}
|
|
|
|
func (c config) withOpWeight(op opType, weight int) config {
|
|
c.ops[op] = weight
|
|
return c
|
|
}
|
|
|
|
var presetConfigs = []config{
|
|
defaultConfig(),
|
|
// Generate a configuration that helps exercise code paths dependent on many
|
|
// versions of keys with the same prefixes. The default configuration does
|
|
// not tend to generate many versions of the same key. Additionally, its
|
|
// relatively high weight for deletion write operations makes it less likely
|
|
// that we'll accumulate enough versions to exercise some code paths (eg,
|
|
// see #2921 which requires >16 SETs for versions of the same prefix to
|
|
// reside in a single block to exercise the code path).
|
|
//
|
|
// To encourage generation of many versions of the same keys, generate a new
|
|
// prefix only 4% of the time when generating a new key. The remaining 96%
|
|
// of new key generations will use an existing prefix. To keep the size of
|
|
// the database growing, we also reduce the probability of delete write
|
|
// operations significantly.
|
|
defaultConfig().
|
|
withNewPrefixProbability(0.04).
|
|
withOpWeight(writerDeleteRange, 1).
|
|
withOpWeight(writerDelete, 5).
|
|
withOpWeight(writerSingleDelete, 5).
|
|
withOpWeight(writerMerge, 0),
|
|
}
|
|
|
|
var multiInstancePresetConfig = multiInstanceConfig()
|
|
|
|
func defaultConfig() config {
|
|
return config{
|
|
// dbClose is not in this list since it is deterministically generated once, at the end of the test.
|
|
ops: []int{
|
|
batchAbort: 5,
|
|
batchCommit: 5,
|
|
dbCheckpoint: 1,
|
|
dbCompact: 1,
|
|
dbFlush: 2,
|
|
dbRatchetFormatMajorVersion: 1,
|
|
dbRestart: 2,
|
|
iterClose: 5,
|
|
iterFirst: 100,
|
|
iterLast: 100,
|
|
iterNext: 100,
|
|
iterNextWithLimit: 20,
|
|
iterNextPrefix: 20,
|
|
iterCanSingleDelete: 20,
|
|
iterPrev: 100,
|
|
iterPrevWithLimit: 20,
|
|
iterSeekGE: 100,
|
|
iterSeekGEWithLimit: 20,
|
|
iterSeekLT: 100,
|
|
iterSeekLTWithLimit: 20,
|
|
iterSeekPrefixGE: 100,
|
|
iterSetBounds: 100,
|
|
iterSetOptions: 10,
|
|
newBatch: 5,
|
|
newIndexedBatch: 5,
|
|
newIter: 10,
|
|
newIterUsingClone: 5,
|
|
newSnapshot: 10,
|
|
readerGet: 100,
|
|
replicate: 0,
|
|
snapshotClose: 10,
|
|
writerApply: 10,
|
|
writerDelete: 100,
|
|
writerDeleteRange: 50,
|
|
writerIngest: 100,
|
|
writerMerge: 100,
|
|
writerRangeKeySet: 10,
|
|
writerRangeKeyUnset: 10,
|
|
writerRangeKeyDelete: 5,
|
|
writerSet: 100,
|
|
writerSingleDelete: 50,
|
|
},
|
|
// Use a new prefix 75% of the time (and 25% of the time use an existing
|
|
// prefix with an alternative suffix).
|
|
newPrefix: 0.75,
|
|
// Use a skewed distribution of suffixes to mimic MVCC timestamps. The
|
|
// range will be widened whenever a suffix is found to already be in use
|
|
// for a particular prefix.
|
|
writeSuffixDist: mustDynamic(randvar.NewSkewedLatest(0, 1, 0.99)),
|
|
}
|
|
}
|
|
|
|
func multiInstanceConfig() config {
|
|
cfg := defaultConfig()
|
|
cfg.ops[replicate] = 5
|
|
// Single deletes and merges are disabled in multi-instance mode, as
|
|
// replicateOp doesn't support them.
|
|
cfg.ops[writerSingleDelete] = 0
|
|
cfg.ops[writerMerge] = 0
|
|
return cfg
|
|
}
|
|
|
|
func mustDynamic(dyn randvar.Dynamic, err error) randvar.Dynamic {
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return dyn
|
|
}
|