Skip to content

Commit

Permalink
kv: add error code for package kv (#12866)
Browse files Browse the repository at this point in the history
  • Loading branch information
jackysp authored Nov 1, 2019
1 parent de3a672 commit ff6a4f7
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 36 deletions.
2 changes: 1 addition & 1 deletion ddl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ LOOP:
select {
case err := <-done:
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[kv:1062]Duplicate for key c3_index", Commentf("err:%v", err))
c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '' for key 'c3_index'", Commentf("err:%v", err))
break LOOP
case <-ticker.C:
if times >= 10 {
Expand Down
2 changes: 1 addition & 1 deletion ddl/rollingback.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func convertAddIdxJob2RollbackJob(t *meta.Meta, job *model.Job, tblInfo *model.T
}

if kv.ErrKeyExists.Equal(err) {
return ver, kv.ErrKeyExists.GenWithStack("Duplicate for key %s", indexInfo.Name.O)
return ver, kv.ErrKeyExists.GenWithStackByArgs("", indexInfo.Name.O)
}

return ver, errors.Trace(err)
Expand Down
6 changes: 3 additions & 3 deletions executor/batch_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package executor

import (
"context"
"strconv"

"github.com/pingcap/parser/model"
"github.com/pingcap/tidb/expression"
Expand Down Expand Up @@ -118,7 +119,7 @@ func getKeysNeedCheckOneRow(ctx sessionctx.Context, t table.Table, row []types.D
key: t.RecordKey(handle),
value: newRowValue,
},
dupErr: kv.ErrKeyExists.FastGen("Duplicate entry '%d' for key 'PRIMARY'", handle),
dupErr: kv.ErrKeyExists.FastGenByArgs(strconv.FormatInt(handle, 10), "PRIMARY"),
}
}

Expand Down Expand Up @@ -150,8 +151,7 @@ func getKeysNeedCheckOneRow(ctx sessionctx.Context, t table.Table, row []types.D
newKV: keyValue{
key: key,
},
dupErr: kv.ErrKeyExists.FastGen("Duplicate entry '%s' for key '%s'",
colValStr, v.Meta().Name),
dupErr: kv.ErrKeyExists.FastGenByArgs(colValStr, v.Meta().Name),
})
}
result = append(result, toBeCheckedRow{
Expand Down
44 changes: 18 additions & 26 deletions kv/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,30 @@ import (
"github.com/pingcap/parser/terror"
)

// KV error codes.
const (
codeClosed terror.ErrCode = 1
codeNotExist = 2
codeTxnRetryable = 6
codeCantSetNilValue = 7
codeInvalidTxn = 8
codeNotImplemented = 10
codeTxnTooLarge = 11
codeEntryTooLarge = 12
codeKeyExists = 1062
)

// TxnRetryableMark is used to uniform the commit error messages which could retry the transaction.
// *WARNING*: changing this string will affect the backward compatibility.
const TxnRetryableMark = "[try again later]"

var (
// ErrClosed is used when close an already closed txn.
ErrClosed = terror.ClassKV.New(codeClosed, "Error: Transaction already closed")
// ErrNotExist is used when try to get an entry with an unexist key from KV store.
ErrNotExist = terror.ClassKV.New(codeNotExist, "Error: key not exist")
ErrNotExist = terror.ClassKV.New(mysql.ErrNotExist, mysql.MySQLErrName[mysql.ErrNotExist])
// ErrTxnRetryable is used when KV store occurs retryable error which SQL layer can safely retry the transaction.
// When using TiKV as the storage node, the error is returned ONLY when lock not found (txnLockNotFound) in Commit,
// subject to change it in the future.
ErrTxnRetryable = terror.ClassKV.New(codeTxnRetryable, "Error: KV error safe to retry %s "+TxnRetryableMark)
ErrTxnRetryable = terror.ClassKV.New(mysql.ErrTxnRetryable,
mysql.MySQLErrName[mysql.ErrTxnRetryable]+TxnRetryableMark)
// ErrCannotSetNilValue is the error when sets an empty value.
ErrCannotSetNilValue = terror.ClassKV.New(codeCantSetNilValue, "can not set nil value")
ErrCannotSetNilValue = terror.ClassKV.New(mysql.ErrCannotSetNilValue, mysql.MySQLErrName[mysql.ErrCannotSetNilValue])
// ErrInvalidTxn is the error when commits or rollbacks in an invalid transaction.
ErrInvalidTxn = terror.ClassKV.New(codeInvalidTxn, "invalid transaction")
ErrInvalidTxn = terror.ClassKV.New(mysql.ErrInvalidTxn, mysql.MySQLErrName[mysql.ErrInvalidTxn])
// ErrTxnTooLarge is the error when transaction is too large, lock time reached the maximum value.
ErrTxnTooLarge = terror.ClassKV.New(codeTxnTooLarge, "transaction is too large")
ErrTxnTooLarge = terror.ClassKV.New(mysql.ErrTxnTooLarge, mysql.MySQLErrName[mysql.ErrTxnTooLarge])
// ErrEntryTooLarge is the error when a key value entry is too large.
ErrEntryTooLarge = terror.ClassKV.New(codeEntryTooLarge, "entry too large, the max entry size is %d, the size of data is %d")
ErrEntryTooLarge = terror.ClassKV.New(mysql.ErrEntryTooLarge, mysql.MySQLErrName[mysql.ErrEntryTooLarge])
// ErrKeyExists returns when key is already exist.
ErrKeyExists = terror.ClassKV.New(codeKeyExists, "key already exist")
ErrKeyExists = terror.ClassKV.New(mysql.ErrDupEntry, mysql.MySQLErrName[mysql.ErrDupEntry])
// ErrNotImplemented returns when a function is not implemented yet.
ErrNotImplemented = terror.ClassKV.New(codeNotImplemented, "not implemented")
ErrNotImplemented = terror.ClassKV.New(mysql.ErrNotImplemented, mysql.MySQLErrName[mysql.ErrNotImplemented])
// ErrWriteConflict is the error when the commit meets an write conflict error.
ErrWriteConflict = terror.ClassKV.New(mysql.ErrWriteConflict,
mysql.MySQLErrName[mysql.ErrWriteConflict]+" "+TxnRetryableMark)
Expand All @@ -66,11 +52,17 @@ var (

func init() {
kvMySQLErrCodes := map[terror.ErrCode]uint16{
codeKeyExists: mysql.ErrDupEntry,
codeEntryTooLarge: mysql.ErrTooBigRowsize,
codeTxnTooLarge: mysql.ErrTxnTooLarge,
mysql.ErrNotExist: mysql.ErrNotExist,
mysql.ErrDupEntry: mysql.ErrDupEntry,
mysql.ErrTooBigRowsize: mysql.ErrTooBigRowsize,
mysql.ErrTxnTooLarge: mysql.ErrTxnTooLarge,
mysql.ErrTxnRetryable: mysql.ErrTxnRetryable,
mysql.ErrWriteConflict: mysql.ErrWriteConflict,
mysql.ErrWriteConflictInTiDB: mysql.ErrWriteConflictInTiDB,
mysql.ErrCannotSetNilValue: mysql.ErrCannotSetNilValue,
mysql.ErrInvalidTxn: mysql.ErrInvalidTxn,
mysql.ErrEntryTooLarge: mysql.ErrEntryTooLarge,
mysql.ErrNotImplemented: mysql.ErrNotImplemented,
}
terror.ErrClassToMySQLCodes[terror.ClassKV] = kvMySQLErrCodes
}
Expand Down
42 changes: 42 additions & 0 deletions kv/error_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2019 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package kv

import (
. "github.com/pingcap/check"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/parser/terror"
)

type testErrorSuite struct{}

var _ = Suite(testErrorSuite{})

func (s testErrorSuite) TestError(c *C) {
kvErrs := []*terror.Error{
ErrNotExist,
ErrTxnRetryable,
ErrCannotSetNilValue,
ErrInvalidTxn,
ErrTxnTooLarge,
ErrEntryTooLarge,
ErrKeyExists,
ErrNotImplemented,
ErrWriteConflict,
ErrWriteConflictInTiDB,
}
for _, err := range kvErrs {
c.Assert(err.ToSQLError().Code != mysql.ErrUnknown, IsTrue)
}
}
2 changes: 1 addition & 1 deletion kv/memdb_buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (m *memDbBuffer) Set(k Key, v []byte) error {

m.db.Put(k, v)
if m.Size() > int(m.bufferSizeLimit) {
return ErrTxnTooLarge.GenWithStack("transaction too large, size:%d", m.Size())
return ErrTxnTooLarge.GenWithStackByArgs(m.Size())
}
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion kv/union_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (e *existErrInfo) GetValue() string {

// Err generates the error for existErrInfo
func (e *existErrInfo) Err() error {
return ErrKeyExists.FastGen("Duplicate entry '%s' for key '%s'", e.value, e.idxName)
return ErrKeyExists.FastGenByArgs(e.value, e.idxName)
}

// unionStore is an in-memory Store which contains a buffer for write and a
Expand Down
2 changes: 1 addition & 1 deletion store/tikv/2pc.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ func (c *twoPhaseCommitter) initKeysAndMutations() error {
}

if size > int(kv.TxnTotalSizeLimit) {
return kv.ErrTxnTooLarge
return kv.ErrTxnTooLarge.GenWithStackByArgs(size)
}
const logEntryCount = 10000
const logSize = 4 * 1024 * 1024 // 4MB
Expand Down
2 changes: 1 addition & 1 deletion store/tikv/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ func extractKeyErr(keyErr *pb.KeyError) error {
}
if keyErr.Retryable != "" {
notFoundDetail := prettyLockNotFoundKey(keyErr.GetRetryable())
return kv.ErrTxnRetryable.FastGenByArgs("tikv restarts txn: " + keyErr.GetRetryable() + " " + notFoundDetail)
return kv.ErrTxnRetryable.FastGenByArgs(keyErr.GetRetryable() + " " + notFoundDetail)
}
if keyErr.Abort != "" {
err := errors.Errorf("tikv aborts txn: %s", keyErr.GetAbort())
Expand Down
2 changes: 1 addition & 1 deletion table/tables/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ func (t *tableCommon) buildIndexForRow(ctx sessionctx.Context, rm kv.RetrieverMu
return err
}

return kv.ErrKeyExists.FastGen("Duplicate entry '%s' for key '%s'", entryKey, idx.Meta().Name)
return kv.ErrKeyExists.FastGenByArgs(entryKey, idx.Meta().Name)
}
return err
}
Expand Down

0 comments on commit ff6a4f7

Please sign in to comment.