From f73d0ff770876a2be6a664cf41d04fcbd7b7ce6b Mon Sep 17 00:00:00 2001 From: MyonKeminta Date: Thu, 18 Nov 2021 15:43:50 +0800 Subject: [PATCH 1/2] Pick unistore changes from #28313, ref #26833 --- go.mod | 2 + go.sum | 12 +- store/mockstore/unistore/tikv/errors.go | 15 +++ store/mockstore/unistore/tikv/mvcc.go | 42 ++++++- store/mockstore/unistore/tikv/mvcc_test.go | 129 ++++++++++++++++++++- store/mockstore/unistore/tikv/server.go | 10 ++ 6 files changed, 194 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index fc9980de52b83..30b33eaf057b8 100644 --- a/go.mod +++ b/go.mod @@ -99,3 +99,5 @@ require ( // FIXME the official repo has some bug makes br_gcs test failed. https://github.com/googleapis/google-cloud-go/pull/3509 // replace cloud.google.com/go/storage => github.com/3pointer/google-cloud-go/storage v1.6.1-0.20210108125931-b59bfa0720b2 + +replace github.com/pingcap/kvproto => github.com/MyonKeminta/kvproto v0.0.0-20211021102703-60266c23d5bd diff --git a/go.sum b/go.sum index 8ec3ae8ae9147..8fcdb241b8c38 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,8 @@ github.com/Jeffail/gabs/v2 v2.5.1/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/MyonKeminta/kvproto v0.0.0-20211021102703-60266c23d5bd h1:IwkCAyIHQJ2dh3y59k+8LCNZX0Tuf40KJMquqLPTts0= +github.com/MyonKeminta/kvproto v0.0.0-20211021102703-60266c23d5bd/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -252,7 +254,6 @@ github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/E github.com/goccy/go-graphviz v0.0.5/go.mod h1:wXVsXxmyMQU6TN3zGRttjNn3h+iCAS7xQFC6TlNvLhk= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v0.0.0-20180717141946-636bf0302bc9/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -277,7 +278,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v0.0.0-20180814211427-aa810b61a9c7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -552,12 +552,6 @@ github.com/pingcap/fn v0.0.0-20200306044125-d5540d389059 h1:Pe2LbxRmbTfAoKJ65bZL github.com/pingcap/fn v0.0.0-20200306044125-d5540d389059/go.mod h1:fMRU1BA1y+r89AxUoaAar4JjrhUkVDt0o0Np6V8XbDQ= 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-20191211054548-3c6b38ea5107/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= -github.com/pingcap/kvproto v0.0.0-20200411081810-b85805c9476c/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20210219064844-c1844a4775d6/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20210805052247-76981389e818/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20210806074406-317f69fb54b4 h1:4EUpHzPFHwleKkVALyMqQbQcNziPZvU+vhUT9Wzj93E= -github.com/pingcap/kvproto v0.0.0-20210806074406-317f69fb54b4/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= 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-20201112100606-8f1e84a3abc8/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= @@ -1062,7 +1056,6 @@ google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpC google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181004005441-af9cb2a35e7f/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1082,7 +1075,6 @@ google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171 h1:xes2Q2k+d/+YNXVw0FpZkIDJiaux4OVrRKXRAzH6A0U= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/grpc v0.0.0-20180607172857-7a6a684ca69e/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= diff --git a/store/mockstore/unistore/tikv/errors.go b/store/mockstore/unistore/tikv/errors.go index 6043f2fd7a753..59635eb073a1b 100644 --- a/store/mockstore/unistore/tikv/errors.go +++ b/store/mockstore/unistore/tikv/errors.go @@ -15,6 +15,7 @@ package tikv import ( + "encoding/hex" "fmt" deadlockpb "github.com/pingcap/kvproto/pkg/deadlock" @@ -132,3 +133,17 @@ type ErrTxnNotFound struct { func (e *ErrTxnNotFound) Error() string { return "txn not found" } + +// ErrAssertionFailed is returned if any assertion fails on a transaction request. +type ErrAssertionFailed struct { + StartTS uint64 + Key []byte + Assertion kvrpcpb.Assertion + ExistingStartTS uint64 + ExistingCommitTS uint64 +} + +func (e *ErrAssertionFailed) Error() string { + return fmt.Sprintf("AssertionFailed { StartTS: %v, Key: %v, Assertion: %v, ExistingStartTS: %v, ExistingCommitTS: %v }", + e.StartTS, hex.EncodeToString(e.Key), e.Assertion.String(), e.ExistingStartTS, e.ExistingCommitTS) +} diff --git a/store/mockstore/unistore/tikv/mvcc.go b/store/mockstore/unistore/tikv/mvcc.go index 47a59a3cb1f75..4623a747967a8 100644 --- a/store/mockstore/unistore/tikv/mvcc.go +++ b/store/mockstore/unistore/tikv/mvcc.go @@ -293,17 +293,23 @@ func (store *MVCCStore) PessimisticLock(reqCtx *requestCtx, req *kvrpcpb.Pessimi resp.Value = val resp.CommitTs = dbMeta.CommitTS() } - if req.ReturnValues { + if req.ReturnValues || req.CheckExistence { for _, item := range items { if item == nil { - resp.Values = append(resp.Values, nil) + if req.ReturnValues { + resp.Values = append(resp.Values, nil) + } + resp.NotFounds = append(resp.NotFounds, true) continue } val, err1 := item.ValueCopy(nil) if err1 != nil { return nil, err1 } - resp.Values = append(resp.Values, val) + if req.ReturnValues { + resp.Values = append(resp.Values, val) + } + resp.NotFounds = append(resp.NotFounds, len(val) == 0) } } return nil, err @@ -853,6 +859,36 @@ func (store *MVCCStore) buildPrewriteLock(reqCtx *requestCtx, m *kvrpcpb.Mutatio Value: m.Value, Secondaries: req.Secondaries, } + // Note that this is not fully consistent with TiKV. TiKV doesn't always get the value from Write CF. In + // AssertionLevel_Fast, TiKV skips checking assertion if Write CF is not read, in order not to harm the performance. + // However, unistore can always check it. It's better not to assume the store's behavior about assertion when the + // mode is set to AssertionLevel_Fast. + if req.AssertionLevel != kvrpcpb.AssertionLevel_Off { + if item == nil || item.IsEmpty() { + if m.Assertion == kvrpcpb.Assertion_Exist { + log.Error("ASSERTION FAIL!!! non-exist for must exist key", zap.Stringer("mutation", m)) + return nil, &ErrAssertionFailed{ + StartTS: req.StartVersion, + Key: m.Key, + Assertion: m.Assertion, + ExistingStartTS: 0, + ExistingCommitTS: 0, + } + } + } else { + if m.Assertion == kvrpcpb.Assertion_NotExist { + log.Error("ASSERTION FAIL!!! exist for must non-exist key", zap.Stringer("mutation", m)) + userMeta := mvcc.DBUserMeta(item.UserMeta()) + return nil, &ErrAssertionFailed{ + StartTS: req.StartVersion, + Key: m.Key, + Assertion: m.Assertion, + ExistingStartTS: userMeta.StartTS(), + ExistingCommitTS: userMeta.CommitTS(), + } + } + } + } var err error lock.Op = uint8(m.Op) if lock.Op == uint8(kvrpcpb.Op_Insert) { diff --git a/store/mockstore/unistore/tikv/mvcc_test.go b/store/mockstore/unistore/tikv/mvcc_test.go index 05e061ac55749..9913c7f32a739 100644 --- a/store/mockstore/unistore/tikv/mvcc_test.go +++ b/store/mockstore/unistore/tikv/mvcc_test.go @@ -25,6 +25,7 @@ import ( "github.com/pingcap/badger" "github.com/pingcap/badger/y" . "github.com/pingcap/check" + "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/kvrpcpb" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/store/mockstore/unistore/config" @@ -169,28 +170,50 @@ func PessimisticLock(pk []byte, key []byte, startTs uint64, lockTTL uint64, forU // PrewriteOptimistic raises optimistic prewrite requests on store func PrewriteOptimistic(pk []byte, key []byte, value []byte, startTs uint64, lockTTL uint64, minCommitTs uint64, useAsyncCommit bool, secondaries [][]byte, store *TestStore) error { + return PrewriteOptimisticWithAssertion(pk, key, value, startTs, lockTTL, minCommitTs, useAsyncCommit, secondaries, + kvrpcpb.Assertion_None, kvrpcpb.AssertionLevel_Off, store) +} + +// PrewriteOptimisticWithAssertion raises optimistic prewrite requests on store, with specified assertion config +func PrewriteOptimisticWithAssertion(pk []byte, key []byte, value []byte, startTs uint64, lockTTL uint64, + minCommitTs uint64, useAsyncCommit bool, secondaries [][]byte, assertion kvrpcpb.Assertion, + assertionLevel kvrpcpb.AssertionLevel, store *TestStore) error { + mutation := newMutation(kvrpcpb.Op_Put, key, value) + mutation.Assertion = assertion prewriteReq := &kvrpcpb.PrewriteRequest{ - Mutations: []*kvrpcpb.Mutation{newMutation(kvrpcpb.Op_Put, key, value)}, + Mutations: []*kvrpcpb.Mutation{mutation}, PrimaryLock: pk, StartVersion: startTs, LockTtl: lockTTL, MinCommitTs: minCommitTs, UseAsyncCommit: useAsyncCommit, Secondaries: secondaries, + AssertionLevel: assertionLevel, } return store.MvccStore.prewriteOptimistic(store.newReqCtx(), prewriteReq.Mutations, prewriteReq) } -// PrewritePessimistic raises pessmistic prewrite requests +// PrewritePessimistic raises pessimistic prewrite requests func PrewritePessimistic(pk []byte, key []byte, value []byte, startTs uint64, lockTTL uint64, isPessimisticLock []bool, forUpdateTs uint64, store *TestStore) error { + return PrewritePessimisticWithAssertion(pk, key, value, startTs, lockTTL, isPessimisticLock, forUpdateTs, + kvrpcpb.Assertion_None, kvrpcpb.AssertionLevel_Off, store) +} + +// PrewritePessimisticWithAssertion raises pessimistic prewrite requests, with specified assertion config +func PrewritePessimisticWithAssertion(pk []byte, key []byte, value []byte, startTs uint64, lockTTL uint64, + isPessimisticLock []bool, forUpdateTs uint64, assertion kvrpcpb.Assertion, assertionLevel kvrpcpb.AssertionLevel, + store *TestStore) error { + mutation := newMutation(kvrpcpb.Op_Put, key, value) + mutation.Assertion = assertion prewriteReq := &kvrpcpb.PrewriteRequest{ - Mutations: []*kvrpcpb.Mutation{newMutation(kvrpcpb.Op_Put, key, value)}, + Mutations: []*kvrpcpb.Mutation{mutation}, PrimaryLock: pk, StartVersion: startTs, LockTtl: lockTTL, IsPessimisticLock: isPessimisticLock, ForUpdateTs: forUpdateTs, + AssertionLevel: assertionLevel, } return store.MvccStore.prewritePessimistic(store.newReqCtx(), prewriteReq.Mutations, prewriteReq) } @@ -1634,3 +1657,103 @@ func (s *testMvccSuite) TestAsyncCommitPrewrite(c *C) { store.c.Assert(secLock.MinCommitTS, Greater, uint64(0)) store.c.Assert(bytes.Compare(secLock.Value, secVal2), Equals, 0) } + +func (s *testMvccSuite) TestAssertion(c *C) { + store, err := NewTestStore("TestAssertion", "TestAssertion", c) + c.Assert(err, IsNil) + defer CleanTestStore(store) + + // Prepare + MustPrewriteOptimistic([]byte("k1"), []byte("k1"), []byte("v1"), 1, 100, 0, store) + MustPrewriteOptimistic([]byte("k1"), []byte("k2"), []byte("v2"), 1, 100, 0, store) + MustPrewriteOptimistic([]byte("k1"), []byte("k3"), []byte("v3"), 1, 100, 0, store) + MustCommit([]byte("k1"), 1, 2, store) + MustCommit([]byte("k2"), 1, 2, store) + MustCommit([]byte("k3"), 1, 2, store) + + checkAssertionFailedError := func(err error, disable bool, startTs uint64, key []byte, assertion kvrpcpb.Assertion, existingStartTs uint64, existingCommitTs uint64) { + c.Logf("Check error: %+q", err) + if disable { + c.Assert(err, IsNil) + return + } + c.Assert(err, NotNil) + e, ok := errors.Cause(err).(*ErrAssertionFailed) + c.Assert(ok, IsTrue) + c.Assert(e.StartTS, Equals, startTs) + c.Assert(e.Key, DeepEquals, key) + c.Assert(e.Assertion, Equals, assertion) + c.Assert(e.ExistingStartTS, Equals, existingStartTs) + c.Assert(e.ExistingCommitTS, Equals, existingCommitTs) + } + + for _, disable := range []bool{false, true} { + level := kvrpcpb.AssertionLevel_Strict + if disable { + level = kvrpcpb.AssertionLevel_Off + } + // Test with optimistic transaction + err = PrewriteOptimisticWithAssertion([]byte("k1"), []byte("k1"), []byte("v1"), 10, 100, 0, false, nil, + kvrpcpb.Assertion_NotExist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k1"), kvrpcpb.Assertion_NotExist, 1, 2) + err = PrewriteOptimisticWithAssertion([]byte("k11"), []byte("k11"), []byte("v11"), 10, 100, 0, false, nil, + kvrpcpb.Assertion_Exist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k11"), kvrpcpb.Assertion_Exist, 0, 0) + + // Test with pessimistic transaction + MustAcquirePessimisticLock([]byte("k2"), []byte("k2"), 10, 10, store) + err = PrewritePessimisticWithAssertion([]byte("k2"), []byte("k2"), []byte("v2"), 10, 100, []bool{true}, 10, + kvrpcpb.Assertion_NotExist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k2"), kvrpcpb.Assertion_NotExist, 1, 2) + MustAcquirePessimisticLock([]byte("k22"), []byte("k22"), 10, 10, store) + err = PrewritePessimisticWithAssertion([]byte("k22"), []byte("k22"), []byte("v22"), 10, 100, []bool{true}, 10, + kvrpcpb.Assertion_Exist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k22"), kvrpcpb.Assertion_Exist, 0, 0) + + // Test with pessimistic transaction (non-pessimistic-lock) + err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k3"), []byte("v3"), 10, 100, []bool{false}, 10, + kvrpcpb.Assertion_NotExist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k3"), kvrpcpb.Assertion_NotExist, 1, 2) + err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k33"), []byte("v33"), 10, 100, []bool{false}, 10, + kvrpcpb.Assertion_Exist, level, store) + checkAssertionFailedError(err, disable, 10, []byte("k33"), kvrpcpb.Assertion_Exist, 0, 0) + } + + for _, k := range [][]byte{ + []byte("k1"), + []byte("k11"), + []byte("k2"), + []byte("k22"), + []byte("k3"), + []byte("k33"), + } { + MustRollbackKey(k, 10, store) + } + + // Test assertion passes + // Test with optimistic transaction + err = PrewriteOptimisticWithAssertion([]byte("k1"), []byte("k1"), []byte("v1"), 20, 100, 0, false, nil, + kvrpcpb.Assertion_Exist, kvrpcpb.AssertionLevel_Strict, store) + c.Assert(err, IsNil) + err = PrewriteOptimisticWithAssertion([]byte("k11"), []byte("k11"), []byte("v11"), 20, 100, 0, false, nil, + kvrpcpb.Assertion_NotExist, kvrpcpb.AssertionLevel_Strict, store) + c.Assert(err, IsNil) + + // Test with pessimistic transaction + MustAcquirePessimisticLock([]byte("k2"), []byte("k2"), 20, 10, store) + err = PrewritePessimisticWithAssertion([]byte("k2"), []byte("k2"), []byte("v2"), 20, 100, []bool{true}, 10, + kvrpcpb.Assertion_Exist, kvrpcpb.AssertionLevel_Strict, store) + c.Assert(err, IsNil) + MustAcquirePessimisticLock([]byte("k22"), []byte("k22"), 20, 10, store) + err = PrewritePessimisticWithAssertion([]byte("k22"), []byte("k22"), []byte("v22"), 20, 100, []bool{true}, 10, + kvrpcpb.Assertion_NotExist, kvrpcpb.AssertionLevel_Strict, store) + c.Assert(err, IsNil) + + // Test with pessimistic transaction (non-pessimistic-lock) + err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k3"), []byte("v3"), 20, 100, []bool{false}, 10, + kvrpcpb.Assertion_Exist, kvrpcpb.AssertionLevel_Strict, store) + c.Assert(err, IsNil) + err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k33"), []byte("v33"), 20, 100, []bool{false}, 10, + kvrpcpb.Assertion_NotExist, kvrpcpb.AssertionLevel_Strict, store) + c.Assert(err, IsNil) +} diff --git a/store/mockstore/unistore/tikv/server.go b/store/mockstore/unistore/tikv/server.go index 8038acac31922..c844f2cbf5d88 100644 --- a/store/mockstore/unistore/tikv/server.go +++ b/store/mockstore/unistore/tikv/server.go @@ -1041,6 +1041,16 @@ func convertToKeyError(err error) *kvrpcpb.KeyError { PrimaryKey: x.PrimaryKey, }, } + case *ErrAssertionFailed: + return &kvrpcpb.KeyError{ + AssertionFailed: &kvrpcpb.AssertionFailed{ + StartTs: x.StartTS, + Key: x.Key, + Assertion: x.Assertion, + ExistingStartTs: x.ExistingStartTS, + ExistingCommitTs: x.ExistingCommitTS, + }, + } default: return &kvrpcpb.KeyError{ Abort: err.Error(), From 7f06e98b6d41e3247e52ec7695d61a015606a793 Mon Sep 17 00:00:00 2001 From: MyonKeminta Date: Wed, 8 Dec 2021 16:50:25 +0800 Subject: [PATCH 2/2] fix build --- store/mockstore/unistore/tikv/mvcc_test.go | 44 +++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/store/mockstore/unistore/tikv/mvcc_test.go b/store/mockstore/unistore/tikv/mvcc_test.go index 2b4a1b3cdda62..cb55a5548860f 100644 --- a/store/mockstore/unistore/tikv/mvcc_test.go +++ b/store/mockstore/unistore/tikv/mvcc_test.go @@ -25,6 +25,7 @@ import ( "github.com/pingcap/badger" "github.com/pingcap/badger/y" + "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/kvrpcpb" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/store/mockstore/unistore/config" @@ -1672,10 +1673,11 @@ func TestAccessCommittedLocks(t *testing.T) { } } -func (s *testMvccSuite) TestAssertion(c *C) { - store, err := NewTestStore("TestAssertion", "TestAssertion", c) - c.Assert(err, IsNil) - defer CleanTestStore(store) +func TestAssertion(t *testing.T) { + t.Parallel() + + store, close := NewTestStore("TestAssertion", "TestAssertion", t) + defer close() // Prepare MustPrewriteOptimistic([]byte("k1"), []byte("k1"), []byte("v1"), 1, 100, 0, store) @@ -1686,19 +1688,19 @@ func (s *testMvccSuite) TestAssertion(c *C) { MustCommit([]byte("k3"), 1, 2, store) checkAssertionFailedError := func(err error, disable bool, startTs uint64, key []byte, assertion kvrpcpb.Assertion, existingStartTs uint64, existingCommitTs uint64) { - c.Logf("Check error: %+q", err) + t.Logf("Check error: %+q", err) if disable { - c.Assert(err, IsNil) + require.Nil(t, err) return } - c.Assert(err, NotNil) + require.NotNil(t, err) e, ok := errors.Cause(err).(*ErrAssertionFailed) - c.Assert(ok, IsTrue) - c.Assert(e.StartTS, Equals, startTs) - c.Assert(e.Key, DeepEquals, key) - c.Assert(e.Assertion, Equals, assertion) - c.Assert(e.ExistingStartTS, Equals, existingStartTs) - c.Assert(e.ExistingCommitTS, Equals, existingCommitTs) + require.True(t, ok) + require.Equal(t, startTs, e.StartTS) + require.Equal(t, key, e.Key) + require.Equal(t, assertion, e.Assertion) + require.Equal(t, existingStartTs, e.ExistingStartTS) + require.Equal(t, existingCommitTs, e.ExistingCommitTS) } for _, disable := range []bool{false, true} { @@ -1707,7 +1709,7 @@ func (s *testMvccSuite) TestAssertion(c *C) { level = kvrpcpb.AssertionLevel_Off } // Test with optimistic transaction - err = PrewriteOptimisticWithAssertion([]byte("k1"), []byte("k1"), []byte("v1"), 10, 100, 0, false, nil, + err := PrewriteOptimisticWithAssertion([]byte("k1"), []byte("k1"), []byte("v1"), 10, 100, 0, false, nil, kvrpcpb.Assertion_NotExist, level, store) checkAssertionFailedError(err, disable, 10, []byte("k1"), kvrpcpb.Assertion_NotExist, 1, 2) err = PrewriteOptimisticWithAssertion([]byte("k11"), []byte("k11"), []byte("v11"), 10, 100, 0, false, nil, @@ -1746,28 +1748,28 @@ func (s *testMvccSuite) TestAssertion(c *C) { // Test assertion passes // Test with optimistic transaction - err = PrewriteOptimisticWithAssertion([]byte("k1"), []byte("k1"), []byte("v1"), 20, 100, 0, false, nil, + err := PrewriteOptimisticWithAssertion([]byte("k1"), []byte("k1"), []byte("v1"), 20, 100, 0, false, nil, kvrpcpb.Assertion_Exist, kvrpcpb.AssertionLevel_Strict, store) - c.Assert(err, IsNil) + require.Nil(t, err) err = PrewriteOptimisticWithAssertion([]byte("k11"), []byte("k11"), []byte("v11"), 20, 100, 0, false, nil, kvrpcpb.Assertion_NotExist, kvrpcpb.AssertionLevel_Strict, store) - c.Assert(err, IsNil) + require.Nil(t, err) // Test with pessimistic transaction MustAcquirePessimisticLock([]byte("k2"), []byte("k2"), 20, 10, store) err = PrewritePessimisticWithAssertion([]byte("k2"), []byte("k2"), []byte("v2"), 20, 100, []bool{true}, 10, kvrpcpb.Assertion_Exist, kvrpcpb.AssertionLevel_Strict, store) - c.Assert(err, IsNil) + require.Nil(t, err) MustAcquirePessimisticLock([]byte("k22"), []byte("k22"), 20, 10, store) err = PrewritePessimisticWithAssertion([]byte("k22"), []byte("k22"), []byte("v22"), 20, 100, []bool{true}, 10, kvrpcpb.Assertion_NotExist, kvrpcpb.AssertionLevel_Strict, store) - c.Assert(err, IsNil) + require.Nil(t, err) // Test with pessimistic transaction (non-pessimistic-lock) err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k3"), []byte("v3"), 20, 100, []bool{false}, 10, kvrpcpb.Assertion_Exist, kvrpcpb.AssertionLevel_Strict, store) - c.Assert(err, IsNil) + require.Nil(t, err) err = PrewritePessimisticWithAssertion([]byte("pk"), []byte("k33"), []byte("v33"), 20, 100, []bool{false}, 10, kvrpcpb.Assertion_NotExist, kvrpcpb.AssertionLevel_Strict, store) - c.Assert(err, IsNil) + require.Nil(t, err) }