vitess-gh/go/vt/tabletserver/tablet_error.go

109 строки
2.2 KiB
Go
Исходник Обычный вид История

// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
2012-02-25 11:30:03 +04:00
package tabletserver
import (
"fmt"
log "github.com/golang/glog"
"github.com/youtube/vitess/go/mysql"
"github.com/youtube/vitess/go/tb"
2012-02-25 11:30:03 +04:00
)
const (
FAIL = iota
RETRY
FATAL
TX_POOL_FULL
2013-09-21 09:21:30 +04:00
NOT_IN_TX
2012-02-25 11:30:03 +04:00
)
type TabletError struct {
ErrorType int
Message string
SqlError int
}
// This is how go-mysql exports its error number
type hasNumber interface {
Number() int
}
func NewTabletError(errorType int, format string, args ...interface{}) *TabletError {
return &TabletError{errorType, fmt.Sprintf(format, args...), 0}
}
func NewTabletErrorSql(errorType int, err error) *TabletError {
2013-04-11 02:43:10 +04:00
te := NewTabletError(errorType, "%s", err)
2012-02-25 11:30:03 +04:00
if sqlErr, ok := err.(hasNumber); ok {
2013-04-11 02:43:10 +04:00
te.SqlError = sqlErr.Number()
2012-02-25 11:30:03 +04:00
}
2013-04-11 02:43:10 +04:00
return te
2012-02-25 11:30:03 +04:00
}
2013-04-11 02:43:10 +04:00
func (te *TabletError) Error() string {
2012-02-25 11:30:03 +04:00
format := "error: %s"
2013-04-11 02:43:10 +04:00
switch te.ErrorType {
2012-02-25 11:30:03 +04:00
case RETRY:
format = "retry: %s"
case FATAL:
format = "fatal: %s"
2013-08-21 01:00:00 +04:00
case TX_POOL_FULL:
format = "tx_pool_full: %s"
2013-09-21 09:21:30 +04:00
case NOT_IN_TX:
format = "not_in_tx: %s"
2012-02-25 11:30:03 +04:00
}
2013-04-11 02:43:10 +04:00
return fmt.Sprintf(format, te.Message)
2012-02-25 11:30:03 +04:00
}
2013-04-11 02:43:10 +04:00
func (te *TabletError) RecordStats() {
switch te.ErrorType {
2012-02-25 11:30:03 +04:00
case RETRY:
infoErrors.Add("Retry", 1)
2012-02-25 11:30:03 +04:00
case FATAL:
infoErrors.Add("Fatal", 1)
case TX_POOL_FULL:
errorStats.Add("TxPoolFull", 1)
2013-09-21 09:21:30 +04:00
case NOT_IN_TX:
errorStats.Add("NotInTx", 1)
2012-02-25 11:30:03 +04:00
default:
switch te.SqlError {
case mysql.DUP_ENTRY:
infoErrors.Add("DupKey", 1)
case mysql.LOCK_WAIT_TIMEOUT, mysql.LOCK_DEADLOCK:
errorStats.Add("Deadlock", 1)
default:
2012-02-25 11:30:03 +04:00
errorStats.Add("Fail", 1)
}
}
}
2012-11-20 04:24:03 +04:00
func handleError(err *error, logStats *sqlQueryStats) {
if logStats != nil {
logStats.Send()
}
2012-02-25 11:30:03 +04:00
if x := recover(); x != nil {
terr, ok := x.(*TabletError)
if !ok {
log.Errorf("Uncaught panic:\n%v\n%s", x, tb.Stack(4))
*err = NewTabletError(FAIL, "%v: uncaught panic", x)
internalErrors.Add("Panic", 1)
return
}
2012-02-25 11:30:03 +04:00
*err = terr
terr.RecordStats()
if terr.ErrorType == RETRY { // Retry errors are too spammy
return
}
log.Errorf("%s", terr.Message)
2012-02-25 11:30:03 +04:00
}
}
func logError() {
if x := recover(); x != nil {
log.Errorf("%s", x.(*TabletError).Message)
2012-02-25 11:30:03 +04:00
}
}