From 1d221a4ed0e9980e8f11e31700714bb4afdb383c Mon Sep 17 00:00:00 2001 From: haojinming Date: Tue, 26 Jul 2022 10:44:11 +0800 Subject: [PATCH 1/7] add tikv v2 br test Signed-off-by: haojinming --- .github/workflows/ci-br.yml | 8 +- br/Makefile | 14 +- br/tests/rawkv/client.go | 383 ------------------------------------ br/tests/rawkv/go.mod | 17 +- br/tests/rawkv/go.sum | 79 ++------ br/tests/rawkv/main.go | 297 ++++++++++++++++++++++++++++ br/tests/rawkv/run.py | 79 +++++--- br/tests/rawkv/tikv_br.go | 78 ++++++++ 8 files changed, 467 insertions(+), 488 deletions(-) delete mode 100644 br/tests/rawkv/client.go create mode 100644 br/tests/rawkv/main.go create mode 100644 br/tests/rawkv/tikv_br.go diff --git a/.github/workflows/ci-br.yml b/.github/workflows/ci-br.yml index 11fc8ce8..aaa77d47 100644 --- a/.github/workflows/ci-br.yml +++ b/.github/workflows/ci-br.yml @@ -65,6 +65,7 @@ jobs: strategy: matrix: tikv_version: [nightly] + api_version: [1, 2] steps: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 @@ -74,12 +75,15 @@ jobs: run: curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh - name: start tikv cluster run: | - # start tikv in apiv1ttl - /home/runner/.tiup/bin/tiup playground ${{ matrix.tikv_version }} --mode tikv-slim --kv 1 --without-monitor --kv.config /home/runner/work/migration/migration/.github/config/br_rawkv.toml --pd.config /home/runner/work/migration/migration/.github/config/br_pd.toml &> raw.out 2>&1 & + # start tikv + echo -e "[storage]\napi-version=${{ matrix.api_version }}\nenable-ttl=true" > br_tikv.toml + /home/runner/.tiup/bin/tiup playground ${{ matrix.tikv_version }} --mode tikv-slim --kv 1 --without-monitor --kv.config br_tikv.toml --pd.config /home/runner/work/migration/migration/.github/config/br_pd.toml &> raw.out 2>&1 & # The first run of `tiup` has to download all components so it'll take longer. sleep 1m 30s # Parse PD address from `tiup` output echo "PD_ADDR=$(cat raw.out | grep -oP '(?<=PD client endpoints: \[)[0-9\.:]+(?=\])')" >> $GITHUB_ENV + # Ouput the api version + echo "API_VERSION=${{ matrix.api_version }}" >> $GITHUB_ENV # Log the output echo "$(cat raw.out)" >&2 - name: run integration test diff --git a/br/Makefile b/br/Makefile index 7f377428..cd3ac6fc 100644 --- a/br/Makefile +++ b/br/Makefile @@ -28,6 +28,7 @@ COVERAGE_DIR ?= build TEST_PARALLEL ?= 8 PD_ADDR ?= 127.0.0.1:2379 BR_LOCAL_STORE ?= /tmp/backup_restore_test +API_VERSION ?= 1 LDFLAGS += -X "github.com/tikv/migration/br/pkg/version/build.ReleaseVersion=$(shell git describe --tags --dirty --always)" LDFLAGS += -X "github.com/tikv/migration/br/pkg/version/build.BuildTS=$(shell date -u '+%Y-%m-%d %H:%M:%S')" @@ -57,10 +58,11 @@ test: tools/bin/gocov tools/bin/gocov-xml tools/bin/gocov convert $(COVERAGE_DIR)/coverage.raw | tools/bin/gocov-xml > $(COVERAGE_DIR)/coverage.xml make failpoint/disable -test/integration: build/br-test build/rawkv-helper - ./tests/rawkv/run.py --test-helper=bin/rawkv --pd=$(PD_ADDR) \ - --br='$(TEST_BIN_PATH) -test.coverprofile=cov.br_rawkv.out.log DEVEL' \ - --br-storage=local://$(BR_LOCAL_STORE) +test/integration: build/br-test build/rawkv-integration-test + ./bin/rawkv_test --pd=${PD_ADDR} \ + --br='${TEST_BIN_PATH}' \ + --br-storage=${BR_LOCAL_STORE} \ + --api-version=${API_VERSION} failpoint/enable: tools/bin/failpoint-ctl find `pwd` -type d | grep -vE "(\.git|tools)" | xargs tools/bin/failpoint-ctl enable @@ -86,8 +88,8 @@ build: release: CGO_ENABLED=1 $(GO) build -tags codes -ldflags '$(LDFLAGS)' -o $(BR_BIN_PATH) cmd/br/*.go -build/rawkv-helper: - cd tests/rawkv && $(GO) build -mod=mod -o ../../bin/rawkv client.go +build/rawkv-integration-test: + cd tests/rawkv && $(GO) build -mod=mod -o ../../bin/rawkv_test *.go build/br-test: @make failpoint/enable diff --git a/br/tests/rawkv/client.go b/br/tests/rawkv/client.go deleted file mode 100644 index dd59e698..00000000 --- a/br/tests/rawkv/client.go +++ /dev/null @@ -1,383 +0,0 @@ -package main - -import ( - "bytes" - "context" - "encoding/hex" - "flag" - "fmt" - "hash/crc64" - "math/rand" - "strings" - "time" - - "github.com/pingcap/errors" - "github.com/pingcap/log" - "github.com/tikv/client-go/v2/config" - "github.com/tikv/client-go/v2/rawkv" - "go.uber.org/zap" -) - -var ( - ca = flag.String("ca", "", "CA certificate path for TLS connection") - cert = flag.String("cert", "", "certificate path for TLS connection") - key = flag.String("key", "", "private key path for TLS connection") - pdAddr = flag.String("pd", "127.0.0.1:2379", "Address of PD") - runMode = flag.String("mode", "", "Mode. One of 'rand-gen', 'checksum', 'scan', 'diff', 'delete' and 'put'") - startKeyStr = flag.String("start-key", "", "Start key in hex") - endKeyStr = flag.String("end-key", "", "End key in hex") - keyMaxLen = flag.Int("key-max-len", 32, "Max length of keys for rand-gen mode") - concurrency = flag.Int("concurrency", 32, "Concurrency to run rand-gen") - duration = flag.Int("duration", 10, "duration(second) of rand-gen") - putDataStr = flag.String("put-data", "", "Kv pairs to put to the cluster in hex. "+ - "kv pairs are separated by commas, key and value in a pair are separated by a colon") -) - -func createClient(addr string) (*rawkv.Client, error) { - cli, err := rawkv.NewClient(context.TODO(), []string{addr}, config.Security{ - ClusterSSLCA: *ca, - ClusterSSLCert: *cert, - ClusterSSLKey: *key, - }) - return cli, errors.Trace(err) -} - -func main() { - flag.Parse() - - startKey, err := hex.DecodeString(*startKeyStr) - if err != nil { - log.Panic("Invalid startKey", zap.String("starkey", *startKeyStr), zap.Error(err)) - } - endKey, err := hex.DecodeString(*endKeyStr) - if err != nil { - log.Panic("Invalid endKey: %v, err: %+v", zap.String("endkey", *endKeyStr), zap.Error(err)) - } - // For "put" mode, the key range is not used. So no need to throw error here. - if len(endKey) == 0 && *runMode != "put" { - log.Panic("Empty endKey is not supported yet") - } - - if *runMode == "test-rand-key" { - testRandKey(startKey, endKey, *keyMaxLen) - return - } - - client, err := createClient(*pdAddr) - if err != nil { - log.Panic("Failed to create client", zap.String("pd", *pdAddr), zap.Error(err)) - } - - switch *runMode { - case "rand-gen": - err = randGenWithDuration(client, startKey, endKey, *keyMaxLen, *concurrency, *duration) - case "checksum": - err = checksum(client, startKey, endKey) - case "scan": - err = scan(client, startKey, endKey) - case "delete": - err = deleteRange(client, startKey, endKey) - case "put": - err = put(client, *putDataStr) - } - - if err != nil { - log.Panic("Error", zap.Error(err)) - } -} - -func randGenWithDuration(client *rawkv.Client, startKey, endKey []byte, - maxLen int, concurrency int, duration int) error { - var err error - ok := make(chan struct{}) - go func() { - err = randGen(client, startKey, endKey, maxLen, concurrency) - ok <- struct{}{} - }() - select { - case <-time.After(time.Second * time.Duration(duration)): - case <-ok: - } - return errors.Trace(err) -} - -func randGen(client *rawkv.Client, startKey, endKey []byte, maxLen int, concurrency int) error { - log.Info("Start rand-gen", zap.Int("maxlen", maxLen), - zap.String("startkey", hex.EncodeToString(startKey)), zap.String("endkey", hex.EncodeToString(endKey))) - log.Info("Rand-gen will keep running. Please Ctrl+C to stop manually.") - - // Cannot generate shorter key than commonPrefix - commonPrefixLen := 0 - for ; commonPrefixLen < len(startKey) && commonPrefixLen < len(endKey) && - startKey[commonPrefixLen] == endKey[commonPrefixLen]; commonPrefixLen++ { - continue - } - - if maxLen < commonPrefixLen { - return errors.Errorf("maxLen (%v) < commonPrefixLen (%v)", maxLen, commonPrefixLen) - } - - const batchSize = 32 - - errCh := make(chan error, concurrency) - for i := 0; i < concurrency; i++ { - go func() { - for { - // FIXME: because of the incompatibility of `BatchPut`, - // we must use RawPut here. See https://github.com/tikv/client-go/pull/403. - // Once the client get fixed, we'd better use the BatchPut API back. - // keys := make([][]byte, 0, batchSize) - // values := make([][]byte, 0, batchSize) - - for i := 0; i < batchSize; i++ { - key := randKey(startKey, endKey, maxLen) - value := randValue() - - // keys = append(keys, key) - // values = append(values, value) - err := client.Put(context.Background(), key, value) - - if err != nil { - errCh <- errors.Trace(err) - } - } - - } - }() - } - - err := <-errCh - if err != nil { - return errors.Trace(err) - } - - return nil -} - -func testRandKey(startKey, endKey []byte, maxLen int) { - for { - k := randKey(startKey, endKey, maxLen) - if bytes.Compare(k, startKey) < 0 || bytes.Compare(k, endKey) >= 0 { - panic(hex.EncodeToString(k)) - } - } -} - -func randKey(startKey, endKey []byte, maxLen int) []byte { -Retry: - for { // Regenerate on fail - result := make([]byte, 0, maxLen) - - upperUnbounded := false - lowerUnbounded := false - - for i := 0; i < maxLen; i++ { - upperBound := 256 - if !upperUnbounded { - if i >= len(endKey) { - // The generated key is the same as endKey which is invalid. Regenerate it. - continue Retry - } - upperBound = int(endKey[i]) + 1 - } - - lowerBound := 0 - if !lowerUnbounded { - if i >= len(startKey) { - lowerUnbounded = true - } else { - lowerBound = int(startKey[i]) - } - } - - if lowerUnbounded { - if rand.Intn(257) == 0 { - return result - } - } - - value := rand.Intn(upperBound - lowerBound) - value += lowerBound - - if value < upperBound-1 { - upperUnbounded = true - } - if value > lowerBound { - lowerUnbounded = true - } - - result = append(result, uint8(value)) - } - - return result - } -} - -func randValue() []byte { - result := make([]byte, 0, 512) - for i := 0; i < 512; i++ { - value := rand.Intn(257) - if value == 256 { - if i > 0 { - return result - } - value-- - } - result = append(result, uint8(value)) - } - return result -} - -func checksum(client *rawkv.Client, startKey, endKey []byte) error { - log.Info("Start checkcum on range", - zap.String("startkey", hex.EncodeToString(startKey)), zap.String("endkey", hex.EncodeToString(endKey))) - - scanner := newRawKVScanner(client, startKey, endKey) - digest := crc64.New(crc64.MakeTable(crc64.ECMA)) - - var res uint64 - - for { - k, v, err := scanner.Next() - if err != nil { - return errors.Trace(err) - } - if len(k) == 0 { - break - } - _, _ = digest.Write(k) - _, _ = digest.Write(v) - res ^= digest.Sum64() - } - - log.Info("Checksum result", zap.Uint64("checksum", res)) - fmt.Printf("Checksum result: %016x\n", res) - return nil -} - -func deleteRange(client *rawkv.Client, startKey, endKey []byte) error { - log.Info("Start delete data in range", - zap.String("startkey", hex.EncodeToString(startKey)), zap.String("endkey", hex.EncodeToString(endKey))) - return client.DeleteRange(context.TODO(), startKey, endKey) -} - -func scan(client *rawkv.Client, startKey, endKey []byte) error { - log.Info("Start scanning data in range", - zap.String("startkey", hex.EncodeToString(startKey)), zap.String("endkey", hex.EncodeToString(endKey))) - - scanner := newRawKVScanner(client, startKey, endKey) - - var key []byte - for { - k, v, err := scanner.Next() - if err != nil { - return errors.Trace(err) - } - if len(k) == 0 { - break - } - fmt.Printf("key: %v, value: %v\n", hex.EncodeToString(k), hex.EncodeToString(v)) - if bytes.Compare(key, k) >= 0 { - log.Error("Scan result is not in order", - zap.String("Previous key", hex.EncodeToString(key)), zap.String("Current key", hex.EncodeToString(k))) - } - } - - log.Info("Finished Scanning.") - return nil -} - -func put(client *rawkv.Client, dataStr string) error { - keys := make([][]byte, 0) - values := make([][]byte, 0) - - for _, pairStr := range strings.Split(dataStr, ",") { - pair := strings.Split(pairStr, ":") - if len(pair) != 2 { - return errors.Errorf("invalid kv pair string %q", pairStr) - } - - key, err := hex.DecodeString(strings.Trim(pair[0], " ")) - if err != nil { - return errors.Annotatef(err, "invalid kv pair string %q", pairStr) - } - value, err := hex.DecodeString(strings.Trim(pair[1], " ")) - if err != nil { - return errors.Annotatef(err, "invalid kv pair string %q", pairStr) - } - - keys = append(keys, key) - values = append(values, value) - // FIXME: because of the incompatibility of `BatchPut`, - // we must use RawPut here. See https://github.com/tikv/client-go/pull/403. - // Once the client get fixed, we'd better use the BatchPut API back. - if err := client.Put(context.Background(), key, value); err != nil { - return err - } - } - - log.Info("Put rawkv data", zap.ByteStrings("keys", keys), zap.ByteStrings("values", values)) - - return nil -} - -const defaultScanBatchSize = 128 - -type rawKVScanner struct { - client *rawkv.Client - batchSize int - - currentKey []byte - endKey []byte - - bufferKeys [][]byte - bufferValues [][]byte - bufferCursor int - noMore bool -} - -func newRawKVScanner(client *rawkv.Client, startKey, endKey []byte) *rawKVScanner { - return &rawKVScanner{ - client: client, - batchSize: defaultScanBatchSize, - - currentKey: startKey, - endKey: endKey, - - noMore: false, - } -} - -func (s *rawKVScanner) Next() ([]byte, []byte, error) { - if s.bufferCursor >= len(s.bufferKeys) { - if s.noMore { - return nil, nil, nil - } - - s.bufferCursor = 0 - - batchSize := s.batchSize - var err error - s.bufferKeys, s.bufferValues, err = s.client.Scan(context.TODO(), s.currentKey, s.endKey, batchSize) - if err != nil { - return nil, nil, errors.Trace(err) - } - - if len(s.bufferKeys) < batchSize { - s.noMore = true - } - - if len(s.bufferKeys) == 0 { - return nil, nil, nil - } - - bufferKey := s.bufferKeys[len(s.bufferKeys)-1] - bufferKey = append(bufferKey, 0) - s.currentKey = bufferKey - } - - key := s.bufferKeys[s.bufferCursor] - value := s.bufferValues[s.bufferCursor] - s.bufferCursor++ - return key, value, nil -} diff --git a/br/tests/rawkv/go.mod b/br/tests/rawkv/go.mod index 25cad053..4f22e6d1 100644 --- a/br/tests/rawkv/go.mod +++ b/br/tests/rawkv/go.mod @@ -1,12 +1,16 @@ module github.com/tikv/migration/br/tests/br_rawkv -go 1.17 +go 1.18 require ( - github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c + github.com/docker/go-units v0.4.0 + github.com/juju/errors v1.0.0 + github.com/pingcap/kvproto v0.0.0-20220705053936-aa9c2d20cd2a github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee - github.com/tikv/client-go/v2 v2.0.0 + github.com/tikv/client-go/v2 v2.0.1-0.20220721031657-e38d2b07de3f + github.com/tikv/pd/client v0.0.0-20220307081149-841fa61e9710 go.uber.org/zap v1.21.0 + google.golang.org/grpc v1.43.0 ) require ( @@ -15,18 +19,18 @@ require ( github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/btree v1.0.0 // indirect + github.com/google/btree v1.1.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect github.com/pingcap/failpoint v0.0.0-20210918120811-547c13e3eb00 // indirect - github.com/pingcap/kvproto v0.0.0-20220106070556-3fa8fa04f898 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect - github.com/tikv/pd/client v0.0.0-20220216070739-26c668271201 // indirect + github.com/stathat/consistent v1.0.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect @@ -34,7 +38,6 @@ require ( golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect golang.org/x/text v0.3.6 // indirect google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect - google.golang.org/grpc v1.43.0 // indirect google.golang.org/protobuf v1.26.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect ) diff --git a/br/tests/rawkv/go.sum b/br/tests/rawkv/go.sum index 077a8706..a7dcec9e 100644 --- a/br/tests/rawkv/go.sum +++ b/br/tests/rawkv/go.sum @@ -18,9 +18,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -28,15 +25,12 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -44,8 +38,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -54,8 +46,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -79,9 +69,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf h1:gFVkHXmVAhEbxZVDln5V9GKrLaluNoFHDbrZwAWZgws= -github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -91,20 +80,18 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM= +github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -115,8 +102,10 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -125,17 +114,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= @@ -149,9 +127,9 @@ github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c/go.mod h1:X2r9ue github.com/pingcap/failpoint v0.0.0-20210918120811-547c13e3eb00 h1:C3N3itkduZXDZFh4N3vQ5HEtld3S+Y+StULhWVvumU0= github.com/pingcap/failpoint v0.0.0-20210918120811-547c13e3eb00/go.mod h1:4qGtCB0QK0wBzKtFEGDhxXnSnbQApw1gc9siScUl8ew= github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 h1:surzm05a8C9dN8dIUmo4Be2+pMRb6f55i+UIYrluu2E= -github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw= -github.com/pingcap/kvproto v0.0.0-20220106070556-3fa8fa04f898 h1:c0d/sMTeftJQF9O5OHyezWwPrzf2FXcEE5HWwnq/Ahs= -github.com/pingcap/kvproto v0.0.0-20220106070556-3fa8fa04f898/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20220302110454-c696585a961b/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20220705053936-aa9c2d20cd2a h1:nP2wmyw9JTRsk5rm+tZtfAso6c/1FvuaFNbXTaYz3FE= +github.com/pingcap/kvproto v0.0.0-20220705053936-aa9c2d20cd2a/go.mod h1:OYtxs0786qojVTmkVeufx93xe+jUgm56GUYRIKnmaGI= github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee h1:VO2t6IBpfvW34TdtD/G10VvnGqjLic1jzOuHjUb5VqM= github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4= @@ -180,13 +158,14 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/stathat/consistent v1.0.0 h1:ZFJ1QTRn8npNBKW065raSZ8xfOqhpb8vLOkfp4CcL/U= +github.com/stathat/consistent v1.0.0/go.mod h1:uajTPbgSygZBJ+V+0mY7meZ8i0XAcZs7AQ6V121XSxw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -195,17 +174,13 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tikv/client-go/v2 v2.0.0 h1:XsYR7TwtyJbF6l6kyFG0RSAR7g2ftyl8LWbOAmq+CVI= -github.com/tikv/client-go/v2 v2.0.0/go.mod h1:gaHSp8rnxZ0w36qb6QPPNPh9P0Mu5vAEwCQcc0Brni4= -github.com/tikv/pd/client v0.0.0-20220216070739-26c668271201 h1:7h/Oi4Zw6eGCeXh4Q4ZvKI4k7nBJVUq0c29YCcLwKPM= -github.com/tikv/pd/client v0.0.0-20220216070739-26c668271201/go.mod h1:fEvI5fhAuJn1Fn87VJF8ByE9Vc16EzWGoePZB21/nL8= -github.com/twmb/murmur3 v1.1.3/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/tikv/client-go/v2 v2.0.1-0.20220721031657-e38d2b07de3f h1:fCAWVzUJYee1pDqYTBt5j2G1WuUfOL7A2mZoONoaHgs= +github.com/tikv/client-go/v2 v2.0.1-0.20220721031657-e38d2b07de3f/go.mod h1:UmDQEoeHXza8RSHBXVFERpxH54VBOf8yKZVphyel3l4= +github.com/tikv/pd/client v0.0.0-20220307081149-841fa61e9710 h1:jxgmKOscXSjaFEKQGRyY5qOpK8hLqxs2irb/uDJMtwk= +github.com/tikv/pd/client v0.0.0-20220307081149-841fa61e9710/go.mod h1:AtvppPwkiyUgQlR1W9qSqfTB+OsOIu19jDCOxOsPkmU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/etcd/api/v3 v3.5.2/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= -go.etcd.io/etcd/client/pkg/v3 v3.5.2/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v3 v3.5.2/go.mod h1:kOOaWFFgHygyT0WlSmL8TJiXmMysO/nNUlEsSsN6W4o= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -217,7 +192,6 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= @@ -228,7 +202,6 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.20.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= @@ -251,7 +224,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -261,7 +233,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -282,25 +253,18 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -328,7 +292,6 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -372,24 +335,22 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +stathat.com/c/consistent v1.0.0 h1:ezyc51EGcRPJUxfHGSgJjWzJdj3NiMU9pNfLNGiXV0c= diff --git a/br/tests/rawkv/main.go b/br/tests/rawkv/main.go new file mode 100644 index 00000000..74f01aa6 --- /dev/null +++ b/br/tests/rawkv/main.go @@ -0,0 +1,297 @@ +package main + +import ( + "context" + "flag" + "fmt" + "math" + "os" + "os/exec" + "regexp" + "strconv" + "strings" + "time" + + units "github.com/docker/go-units" + "github.com/juju/errors" + "github.com/pingcap/kvproto/pkg/kvrpcpb" + "github.com/pingcap/log" + "github.com/tikv/client-go/v2/oracle" + "github.com/tikv/client-go/v2/rawkv" + pd "github.com/tikv/pd/client" + "go.uber.org/zap" + "google.golang.org/grpc" +) + +var ( + maxMsgSize = int(128 * units.MiB) // pd.ScanRegion may return a large response + maxBatchSize = uint(1024) // max batch size with BatchPut + + pdAddr = flag.String("pd", "127.0.0.1:2379", "Address of PD") + apiVersionInt = flag.Uint("api-version", 1, "Api version of tikv-server") + br = flag.String("br", "br", "The br binary to be tested.") + brStorage = flag.String("br-storage", "local:///tmp/backup_restore_test", "The url to store SST files of backup/resotre. Default: 'local:///tmp/backup_restore_test'") +) + +type RawKVBRTester struct { + pdAddr string + apiVersion kvrpcpb.APIVersion + br string + brStorage string + rawkvClient *rawkv.Client + pdClient pd.Client +} + +func NewPDClient(ctx context.Context, pdAddrs string) (pd.Client, error) { + addrs := strings.Split(pdAddrs, ",") + maxCallMsgSize := []grpc.DialOption{ + grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize)), + grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(maxMsgSize)), + } + return pd.NewClientWithContext( + ctx, addrs, pd.SecurityOption{}, + pd.WithGRPCDialOptions(maxCallMsgSize...), + pd.WithCustomTimeoutOption(10*time.Second), + pd.WithMaxErrorRetry(3), + ) +} + +func NewRawKVBRTester(ctx context.Context, pd, br, storage string, version kvrpcpb.APIVersion) (*RawKVBRTester, error) { + cli, err := rawkv.NewClientWithOpts(context.TODO(), []string{pd}, + rawkv.WithAPIVersion(version)) + if err != nil { + fmt.Println("fail to new rawkv client", err) + return nil, err + } + pdClient, err := NewPDClient(ctx, pd) + if err != nil { + fmt.Println("fail to new pd client", err) + return nil, err + } + return &RawKVBRTester{ + pdAddr: pd, + br: br, + apiVersion: version, + brStorage: storage, + rawkvClient: cli, + pdClient: pdClient, + }, nil +} + +func (t *RawKVBRTester) Close() { + if t.rawkvClient != nil { + t.rawkvClient.Close() + } + t.pdClient.Close() +} + +func min(left, right uint) uint { + if left < right { + return left + } else { + return right + } +} + +func GenerateTestData(keyIndex uint, prefix []byte) (key, value []byte) { + key = []byte(fmt.Sprintf("%s:_%019d", string(prefix), keyIndex)) + value = []byte(fmt.Sprintf("v0%020d", keyIndex)) + return key, value +} + +func BatchGenerateData(keyIndex uint, keyCnt uint, prefix []byte) (keys, values [][]byte) { + keys = make([][]byte, 0, keyCnt) + values = make([][]byte, 0, keyCnt) + for idx := keyIndex; idx < keyIndex+keyCnt; idx++ { + key, value := GenerateTestData(idx, prefix) + keys = append(keys, key) + values = append(values, value) + } + return keys, values +} + +// TODO: make it concurrency for large scale data. +func (t *RawKVBRTester) PreloadData(ctx context.Context, keyCnt uint, prefix []byte) error { + startIdx := uint(0) + for startIdx < keyCnt { + batchCnt := min(maxBatchSize, keyCnt-startIdx) + keys, values := BatchGenerateData(startIdx, batchCnt, prefix) + err := t.rawkvClient.BatchPut(ctx, keys, values) + if err != nil { + return errors.Trace(err) + } + startIdx += batchCnt + } + return nil +} + +func (t *RawKVBRTester) CleanData(ctx context.Context, prefix []byte) error { + return t.rawkvClient.DeleteRange(ctx, prefix, append(prefix, 0)) +} + +func (t *RawKVBRTester) Checksum(ctx context.Context) (rawkv.RawChecksum, error) { + return t.rawkvClient.Checksum(ctx, []byte{}, []byte{}) +} + +func (t *RawKVBRTester) Backup(ctx context.Context, dstAPIVersion kvrpcpb.APIVersion, safeInterval int64) ([]byte, error) { + brCmd := NewTiKVBrCmd("backup raw") + brCmdStr := brCmd.Pd(t.pdAddr). + Storage(t.brStorage, true). + CheckReq(false). + DstApiVersion(dstAPIVersion.String()). + SafeInterval(safeInterval). + Checksum(true). + Build() + return t.ExecBRCmd(ctx, brCmdStr) +} + +func (t *RawKVBRTester) Restore(ctx context.Context) ([]byte, error) { + brCmd := NewTiKVBrCmd("restore raw") + brCmdStr := brCmd.Pd(t.pdAddr). + Storage(t.brStorage, true). + CheckReq(false). + Checksum(true). + Build() + return t.ExecBRCmd(ctx, brCmdStr) +} + +func (t *RawKVBRTester) InjectFailpoint(failpoint string) error { + return os.Setenv("GO_FAILPOINTS", failpoint) +} + +func (t *RawKVBRTester) ExecBRCmd(ctx context.Context, cmdStr string) ([]byte, error) { + cmd := exec.CommandContext(ctx, t.br, strings.Split(cmdStr, " ")...) + return cmd.Output() +} + +func (t *RawKVBRTester) ClearStorage() error { + return os.RemoveAll(t.brStorage) +} + +func (t *RawKVBRTester) GetTso(ctx context.Context) (uint64, error) { + p, l, err := t.pdClient.GetTS(ctx) + if err != nil { + return 0, err + } + return oracle.ComposeTS(p, l), nil +} + +func ParseBackupTSFromOutput(output []byte) uint64 { + flysnowRegexp := regexp.MustCompile(`BackupTS=([0-9]*)]`) + if flysnowRegexp == nil { + log.Panic("regex error") + } + params := flysnowRegexp.FindStringSubmatch(string(output)) + + log.Info("backup output", zap.ByteString("output", output), zap.Int("match len", len(params))) + for _, param := range params { + log.Info("regex output", zap.String("regex output", param)) + } + backupTs, err := strconv.ParseUint(params[len(params)-1], 10, 64) + if err != nil { + log.Panic("parse backup ts fails", zap.String("ts", params[len(params)-1])) + } + log.Info("get backup ts", zap.Uint64("ts", backupTs)) + return backupTs +} + +func CheckBackupTS(apiVersion kvrpcpb.APIVersion, tso uint64, backupOutput []byte, safeInterval int64) { + if apiVersion != kvrpcpb.APIVersion_V2 { + return + } + backupTS := ParseBackupTSFromOutput(backupOutput) + tsoPhysical := oracle.ExtractPhysical(tso) + backupTSPhysical := oracle.ExtractPhysical(backupTS) + diff := (tsoPhysical - backupTSPhysical) / 1000 + if math.Abs(float64(diff-safeInterval)) > 1.0 { + log.Panic("backup ts does not match the rule", zap.Int64("backupTSPhysical", backupTSPhysical), + zap.Int64("tsoPhysical", tsoPhysical), zap.Int64("safeInterval", safeInterval)) + } +} + +func runTestWithFailPoint(failpoint string) { + apiVersion := kvrpcpb.APIVersion_V1TTL + if *apiVersionInt == 2 { + apiVersion = kvrpcpb.APIVersion_V2 + } + ctx := context.TODO() + + fmt.Println("test api version", apiVersion) + + tester, err := NewRawKVBRTester(ctx, *pdAddr, *br, *brStorage, apiVersion) + if err != nil { + log.Panic("New Tester Error", zap.Error(err)) + } + err = tester.InjectFailpoint(failpoint) + if err != nil { + log.Panic("Inject failpoint Error", zap.Error(err)) + } + + if err := tester.ClearStorage(); err != nil { + log.Panic("ClearStorage fail", zap.Error(err)) + } + + prefix := []byte{'a'} + err = tester.PreloadData(ctx, 1000, prefix) + if err != nil { + log.Panic("Preload data fail", zap.Error(err)) + } + + oriChecksum, err := tester.Checksum(ctx) + if err != nil { + log.Panic("Checksum fail", zap.Error(err)) + } + + tso := uint64(0) + if apiVersion == kvrpcpb.APIVersion_V2 { + tso, err = tester.GetTso(ctx) + if err != nil { + log.Panic("Get tso fail", zap.Error(err)) + } + } + safeInterval := int64(120) // 2m + backupOutput, err := tester.Backup(ctx, apiVersion, safeInterval) + if err != nil { + log.Panic("Backup fail", zap.Error(err), zap.ByteString("output", backupOutput)) + } + log.Info("backup finish:", zap.ByteString("output", backupOutput)) + CheckBackupTS(apiVersion, tso, backupOutput, safeInterval) + + err = tester.CleanData(ctx, prefix) + if err != nil { + log.Panic("Clean data fail", zap.Error(err)) + } + restoreOutput, err := tester.Restore(ctx) + if err != nil { + log.Panic("Restore fail", zap.Error(err), zap.ByteString("output", restoreOutput)) + } + log.Info("Restore finish:", zap.ByteString("output", restoreOutput)) + restoreChecksum, err := tester.Checksum(ctx) + if err != nil { + log.Panic("Checksum fail", zap.Error(err)) + } + if oriChecksum != restoreChecksum { + log.Panic("Checksum mismatch", zap.Reflect("OriChecksum", oriChecksum), zap.Reflect("RestoreChecksum", restoreChecksum)) + } + + if apiVersion == kvrpcpb.APIVersion_V1TTL { + if err := tester.ClearStorage(); err != nil { + log.Panic("ClearStorage fail", zap.Error(err)) + } + backupOutput, err := tester.Backup(ctx, kvrpcpb.APIVersion_V2, safeInterval) + if err != nil { + log.Panic("Backup fail", zap.Error(err), zap.ByteString("output", backupOutput)) + } + log.Info("backup conversion finish:", zap.ByteString("output", backupOutput)) + } +} + +func main() { + flag.Parse() + failpoints := []string{"", + "github.com/tikv/migration/br/pkg/backup/tikv-region-error=return(\"region error\")", + } + for _, failpoint := range failpoints { + runTestWithFailPoint(failpoint) + } +} diff --git a/br/tests/rawkv/run.py b/br/tests/rawkv/run.py index dc9637b9..2a30c476 100755 --- a/br/tests/rawkv/run.py +++ b/br/tests/rawkv/run.py @@ -28,32 +28,33 @@ def __init__(self, global_args, failpoints=''): self.helper = global_args.helper self.br_storage = global_args.br_storage self.failpoints = failpoints + self.api_version = global_args.api_version - def test_dst_apiv1(self): + def test_dst_apiv1(self, test_restore): test_name = self.test_dst_apiv1.__name__ storage_dir = self.br_storage + "/" + test_name self._clean(storage_dir) - self._run_br_test("v1", storage_dir) + self._run_br_test("v1", storage_dir, test_restore) self._success_msg(test_name) - def test_dst_apiv1ttl(self): + def test_dst_apiv1ttl(self, test_restore): test_name = self.test_dst_apiv1ttl.__name__ storage_dir = self.br_storage + "/" + test_name self._clean(storage_dir) - self._run_br_test("v1ttl", storage_dir) + self._run_br_test("v1ttl", storage_dir, test_restore) self._success_msg(test_name) - def test_dst_apiv2(self): + def test_dst_apiv2(self, test_restore): test_name = self.test_dst_apiv2.__name__ storage_dir = self.br_storage + "/" + test_name self._clean(storage_dir) - self._run_br_test("v2", storage_dir) + self._run_br_test("v2", storage_dir, test_restore) self._success_msg(test_name) def _clean(self, storage_dir): @@ -67,7 +68,7 @@ def _success_msg(self, case_name): print(f"PASSED: {case_name}") - def _run_br_test(self, dst_api_version, storage_dir): + def _run_br_test(self, dst_api_version, storage_dir, test_restore): outer_start, outer_end = "31", "3130303030303030" inner_start, inner_end = "311111", "311122" @@ -77,34 +78,41 @@ def _run_br_test(self, dst_api_version, storage_dir): # prepare and backup data self._randgen(outer_start, outer_end) - self._run_cmd(self.helper, "-pd", self.pd, "-mode", "put", + self._run_cmd(self.helper, "-pd", self.pd, "-mode", "put", "-api-version", self.api_version, "-put-data", "311121:31, 31112100:32, 311122:33, 31112200:34, 3111220000:35, 311123:36") - self._backup_range(outer_start, outer_end, dst_api_version, storage_dir) + output = self._backup_range(outer_start, outer_end, dst_api_version, storage_dir) + print(output) + matched = re.search("BackupTS=.*", output) + if matched: + print("found BackupTS") + print(matched) + print(str(matched.group(0))[len("BackupTS="):]) + else: + print("Not found BackupTS") + cs_outer_origin = self._get_checksum(outer_start, outer_end) cs_inner_origin = self._get_checksum(inner_start, inner_end) - # clean and restore outer range - self._clean_range(outer_start, outer_end) - cs_outer_clean = self._get_checksum(outer_start, outer_end) - self._assert("clean range failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_clean, cs_outer_empty) - self._restore_range(outer_start, outer_end, dst_api_version, storage_dir) - cs_outer_restore = self._get_checksum(outer_start, outer_end) - self._assert("restore failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_restore, cs_outer_origin) + if test_restore: + # clean and restore outer range + self._clean_range(outer_start, outer_end) + cs_outer_clean = self._get_checksum(outer_start, outer_end) + self._assert("clean range failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_clean, cs_outer_empty) + self._restore_range(outer_start, outer_end, dst_api_version, storage_dir) + cs_outer_restore = self._get_checksum(outer_start, outer_end) + self._assert("restore failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_restore, cs_outer_origin) - # clean and restore inner range - self._clean_range(outer_start, outer_end) - cs_outer_clean = self._get_checksum(outer_start, outer_end) - self._assert("clean range failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_clean, cs_outer_empty) - #self._restore_range(inner_start, inner_end, dst_api_version, storage_dir) - #cs_inner_restore = self._get_checksum(inner_start, inner_end) - #self._assert("restore failed, checksum mismatch.\n actual: {}\n expect: {}", cs_inner_restore, cs_inner_origin) + # clean and restore inner range + self._clean_range(outer_start, outer_end) + cs_outer_clean = self._get_checksum(outer_start, outer_end) + self._assert("clean range failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_clean, cs_outer_empty) def _backup_range(self, start_key, end_key, dst_api_version, storage_dir): env = { 'GO_FAILPOINTS': self.failpoints, } - self._run_cmd(self.br, "--pd", self.pd, "backup", "raw", "-s", storage_dir, + return self._run_cmd(self.br, "--pd", self.pd, "backup", "raw", "-s", storage_dir, "--start", start_key, "--end", end_key, "--format", "hex", "--dst-api-version", dst_api_version, "--check-requirements=false", "-L", "debug", **env) @@ -119,15 +127,21 @@ def _restore_range(self, start_key, end_key, dst_api_version, storage_dir): def _randgen(self, start_key, end_key): - self._run_cmd(self.helper, "-pd", self.pd, "-mode", "rand-gen", "-start-key", start_key, "-end-key", end_key, "-duration", "10") + self._run_cmd(self.helper, "-pd", self.pd, "-mode", "rand-gen", + "-start-key", start_key, "-end-key", end_key, "-duration", "10", + "-api-version", self.api_version) def _clean_range(self, start_key, end_key): - self._run_cmd(self.helper, "-pd", self.pd, "-mode", "delete", "-start-key", start_key, "-end-key", end_key) + self._run_cmd(self.helper, "-pd", self.pd, "-mode", "delete", + "-start-key", start_key, "-end-key", end_key, + "-api-version", self.api_version) def _get_checksum(self, start_key, end_key): - output = self._run_cmd(self.helper, "-pd", self.pd, "-mode", "checksum", "-start-key", start_key, "-end-key", end_key) + output = self._run_cmd(self.helper, "-pd", self.pd, "-mode", "checksum", + "-start-key", start_key, "-end-key", end_key, + "-api-version", self.api_version) matched = re.search("Checksum result: .*", output) if matched: return str(matched.group(0))[len("Checksum result: "):] @@ -173,10 +187,11 @@ def main(): args = parse_args() for failpoint in [''] + FAILPOINTS: tester = rawkvTester(args, failpoints=failpoint) - # tester.test_dst_apiv1() // does not support v1ttl --> v1 - tester.test_dst_apiv1ttl() - # v1ttl -> v2 is not supported in current TiKV, enable this after V1/V1ttl -> V2 is enabled. - # tester.test_dst_apiv2() + if args.api_version == "1": + tester.test_dst_apiv1ttl(True) + tester.test_dst_apiv2(False) # test apiversion conversion + else: + tester.test_dst_apiv2(True) def parse_args(): @@ -189,6 +204,8 @@ def parse_args(): help = "The url to store SST files of backup/resotre. Default: 'local:///tmp/backup_restore_test'") parser.add_argument("--test-helper", dest = "helper", default = "./rawkv", help = "The test helper binary to be used to populate and clean data for the TiKV cluster. Default: './rawkv'") + parser.add_argument("--api-version", dest = "api_version", default = "1", required = True, + help = "The api version of tikv-server") args = parser.parse_args() return args diff --git a/br/tests/rawkv/tikv_br.go b/br/tests/rawkv/tikv_br.go new file mode 100644 index 00000000..eadc8066 --- /dev/null +++ b/br/tests/rawkv/tikv_br.go @@ -0,0 +1,78 @@ +package main + +import ( + "fmt" + "strings" + "time" +) + +const ( + BrTimeout = time.Duration(30) * time.Minute +) + +type TiKVBrRunCmd struct { + command string + options []string + + local bool +} + +func NewTiKVBrCmd(command string) *TiKVBrRunCmd { + b := &TiKVBrRunCmd{command: command} + return b +} + +func (b *TiKVBrRunCmd) Pd(pd string) *TiKVBrRunCmd { + b.options = append(b.options, fmt.Sprintf("--pd=%s", pd)) + return b +} + +func (b *TiKVBrRunCmd) Storage(storage string, isLocal bool) *TiKVBrRunCmd { + b.options = append(b.options, fmt.Sprintf("--storage=%s", storage)) + b.local = isLocal + return b +} + +func (b *TiKVBrRunCmd) S3endpoint(s3endpoint string) *TiKVBrRunCmd { + b.options = append(b.options, fmt.Sprintf("--s3.endpoint=%s", s3endpoint)) + return b +} + +func (b *TiKVBrRunCmd) LogFile(logFile string) *TiKVBrRunCmd { + b.options = append(b.options, fmt.Sprintf("--log-file=%s", logFile)) + return b +} + +func (b *TiKVBrRunCmd) DstApiVersion(dstApiVersion string) *TiKVBrRunCmd { + b.options = append(b.options, fmt.Sprintf("--dst-api-version=%s", dstApiVersion)) + return b +} + +// safeInterval is seconds. +func (b *TiKVBrRunCmd) SafeInterval(safeInterval int64) *TiKVBrRunCmd { + b.options = append(b.options, fmt.Sprintf("--safe-interval=%s", time.Duration(safeInterval)*time.Second)) + return b +} + +func (b *TiKVBrRunCmd) Checksum(check bool) *TiKVBrRunCmd { + checkStr := "false" + if check { + checkStr = "true" + } + b.options = append(b.options, fmt.Sprintf("--checksum=%s", checkStr)) + return b +} + +func (b *TiKVBrRunCmd) CheckReq(checkReq bool) *TiKVBrRunCmd { + b.options = append(b.options, fmt.Sprintf("--check-requirements=%t", checkReq)) + return b +} + +func (t *TiKVBrRunCmd) Command(command string) *TiKVBrRunCmd { + t.command = command + return t +} + +func (s *TiKVBrRunCmd) Build() string { + return fmt.Sprintf("%s %s", s.command, strings.Join(s.options[:], " ")) +} From b7a8ebb143315f46a87700813eb62a4e5ac7bb2a Mon Sep 17 00:00:00 2001 From: haojinming Date: Mon, 1 Aug 2022 15:56:52 +0800 Subject: [PATCH 2/7] fix gosec Signed-off-by: haojinming --- .github/config/br_rawkv.toml | 5 ++--- .github/workflows/ci-br.yml | 4 ++-- br/Makefile | 2 +- br/go.mod | 7 +++--- br/go.sum | 14 +++++++----- br/tests/rawkv/main.go | 42 ++++++++++++++++++++---------------- 6 files changed, 42 insertions(+), 32 deletions(-) diff --git a/.github/config/br_rawkv.toml b/.github/config/br_rawkv.toml index 5ee1bfe0..2c9874fd 100644 --- a/.github/config/br_rawkv.toml +++ b/.github/config/br_rawkv.toml @@ -7,12 +7,11 @@ pd-heartbeat-tick-interval = "2s" pd-store-heartbeat-tick-interval = "5s" split-region-check-tick-interval = "1s" -[storage] -enable-ttl = true - [rocksdb] max-open-files = 10000 [raftdb] max-open-files = 10000 +[storage] +enable-ttl = true \ No newline at end of file diff --git a/.github/workflows/ci-br.yml b/.github/workflows/ci-br.yml index aaa77d47..8cc69ada 100644 --- a/.github/workflows/ci-br.yml +++ b/.github/workflows/ci-br.yml @@ -76,8 +76,8 @@ jobs: - name: start tikv cluster run: | # start tikv - echo -e "[storage]\napi-version=${{ matrix.api_version }}\nenable-ttl=true" > br_tikv.toml - /home/runner/.tiup/bin/tiup playground ${{ matrix.tikv_version }} --mode tikv-slim --kv 1 --without-monitor --kv.config br_tikv.toml --pd.config /home/runner/work/migration/migration/.github/config/br_pd.toml &> raw.out 2>&1 & + echo -e "\napi-version = ${{ matrix.api_version }}\n" >> /home/runner/work/migration/migration/.github/config/br_rawkv.toml + /home/runner/.tiup/bin/tiup playground ${{ matrix.tikv_version }} --mode tikv-slim --kv 1 --without-monitor --kv.config /home/runner/work/migration/migration/.github/config/br_rawkv.toml --pd.config /home/runner/work/migration/migration/.github/config/br_pd.toml &> raw.out 2>&1 & # The first run of `tiup` has to download all components so it'll take longer. sleep 1m 30s # Parse PD address from `tiup` output diff --git a/br/Makefile b/br/Makefile index cd3ac6fc..883a219d 100644 --- a/br/Makefile +++ b/br/Makefile @@ -47,7 +47,7 @@ check/golangci-lint: tools/bin/golangci-lint GO111MODULE=on CGO_ENABLED=0 tools/bin/golangci-lint run -v $$($(DIRECTORIES)) --config ../.golangci.yml --timeout 5m check/gosec: - $(GO) install github.com/securego/gosec/v2/cmd/gosec@v2.11.0 + $(GO) install github.com/securego/gosec/v2/cmd/gosec@v2.12.0 gosec -fmt=junit-xml -out=results.xml -stdout -verbose=text -exclude=G103,G104,G204,G304,G307,G401,G404,G501,G505,G601 ./... test: tools/bin/gocov tools/bin/gocov-xml diff --git a/br/go.mod b/br/go.mod index e6a1ed6a..a0b93a54 100644 --- a/br/go.mod +++ b/br/go.mod @@ -16,21 +16,21 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.6.0 - github.com/google/btree v1.0.1 + github.com/google/btree v1.1.2 github.com/google/uuid v1.1.2 github.com/jarcoal/httpmock v1.1.0 github.com/opentracing/opentracing-go v1.2.0 github.com/pingcap/check v0.0.0-20211026125417-57bd13f7b5f0 github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c github.com/pingcap/failpoint v0.0.0-20210918120811-547c13e3eb00 - github.com/pingcap/kvproto v0.0.0-20220517085838-12e2f5a9d167 + github.com/pingcap/kvproto v0.0.0-20220705053936-aa9c2d20cd2a github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee github.com/pingcap/tidb v1.1.0-beta.0.20220222031143-5988d0b2f46e github.com/prometheus/client_golang v1.11.0 github.com/spf13/cobra v1.1.3 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 - github.com/tikv/client-go/v2 v2.0.1-0.20220518162527-de7ca289ac77 + github.com/tikv/client-go/v2 v2.0.1-0.20220721031657-e38d2b07de3f github.com/tikv/pd/client v0.0.0-20220307081149-841fa61e9710 go.uber.org/goleak v1.1.12 go.uber.org/multierr v1.7.0 @@ -81,6 +81,7 @@ require ( github.com/prometheus/procfs v0.6.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/stathat/consistent v1.0.0 // indirect github.com/twmb/murmur3 v1.1.3 // indirect go.etcd.io/etcd/api/v3 v3.5.2 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.2 // indirect diff --git a/br/go.sum b/br/go.sum index 7299fbac..70b4f687 100644 --- a/br/go.sum +++ b/br/go.sum @@ -290,8 +290,9 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -532,8 +533,8 @@ github.com/pingcap/kvproto v0.0.0-20191211054548-3c6b38ea5107/go.mod h1:WWLmULLO github.com/pingcap/kvproto v0.0.0-20220106070556-3fa8fa04f898/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/kvproto v0.0.0-20220215045702-d229fcc888c8/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/kvproto v0.0.0-20220302110454-c696585a961b/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20220517085838-12e2f5a9d167 h1:dsMpneacHyuVslSVndgUfJKrXFNG7VPdXip2ulG6glo= -github.com/pingcap/kvproto v0.0.0-20220517085838-12e2f5a9d167/go.mod h1:OYtxs0786qojVTmkVeufx93xe+jUgm56GUYRIKnmaGI= +github.com/pingcap/kvproto v0.0.0-20220705053936-aa9c2d20cd2a h1:nP2wmyw9JTRsk5rm+tZtfAso6c/1FvuaFNbXTaYz3FE= +github.com/pingcap/kvproto v0.0.0-20220705053936-aa9c2d20cd2a/go.mod h1:OYtxs0786qojVTmkVeufx93xe+jUgm56GUYRIKnmaGI= github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20200511115504-543df19646ad/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20210625125904-98ed8e2eb1c7/go.mod h1:8AanEdAHATuRurdGxZXBz0At+9avep+ub7U1AGYLIMM= @@ -624,6 +625,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/stathat/consistent v1.0.0 h1:ZFJ1QTRn8npNBKW065raSZ8xfOqhpb8vLOkfp4CcL/U= +github.com/stathat/consistent v1.0.0/go.mod h1:uajTPbgSygZBJ+V+0mY7meZ8i0XAcZs7AQ6V121XSxw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -636,8 +639,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tiancaiamao/appdash v0.0.0-20181126055449-889f96f722a2/go.mod h1:2PfKggNGDuadAa0LElHrByyrz4JPZ9fFx6Gs7nx7ZZU= github.com/tikv/client-go/v2 v2.0.0-rc.0.20220217140116-589cf79b2ab5/go.mod h1:gaHSp8rnxZ0w36qb6QPPNPh9P0Mu5vAEwCQcc0Brni4= -github.com/tikv/client-go/v2 v2.0.1-0.20220518162527-de7ca289ac77 h1:baRGhZtEp4wY3qh/0bscTCZ+97MVTZekBg5rOdgopQc= -github.com/tikv/client-go/v2 v2.0.1-0.20220518162527-de7ca289ac77/go.mod h1:VTlli8fRRpcpISj9I2IqroQmcAFfaTyBquiRhofOcDs= +github.com/tikv/client-go/v2 v2.0.1-0.20220721031657-e38d2b07de3f h1:fCAWVzUJYee1pDqYTBt5j2G1WuUfOL7A2mZoONoaHgs= +github.com/tikv/client-go/v2 v2.0.1-0.20220721031657-e38d2b07de3f/go.mod h1:UmDQEoeHXza8RSHBXVFERpxH54VBOf8yKZVphyel3l4= github.com/tikv/pd/client v0.0.0-20220216070739-26c668271201/go.mod h1:fEvI5fhAuJn1Fn87VJF8ByE9Vc16EzWGoePZB21/nL8= github.com/tikv/pd/client v0.0.0-20220216080339-1b8f82378ee7/go.mod h1:fEvI5fhAuJn1Fn87VJF8ByE9Vc16EzWGoePZB21/nL8= github.com/tikv/pd/client v0.0.0-20220307081149-841fa61e9710 h1:jxgmKOscXSjaFEKQGRyY5qOpK8hLqxs2irb/uDJMtwk= @@ -1231,3 +1234,4 @@ sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 h1:ucqkfpjg9WzSUubAO62csmucvxl4/JeW3F4I4909XkM= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= +stathat.com/c/consistent v1.0.0 h1:ezyc51EGcRPJUxfHGSgJjWzJdj3NiMU9pNfLNGiXV0c= diff --git a/br/tests/rawkv/main.go b/br/tests/rawkv/main.go index 74f01aa6..8d432e6c 100644 --- a/br/tests/rawkv/main.go +++ b/br/tests/rawkv/main.go @@ -13,7 +13,7 @@ import ( "time" units "github.com/docker/go-units" - "github.com/juju/errors" + "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/kvrpcpb" "github.com/pingcap/log" "github.com/tikv/client-go/v2/oracle" @@ -209,7 +209,7 @@ func CheckBackupTS(apiVersion kvrpcpb.APIVersion, tso uint64, backupOutput []byt } } -func runTestWithFailPoint(failpoint string) { +func runTestWithFailPoint(failpoint string) error { apiVersion := kvrpcpb.APIVersion_V1TTL if *apiVersionInt == 2 { apiVersion = kvrpcpb.APIVersion_V2 @@ -220,70 +220,72 @@ func runTestWithFailPoint(failpoint string) { tester, err := NewRawKVBRTester(ctx, *pdAddr, *br, *brStorage, apiVersion) if err != nil { - log.Panic("New Tester Error", zap.Error(err)) + return errors.Annotate(err, "New Tester Fail") } err = tester.InjectFailpoint(failpoint) if err != nil { - log.Panic("Inject failpoint Error", zap.Error(err)) + return errors.Annotatef(err, "Inject failpoint % s fail", failpoint) } if err := tester.ClearStorage(); err != nil { - log.Panic("ClearStorage fail", zap.Error(err)) + return errors.Annotate(err, "ClearStorage fail") } - prefix := []byte{'a'} - err = tester.PreloadData(ctx, 1000, prefix) + prefix := []byte("index") + keyCnt := uint(10000) + err = tester.PreloadData(ctx, keyCnt, prefix) if err != nil { - log.Panic("Preload data fail", zap.Error(err)) + return errors.Annotate(err, "Preload data fail") } oriChecksum, err := tester.Checksum(ctx) if err != nil { - log.Panic("Checksum fail", zap.Error(err)) + return errors.Annotate(err, "Preload checksum fail") } tso := uint64(0) if apiVersion == kvrpcpb.APIVersion_V2 { tso, err = tester.GetTso(ctx) if err != nil { - log.Panic("Get tso fail", zap.Error(err)) + return errors.Annotate(err, "Get tso fail") } } safeInterval := int64(120) // 2m backupOutput, err := tester.Backup(ctx, apiVersion, safeInterval) if err != nil { - log.Panic("Backup fail", zap.Error(err), zap.ByteString("output", backupOutput)) + return errors.Annotatef(err, "Backup fail:%s", backupOutput) } log.Info("backup finish:", zap.ByteString("output", backupOutput)) CheckBackupTS(apiVersion, tso, backupOutput, safeInterval) err = tester.CleanData(ctx, prefix) if err != nil { - log.Panic("Clean data fail", zap.Error(err)) + return errors.Annotate(err, "Clean data fail") } restoreOutput, err := tester.Restore(ctx) if err != nil { - log.Panic("Restore fail", zap.Error(err), zap.ByteString("output", restoreOutput)) + return errors.Annotatef(err, "Restore fail: %s", restoreOutput) } log.Info("Restore finish:", zap.ByteString("output", restoreOutput)) restoreChecksum, err := tester.Checksum(ctx) if err != nil { - log.Panic("Checksum fail", zap.Error(err)) + return errors.Annotate(err, "Checksum fail") } if oriChecksum != restoreChecksum { - log.Panic("Checksum mismatch", zap.Reflect("OriChecksum", oriChecksum), zap.Reflect("RestoreChecksum", restoreChecksum)) + return errors.Annotatef(err, "Checksum mismatch, src:%v, dst:%v", oriChecksum, restoreChecksum) } if apiVersion == kvrpcpb.APIVersion_V1TTL { if err := tester.ClearStorage(); err != nil { - log.Panic("ClearStorage fail", zap.Error(err)) + return errors.Annotate(err, "ClearStorage fail") } backupOutput, err := tester.Backup(ctx, kvrpcpb.APIVersion_V2, safeInterval) if err != nil { - log.Panic("Backup fail", zap.Error(err), zap.ByteString("output", backupOutput)) + return errors.Annotatef(err, "Backup fail:%s", backupOutput) } log.Info("backup conversion finish:", zap.ByteString("output", backupOutput)) } + return nil } func main() { @@ -292,6 +294,10 @@ func main() { "github.com/tikv/migration/br/pkg/backup/tikv-region-error=return(\"region error\")", } for _, failpoint := range failpoints { - runTestWithFailPoint(failpoint) + err := runTestWithFailPoint(failpoint) + if err != nil { + log.Error("run test with failpoint fails", zap.Error(err)) + os.Exit(1) + } } } From 4c8d12c98ed338fe5a6d03bdb186f7b60bbc8ed7 Mon Sep 17 00:00:00 2001 From: haojinming Date: Mon, 1 Aug 2022 16:47:21 +0800 Subject: [PATCH 3/7] revert run.py change Signed-off-by: haojinming --- br/tests/rawkv/main.go | 6 ++-- br/tests/rawkv/run.py | 79 +++++++++++++++++------------------------- 2 files changed, 34 insertions(+), 51 deletions(-) diff --git a/br/tests/rawkv/main.go b/br/tests/rawkv/main.go index 8d432e6c..33cc87d7 100644 --- a/br/tests/rawkv/main.go +++ b/br/tests/rawkv/main.go @@ -27,6 +27,7 @@ var ( maxMsgSize = int(128 * units.MiB) // pd.ScanRegion may return a large response maxBatchSize = uint(1024) // max batch size with BatchPut + keyCnt = flag.Uint("keycnt", 10000, "KeyCnt of testing") pdAddr = flag.String("pd", "127.0.0.1:2379", "Address of PD") apiVersionInt = flag.Uint("api-version", 1, "Api version of tikv-server") br = flag.String("br", "br", "The br binary to be tested.") @@ -126,7 +127,7 @@ func (t *RawKVBRTester) PreloadData(ctx context.Context, keyCnt uint, prefix []b } func (t *RawKVBRTester) CleanData(ctx context.Context, prefix []byte) error { - return t.rawkvClient.DeleteRange(ctx, prefix, append(prefix, 0)) + return t.rawkvClient.DeleteRange(ctx, prefix, append(prefix, []byte{0xFF, 0xFF, 0xFF, 0xFF}...)) } func (t *RawKVBRTester) Checksum(ctx context.Context) (rawkv.RawChecksum, error) { @@ -232,8 +233,7 @@ func runTestWithFailPoint(failpoint string) error { } prefix := []byte("index") - keyCnt := uint(10000) - err = tester.PreloadData(ctx, keyCnt, prefix) + err = tester.PreloadData(ctx, *keyCnt, prefix) if err != nil { return errors.Annotate(err, "Preload data fail") } diff --git a/br/tests/rawkv/run.py b/br/tests/rawkv/run.py index 2a30c476..dc9637b9 100755 --- a/br/tests/rawkv/run.py +++ b/br/tests/rawkv/run.py @@ -28,33 +28,32 @@ def __init__(self, global_args, failpoints=''): self.helper = global_args.helper self.br_storage = global_args.br_storage self.failpoints = failpoints - self.api_version = global_args.api_version - def test_dst_apiv1(self, test_restore): + def test_dst_apiv1(self): test_name = self.test_dst_apiv1.__name__ storage_dir = self.br_storage + "/" + test_name self._clean(storage_dir) - self._run_br_test("v1", storage_dir, test_restore) + self._run_br_test("v1", storage_dir) self._success_msg(test_name) - def test_dst_apiv1ttl(self, test_restore): + def test_dst_apiv1ttl(self): test_name = self.test_dst_apiv1ttl.__name__ storage_dir = self.br_storage + "/" + test_name self._clean(storage_dir) - self._run_br_test("v1ttl", storage_dir, test_restore) + self._run_br_test("v1ttl", storage_dir) self._success_msg(test_name) - def test_dst_apiv2(self, test_restore): + def test_dst_apiv2(self): test_name = self.test_dst_apiv2.__name__ storage_dir = self.br_storage + "/" + test_name self._clean(storage_dir) - self._run_br_test("v2", storage_dir, test_restore) + self._run_br_test("v2", storage_dir) self._success_msg(test_name) def _clean(self, storage_dir): @@ -68,7 +67,7 @@ def _success_msg(self, case_name): print(f"PASSED: {case_name}") - def _run_br_test(self, dst_api_version, storage_dir, test_restore): + def _run_br_test(self, dst_api_version, storage_dir): outer_start, outer_end = "31", "3130303030303030" inner_start, inner_end = "311111", "311122" @@ -78,41 +77,34 @@ def _run_br_test(self, dst_api_version, storage_dir, test_restore): # prepare and backup data self._randgen(outer_start, outer_end) - self._run_cmd(self.helper, "-pd", self.pd, "-mode", "put", "-api-version", self.api_version, + self._run_cmd(self.helper, "-pd", self.pd, "-mode", "put", "-put-data", "311121:31, 31112100:32, 311122:33, 31112200:34, 3111220000:35, 311123:36") - output = self._backup_range(outer_start, outer_end, dst_api_version, storage_dir) - print(output) - matched = re.search("BackupTS=.*", output) - if matched: - print("found BackupTS") - print(matched) - print(str(matched.group(0))[len("BackupTS="):]) - else: - print("Not found BackupTS") - + self._backup_range(outer_start, outer_end, dst_api_version, storage_dir) cs_outer_origin = self._get_checksum(outer_start, outer_end) cs_inner_origin = self._get_checksum(inner_start, inner_end) - if test_restore: - # clean and restore outer range - self._clean_range(outer_start, outer_end) - cs_outer_clean = self._get_checksum(outer_start, outer_end) - self._assert("clean range failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_clean, cs_outer_empty) - self._restore_range(outer_start, outer_end, dst_api_version, storage_dir) - cs_outer_restore = self._get_checksum(outer_start, outer_end) - self._assert("restore failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_restore, cs_outer_origin) + # clean and restore outer range + self._clean_range(outer_start, outer_end) + cs_outer_clean = self._get_checksum(outer_start, outer_end) + self._assert("clean range failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_clean, cs_outer_empty) + self._restore_range(outer_start, outer_end, dst_api_version, storage_dir) + cs_outer_restore = self._get_checksum(outer_start, outer_end) + self._assert("restore failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_restore, cs_outer_origin) - # clean and restore inner range - self._clean_range(outer_start, outer_end) - cs_outer_clean = self._get_checksum(outer_start, outer_end) - self._assert("clean range failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_clean, cs_outer_empty) + # clean and restore inner range + self._clean_range(outer_start, outer_end) + cs_outer_clean = self._get_checksum(outer_start, outer_end) + self._assert("clean range failed, checksum mismatch.\n actual: {}\n expect: {}", cs_outer_clean, cs_outer_empty) + #self._restore_range(inner_start, inner_end, dst_api_version, storage_dir) + #cs_inner_restore = self._get_checksum(inner_start, inner_end) + #self._assert("restore failed, checksum mismatch.\n actual: {}\n expect: {}", cs_inner_restore, cs_inner_origin) def _backup_range(self, start_key, end_key, dst_api_version, storage_dir): env = { 'GO_FAILPOINTS': self.failpoints, } - return self._run_cmd(self.br, "--pd", self.pd, "backup", "raw", "-s", storage_dir, + self._run_cmd(self.br, "--pd", self.pd, "backup", "raw", "-s", storage_dir, "--start", start_key, "--end", end_key, "--format", "hex", "--dst-api-version", dst_api_version, "--check-requirements=false", "-L", "debug", **env) @@ -127,21 +119,15 @@ def _restore_range(self, start_key, end_key, dst_api_version, storage_dir): def _randgen(self, start_key, end_key): - self._run_cmd(self.helper, "-pd", self.pd, "-mode", "rand-gen", - "-start-key", start_key, "-end-key", end_key, "-duration", "10", - "-api-version", self.api_version) + self._run_cmd(self.helper, "-pd", self.pd, "-mode", "rand-gen", "-start-key", start_key, "-end-key", end_key, "-duration", "10") def _clean_range(self, start_key, end_key): - self._run_cmd(self.helper, "-pd", self.pd, "-mode", "delete", - "-start-key", start_key, "-end-key", end_key, - "-api-version", self.api_version) + self._run_cmd(self.helper, "-pd", self.pd, "-mode", "delete", "-start-key", start_key, "-end-key", end_key) def _get_checksum(self, start_key, end_key): - output = self._run_cmd(self.helper, "-pd", self.pd, "-mode", "checksum", - "-start-key", start_key, "-end-key", end_key, - "-api-version", self.api_version) + output = self._run_cmd(self.helper, "-pd", self.pd, "-mode", "checksum", "-start-key", start_key, "-end-key", end_key) matched = re.search("Checksum result: .*", output) if matched: return str(matched.group(0))[len("Checksum result: "):] @@ -187,11 +173,10 @@ def main(): args = parse_args() for failpoint in [''] + FAILPOINTS: tester = rawkvTester(args, failpoints=failpoint) - if args.api_version == "1": - tester.test_dst_apiv1ttl(True) - tester.test_dst_apiv2(False) # test apiversion conversion - else: - tester.test_dst_apiv2(True) + # tester.test_dst_apiv1() // does not support v1ttl --> v1 + tester.test_dst_apiv1ttl() + # v1ttl -> v2 is not supported in current TiKV, enable this after V1/V1ttl -> V2 is enabled. + # tester.test_dst_apiv2() def parse_args(): @@ -204,8 +189,6 @@ def parse_args(): help = "The url to store SST files of backup/resotre. Default: 'local:///tmp/backup_restore_test'") parser.add_argument("--test-helper", dest = "helper", default = "./rawkv", help = "The test helper binary to be used to populate and clean data for the TiKV cluster. Default: './rawkv'") - parser.add_argument("--api-version", dest = "api_version", default = "1", required = True, - help = "The api version of tikv-server") args = parser.parse_args() return args From 401c4cc925f7a38abb2d5c798e1c6dc8b0a01a22 Mon Sep 17 00:00:00 2001 From: haojinming Date: Mon, 1 Aug 2022 17:06:11 +0800 Subject: [PATCH 4/7] display api version in ci task Signed-off-by: haojinming --- .github/workflows/ci-br.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-br.yml b/.github/workflows/ci-br.yml index 8cc69ada..6eb46b4b 100644 --- a/.github/workflows/ci-br.yml +++ b/.github/workflows/ci-br.yml @@ -60,7 +60,7 @@ jobs: cd br make test br-integration-test: - name: br-integration-test-${{ matrix.tikv_version }} + name: br-integration-test-${{ matrix.tikv_version }}-apiv${{ matrix.api_version }} runs-on: ubuntu-latest strategy: matrix: From 04b54f683df4a70e7884f32a211a9d1faec82306 Mon Sep 17 00:00:00 2001 From: haojinming Date: Mon, 1 Aug 2022 17:15:32 +0800 Subject: [PATCH 5/7] fix typo Signed-off-by: haojinming --- .github/workflows/ci-br.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-br.yml b/.github/workflows/ci-br.yml index 6eb46b4b..c11ecb78 100644 --- a/.github/workflows/ci-br.yml +++ b/.github/workflows/ci-br.yml @@ -82,7 +82,7 @@ jobs: sleep 1m 30s # Parse PD address from `tiup` output echo "PD_ADDR=$(cat raw.out | grep -oP '(?<=PD client endpoints: \[)[0-9\.:]+(?=\])')" >> $GITHUB_ENV - # Ouput the api version + # Output the api version echo "API_VERSION=${{ matrix.api_version }}" >> $GITHUB_ENV # Log the output echo "$(cat raw.out)" >&2 From 6d8d98e69e44c50a2295796d0eff0f92f2e220a0 Mon Sep 17 00:00:00 2001 From: haojinming Date: Tue, 2 Aug 2022 10:50:45 +0800 Subject: [PATCH 6/7] address review comments Signed-off-by: haojinming --- .github/workflows/ci-br.yml | 3 +++ br/tests/rawkv/main.go | 52 +++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci-br.yml b/.github/workflows/ci-br.yml index c11ecb78..5fee2b3e 100644 --- a/.github/workflows/ci-br.yml +++ b/.github/workflows/ci-br.yml @@ -90,6 +90,9 @@ jobs: run: | cd br make test/integration + - name: display backup log + run: | + cat /tmp/br.log* # comments low version CI as they fail without checksum & split region capability. # Plan to support low version with feature gate in the future. # br-integration-test-5X: diff --git a/br/tests/rawkv/main.go b/br/tests/rawkv/main.go index 33cc87d7..fe354578 100644 --- a/br/tests/rawkv/main.go +++ b/br/tests/rawkv/main.go @@ -31,7 +31,7 @@ var ( pdAddr = flag.String("pd", "127.0.0.1:2379", "Address of PD") apiVersionInt = flag.Uint("api-version", 1, "Api version of tikv-server") br = flag.String("br", "br", "The br binary to be tested.") - brStorage = flag.String("br-storage", "local:///tmp/backup_restore_test", "The url to store SST files of backup/resotre. Default: 'local:///tmp/backup_restore_test'") + brStorage = flag.String("br-storage", "local:///tmp/backup_restore_test", "The url to store SST files of backup/resotre.") ) type RawKVBRTester struct { @@ -127,7 +127,19 @@ func (t *RawKVBRTester) PreloadData(ctx context.Context, keyCnt uint, prefix []b } func (t *RawKVBRTester) CleanData(ctx context.Context, prefix []byte) error { - return t.rawkvClient.DeleteRange(ctx, prefix, append(prefix, []byte{0xFF, 0xFF, 0xFF, 0xFF}...)) + err := t.rawkvClient.DeleteRange(ctx, prefix, append(prefix, []byte{0xFF, 0xFF, 0xFF, 0xFF}...)) + if err != nil { + return errors.Annotate(err, "Delete range fails.") + } + // scan to verify delete range result. + keys, _, err := t.rawkvClient.Scan(ctx, []byte{}, []byte{}, 1024) + if err != nil { + return errors.Annotate(err, "Scan data fails.") + } + if len(keys) != 0 { + return errors.Errorf("Not empty after clean data, len:%d.", len(keys)) + } + return nil } func (t *RawKVBRTester) Checksum(ctx context.Context) (rawkv.RawChecksum, error) { @@ -210,7 +222,7 @@ func CheckBackupTS(apiVersion kvrpcpb.APIVersion, tso uint64, backupOutput []byt } } -func runTestWithFailPoint(failpoint string) error { +func runTestWithFailPoint(failpoint string) { apiVersion := kvrpcpb.APIVersion_V1TTL if *apiVersionInt == 2 { apiVersion = kvrpcpb.APIVersion_V2 @@ -221,71 +233,71 @@ func runTestWithFailPoint(failpoint string) error { tester, err := NewRawKVBRTester(ctx, *pdAddr, *br, *brStorage, apiVersion) if err != nil { - return errors.Annotate(err, "New Tester Fail") + log.Panic("New Tester Fail", zap.Error(err)) } err = tester.InjectFailpoint(failpoint) if err != nil { - return errors.Annotatef(err, "Inject failpoint % s fail", failpoint) + log.Panic("Inject failpoint fail", zap.Error(err), zap.String("failpoint", failpoint)) } if err := tester.ClearStorage(); err != nil { - return errors.Annotate(err, "ClearStorage fail") + log.Panic("ClearStorage fail", zap.Error(err)) } prefix := []byte("index") err = tester.PreloadData(ctx, *keyCnt, prefix) if err != nil { - return errors.Annotate(err, "Preload data fail") + log.Panic("Preload data fail", zap.Error(err)) } oriChecksum, err := tester.Checksum(ctx) if err != nil { - return errors.Annotate(err, "Preload checksum fail") + log.Panic("Preload checksum fail", zap.Error(err)) } tso := uint64(0) if apiVersion == kvrpcpb.APIVersion_V2 { tso, err = tester.GetTso(ctx) if err != nil { - return errors.Annotate(err, "Get tso fail") + log.Panic("Get tso fail", zap.Error(err)) } } safeInterval := int64(120) // 2m backupOutput, err := tester.Backup(ctx, apiVersion, safeInterval) if err != nil { - return errors.Annotatef(err, "Backup fail:%s", backupOutput) + log.Panic("Backup fail", zap.Error(err), zap.ByteString("output", backupOutput)) } log.Info("backup finish:", zap.ByteString("output", backupOutput)) CheckBackupTS(apiVersion, tso, backupOutput, safeInterval) err = tester.CleanData(ctx, prefix) if err != nil { - return errors.Annotate(err, "Clean data fail") + log.Panic("Clean data fail", zap.Error(err)) } restoreOutput, err := tester.Restore(ctx) if err != nil { - return errors.Annotatef(err, "Restore fail: %s", restoreOutput) + log.Panic("Restore fail", zap.Error(err), zap.ByteString("restore output", restoreOutput)) } log.Info("Restore finish:", zap.ByteString("output", restoreOutput)) restoreChecksum, err := tester.Checksum(ctx) if err != nil { - return errors.Annotate(err, "Checksum fail") + log.Panic("Checksum fail", zap.Error(err)) } if oriChecksum != restoreChecksum { - return errors.Annotatef(err, "Checksum mismatch, src:%v, dst:%v", oriChecksum, restoreChecksum) + log.Panic("Checksum mismatch", zap.Reflect("src", oriChecksum), zap.Reflect("dst", restoreChecksum)) } + log.Info("Checksum pass") if apiVersion == kvrpcpb.APIVersion_V1TTL { if err := tester.ClearStorage(); err != nil { - return errors.Annotate(err, "ClearStorage fail") + log.Panic("ClearStorage fail", zap.Error(err)) } backupOutput, err := tester.Backup(ctx, kvrpcpb.APIVersion_V2, safeInterval) if err != nil { - return errors.Annotatef(err, "Backup fail:%s", backupOutput) + log.Panic("Backup fail", zap.Error(err), zap.ByteString("backup output", backupOutput)) } log.Info("backup conversion finish:", zap.ByteString("output", backupOutput)) } - return nil } func main() { @@ -294,10 +306,6 @@ func main() { "github.com/tikv/migration/br/pkg/backup/tikv-region-error=return(\"region error\")", } for _, failpoint := range failpoints { - err := runTestWithFailPoint(failpoint) - if err != nil { - log.Error("run test with failpoint fails", zap.Error(err)) - os.Exit(1) - } + runTestWithFailPoint(failpoint) } } From 7c98c03e099be922be7716877ffa092503073ccd Mon Sep 17 00:00:00 2001 From: haojinming Date: Tue, 2 Aug 2022 12:58:42 +0800 Subject: [PATCH 7/7] fix apiv1 backup issue Signed-off-by: haojinming --- br/pkg/rtree/rtree.go | 10 +++++++++- br/pkg/rtree/rtree_test.go | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/br/pkg/rtree/rtree.go b/br/pkg/rtree/rtree.go index 22a281da..0b51905a 100644 --- a/br/pkg/rtree/rtree.go +++ b/br/pkg/rtree/rtree.go @@ -79,12 +79,14 @@ var _ btree.Item = &Range{} // All the ranges it stored do not overlap. type RangeTree struct { *btree.BTree + hasValidRange bool } // NewRangeTree returns an empty range tree. func NewRangeTree() RangeTree { return RangeTree{ - BTree: btree.New(32), + BTree: btree.New(32), + hasValidRange: false, } } @@ -140,6 +142,7 @@ func (rangeTree *RangeTree) Update(rg Range) { rangeTree.Delete(item) } rangeTree.ReplaceOrInsert(&rg) + rangeTree.hasValidRange = true } // Put forms a range and inserts it into tree. @@ -215,5 +218,10 @@ func (rangeTree *RangeTree) GetIncompleteRange( append(incomplete, Range{StartKey: start, EndKey: end}) } } + // is no valid range in Btree, and startKey/endKey are both empty, incomplete is empty too. + // This is not the result we need, append the whole input range. + if !rangeTree.hasValidRange && len(incomplete) == 0 { + incomplete = append(incomplete, Range{StartKey: startKey, EndKey: endKey}) + } return incomplete } diff --git a/br/pkg/rtree/rtree_test.go b/br/pkg/rtree/rtree_test.go index 645e8cc6..c651766a 100644 --- a/br/pkg/rtree/rtree_test.go +++ b/br/pkg/rtree/rtree_test.go @@ -17,6 +17,14 @@ func newRange(start, end []byte) *rtree.Range { } } +func TestEmptyRange(t *testing.T) { + rangeTree := rtree.NewRangeTree() + inCompelete := rangeTree.GetIncompleteRange([]byte(""), []byte("")) + require.Equal(t, len(inCompelete), 1) + require.Equal(t, inCompelete[0].StartKey, []byte("")) + require.Equal(t, inCompelete[0].EndKey, []byte("")) +} + func TestRangeTree(t *testing.T) { rangeTree := rtree.NewRangeTree() require.Nil(t, rangeTree.Get(newRange([]byte(""), []byte(""))))