337 lines
9.8 KiB
Go
337 lines
9.8 KiB
Go
|
|
package srdb
|
||
|
|
|
||
|
|
import (
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
)
|
||
|
|
|
||
|
|
// ErrCode 错误码类型
|
||
|
|
type ErrCode int
|
||
|
|
|
||
|
|
// 错误码定义
|
||
|
|
const (
|
||
|
|
// 通用错误 (1000-1999)
|
||
|
|
ErrCodeNotFound ErrCode = 1000 // 数据未找到
|
||
|
|
ErrCodeClosed ErrCode = 1001 // 对象已关闭
|
||
|
|
ErrCodeInvalidData ErrCode = 1002 // 无效数据
|
||
|
|
ErrCodeCorrupted ErrCode = 1003 // 数据损坏
|
||
|
|
ErrCodeExists ErrCode = 1004 // 对象已存在
|
||
|
|
ErrCodeInvalidParam ErrCode = 1005 // 无效参数
|
||
|
|
|
||
|
|
// 数据库错误 (2000-2999)
|
||
|
|
ErrCodeDatabaseNotFound ErrCode = 2000 // 数据库不存在
|
||
|
|
ErrCodeDatabaseExists ErrCode = 2001 // 数据库已存在
|
||
|
|
ErrCodeDatabaseClosed ErrCode = 2002 // 数据库已关闭
|
||
|
|
|
||
|
|
// 表错误 (3000-3999)
|
||
|
|
ErrCodeTableNotFound ErrCode = 3000 // 表不存在
|
||
|
|
ErrCodeTableExists ErrCode = 3001 // 表已存在
|
||
|
|
ErrCodeTableClosed ErrCode = 3002 // 表已关闭
|
||
|
|
|
||
|
|
// Schema 错误 (4000-4999)
|
||
|
|
ErrCodeSchemaNotFound ErrCode = 4000 // Schema 不存在
|
||
|
|
ErrCodeSchemaInvalid ErrCode = 4001 // Schema 无效
|
||
|
|
ErrCodeSchemaMismatch ErrCode = 4002 // Schema 不匹配
|
||
|
|
ErrCodeSchemaValidationFailed ErrCode = 4003 // Schema 验证失败
|
||
|
|
ErrCodeSchemaChecksumMismatch ErrCode = 4004 // Schema 校验和不匹配
|
||
|
|
|
||
|
|
// 字段错误 (5000-5999)
|
||
|
|
ErrCodeFieldNotFound ErrCode = 5000 // 字段不存在
|
||
|
|
ErrCodeFieldTypeMismatch ErrCode = 5001 // 字段类型不匹配
|
||
|
|
ErrCodeFieldRequired ErrCode = 5002 // 必填字段缺失
|
||
|
|
|
||
|
|
// 索引错误 (6000-6999)
|
||
|
|
ErrCodeIndexNotFound ErrCode = 6000 // 索引不存在
|
||
|
|
ErrCodeIndexExists ErrCode = 6001 // 索引已存在
|
||
|
|
ErrCodeIndexNotReady ErrCode = 6002 // 索引未就绪
|
||
|
|
ErrCodeIndexCorrupted ErrCode = 6003 // 索引损坏
|
||
|
|
|
||
|
|
// 文件格式错误 (7000-7999)
|
||
|
|
ErrCodeInvalidFormat ErrCode = 7000 // 无效的文件格式
|
||
|
|
ErrCodeUnsupportedVersion ErrCode = 7001 // 不支持的版本
|
||
|
|
ErrCodeInvalidMagicNumber ErrCode = 7002 // 无效的魔数
|
||
|
|
ErrCodeChecksumMismatch ErrCode = 7003 // 校验和不匹配
|
||
|
|
|
||
|
|
// WAL 错误 (8000-8999)
|
||
|
|
ErrCodeWALCorrupted ErrCode = 8000 // WAL 文件损坏
|
||
|
|
ErrCodeWALClosed ErrCode = 8001 // WAL 已关闭
|
||
|
|
|
||
|
|
// SSTable 错误 (9000-9999)
|
||
|
|
ErrCodeSSTableNotFound ErrCode = 9000 // SSTable 文件不存在
|
||
|
|
ErrCodeSSTableCorrupted ErrCode = 9001 // SSTable 文件损坏
|
||
|
|
|
||
|
|
// Compaction 错误 (10000-10999)
|
||
|
|
ErrCodeCompactionInProgress ErrCode = 10000 // Compaction 正在进行
|
||
|
|
ErrCodeNoCompactionNeeded ErrCode = 10001 // 不需要 Compaction
|
||
|
|
|
||
|
|
// 编解码错误 (11000-11999)
|
||
|
|
ErrCodeEncodeFailed ErrCode = 11000 // 编码失败
|
||
|
|
ErrCodeDecodeFailed ErrCode = 11001 // 解码失败
|
||
|
|
)
|
||
|
|
|
||
|
|
// 错误码消息映射
|
||
|
|
var errCodeMessages = map[ErrCode]string{
|
||
|
|
// 通用错误
|
||
|
|
ErrCodeNotFound: "not found",
|
||
|
|
ErrCodeClosed: "already closed",
|
||
|
|
ErrCodeInvalidData: "invalid data",
|
||
|
|
ErrCodeCorrupted: "data corrupted",
|
||
|
|
ErrCodeExists: "already exists",
|
||
|
|
ErrCodeInvalidParam: "invalid parameter",
|
||
|
|
|
||
|
|
// 数据库错误
|
||
|
|
ErrCodeDatabaseNotFound: "database not found",
|
||
|
|
ErrCodeDatabaseExists: "database already exists",
|
||
|
|
ErrCodeDatabaseClosed: "database closed",
|
||
|
|
|
||
|
|
// 表错误
|
||
|
|
ErrCodeTableNotFound: "table not found",
|
||
|
|
ErrCodeTableExists: "table already exists",
|
||
|
|
ErrCodeTableClosed: "table closed",
|
||
|
|
|
||
|
|
// Schema 错误
|
||
|
|
ErrCodeSchemaNotFound: "schema not found",
|
||
|
|
ErrCodeSchemaInvalid: "schema invalid",
|
||
|
|
ErrCodeSchemaMismatch: "schema mismatch",
|
||
|
|
ErrCodeSchemaValidationFailed: "schema validation failed",
|
||
|
|
ErrCodeSchemaChecksumMismatch: "schema checksum mismatch",
|
||
|
|
|
||
|
|
// 字段错误
|
||
|
|
ErrCodeFieldNotFound: "field not found",
|
||
|
|
ErrCodeFieldTypeMismatch: "field type mismatch",
|
||
|
|
ErrCodeFieldRequired: "required field missing",
|
||
|
|
|
||
|
|
// 索引错误
|
||
|
|
ErrCodeIndexNotFound: "index not found",
|
||
|
|
ErrCodeIndexExists: "index already exists",
|
||
|
|
ErrCodeIndexNotReady: "index not ready",
|
||
|
|
ErrCodeIndexCorrupted: "index corrupted",
|
||
|
|
|
||
|
|
// 文件格式错误
|
||
|
|
ErrCodeInvalidFormat: "invalid file format",
|
||
|
|
ErrCodeUnsupportedVersion: "unsupported version",
|
||
|
|
ErrCodeInvalidMagicNumber: "invalid magic number",
|
||
|
|
ErrCodeChecksumMismatch: "checksum mismatch",
|
||
|
|
|
||
|
|
// WAL 错误
|
||
|
|
ErrCodeWALCorrupted: "wal corrupted",
|
||
|
|
ErrCodeWALClosed: "wal closed",
|
||
|
|
|
||
|
|
// SSTable 错误
|
||
|
|
ErrCodeSSTableNotFound: "sstable not found",
|
||
|
|
ErrCodeSSTableCorrupted: "sstable corrupted",
|
||
|
|
|
||
|
|
// Compaction 错误
|
||
|
|
ErrCodeCompactionInProgress: "compaction in progress",
|
||
|
|
ErrCodeNoCompactionNeeded: "no compaction needed",
|
||
|
|
|
||
|
|
// 编解码错误
|
||
|
|
ErrCodeEncodeFailed: "encode failed",
|
||
|
|
ErrCodeDecodeFailed: "decode failed",
|
||
|
|
}
|
||
|
|
|
||
|
|
// Error 错误类型
|
||
|
|
type Error struct {
|
||
|
|
Code ErrCode // 错误码
|
||
|
|
Message string // 错误消息
|
||
|
|
Cause error // 原始错误
|
||
|
|
}
|
||
|
|
|
||
|
|
// Error 实现 error 接口
|
||
|
|
func (e *Error) Error() string {
|
||
|
|
if e.Cause != nil {
|
||
|
|
return fmt.Sprintf("[%d] %s: %v", e.Code, e.Message, e.Cause)
|
||
|
|
}
|
||
|
|
return fmt.Sprintf("[%d] %s", e.Code, e.Message)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Unwrap 支持 errors.Is 和 errors.As
|
||
|
|
func (e *Error) Unwrap() error {
|
||
|
|
return e.Cause
|
||
|
|
}
|
||
|
|
|
||
|
|
// Is 判断错误码是否相同
|
||
|
|
func (e *Error) Is(target error) bool {
|
||
|
|
t, ok := target.(*Error)
|
||
|
|
if !ok {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
return e.Code == t.Code
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewError 创建新错误
|
||
|
|
func NewError(code ErrCode, cause error) *Error {
|
||
|
|
msg, ok := errCodeMessages[code]
|
||
|
|
if !ok {
|
||
|
|
msg = "unknown error"
|
||
|
|
}
|
||
|
|
return &Error{
|
||
|
|
Code: code,
|
||
|
|
Message: msg,
|
||
|
|
Cause: cause,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewErrorf 创建带格式化消息的错误
|
||
|
|
// 注意:如果 args 中最后一个参数是 error 类型,它会被设置为 Cause
|
||
|
|
func NewErrorf(code ErrCode, format string, args ...any) *Error {
|
||
|
|
var cause error
|
||
|
|
|
||
|
|
// 检查最后一个参数是否为 error
|
||
|
|
if len(args) > 0 {
|
||
|
|
if err, ok := args[len(args)-1].(error); ok {
|
||
|
|
cause = err
|
||
|
|
// 从 args 中移除最后一个 error 参数
|
||
|
|
args = args[:len(args)-1]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return &Error{
|
||
|
|
Code: code,
|
||
|
|
Message: fmt.Sprintf(format, args...),
|
||
|
|
Cause: cause,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 预定义的常用错误(向后兼容)
|
||
|
|
var (
|
||
|
|
// ErrNotFound 数据未找到
|
||
|
|
ErrNotFound = NewError(ErrCodeNotFound, nil)
|
||
|
|
|
||
|
|
// ErrClosed 对象已关闭
|
||
|
|
ErrClosed = NewError(ErrCodeClosed, nil)
|
||
|
|
|
||
|
|
// ErrInvalidData 无效数据
|
||
|
|
ErrInvalidData = NewError(ErrCodeInvalidData, nil)
|
||
|
|
|
||
|
|
// ErrCorrupted 数据损坏
|
||
|
|
ErrCorrupted = NewError(ErrCodeCorrupted, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// 数据库错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrDatabaseNotFound = NewError(ErrCodeDatabaseNotFound, nil)
|
||
|
|
ErrDatabaseExists = NewError(ErrCodeDatabaseExists, nil)
|
||
|
|
ErrDatabaseClosed = NewError(ErrCodeDatabaseClosed, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// 表错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrTableNotFound = NewError(ErrCodeTableNotFound, nil)
|
||
|
|
ErrTableExists = NewError(ErrCodeTableExists, nil)
|
||
|
|
ErrTableClosed = NewError(ErrCodeTableClosed, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// Schema 错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrSchemaNotFound = NewError(ErrCodeSchemaNotFound, nil)
|
||
|
|
ErrSchemaInvalid = NewError(ErrCodeSchemaInvalid, nil)
|
||
|
|
ErrSchemaMismatch = NewError(ErrCodeSchemaMismatch, nil)
|
||
|
|
ErrSchemaValidationFailed = NewError(ErrCodeSchemaValidationFailed, nil)
|
||
|
|
ErrSchemaChecksumMismatch = NewError(ErrCodeSchemaChecksumMismatch, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// 字段错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrFieldNotFound = NewError(ErrCodeFieldNotFound, nil)
|
||
|
|
ErrFieldTypeMismatch = NewError(ErrCodeFieldTypeMismatch, nil)
|
||
|
|
ErrFieldRequired = NewError(ErrCodeFieldRequired, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// 索引错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrIndexNotFound = NewError(ErrCodeIndexNotFound, nil)
|
||
|
|
ErrIndexExists = NewError(ErrCodeIndexExists, nil)
|
||
|
|
ErrIndexNotReady = NewError(ErrCodeIndexNotReady, nil)
|
||
|
|
ErrIndexCorrupted = NewError(ErrCodeIndexCorrupted, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// 文件格式错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrInvalidFormat = NewError(ErrCodeInvalidFormat, nil)
|
||
|
|
ErrUnsupportedVersion = NewError(ErrCodeUnsupportedVersion, nil)
|
||
|
|
ErrInvalidMagicNumber = NewError(ErrCodeInvalidMagicNumber, nil)
|
||
|
|
ErrChecksumMismatch = NewError(ErrCodeChecksumMismatch, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// WAL 错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrWALCorrupted = NewError(ErrCodeWALCorrupted, nil)
|
||
|
|
ErrWALClosed = NewError(ErrCodeWALClosed, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// SSTable 错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrSSTableNotFound = NewError(ErrCodeSSTableNotFound, nil)
|
||
|
|
ErrSSTableCorrupted = NewError(ErrCodeSSTableCorrupted, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// Compaction 错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrCompactionInProgress = NewError(ErrCodeCompactionInProgress, nil)
|
||
|
|
ErrNoCompactionNeeded = NewError(ErrCodeNoCompactionNeeded, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// 编解码错误(向后兼容)
|
||
|
|
var (
|
||
|
|
ErrEncodeFailed = NewError(ErrCodeEncodeFailed, nil)
|
||
|
|
ErrDecodeFailed = NewError(ErrCodeDecodeFailed, nil)
|
||
|
|
)
|
||
|
|
|
||
|
|
// 辅助函数
|
||
|
|
|
||
|
|
// GetErrorCode 获取错误码
|
||
|
|
func GetErrorCode(err error) ErrCode {
|
||
|
|
var e *Error
|
||
|
|
if errors.As(err, &e) {
|
||
|
|
return e.Code
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsError 判断错误是否匹配指定的错误码
|
||
|
|
func IsError(err error, code ErrCode) bool {
|
||
|
|
return GetErrorCode(err) == code
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsNotFound 判断是否是 NotFound 错误
|
||
|
|
func IsNotFound(err error) bool {
|
||
|
|
code := GetErrorCode(err)
|
||
|
|
return code == ErrCodeNotFound ||
|
||
|
|
code == ErrCodeTableNotFound ||
|
||
|
|
code == ErrCodeDatabaseNotFound ||
|
||
|
|
code == ErrCodeIndexNotFound ||
|
||
|
|
code == ErrCodeFieldNotFound ||
|
||
|
|
code == ErrCodeSchemaNotFound ||
|
||
|
|
code == ErrCodeSSTableNotFound
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsCorrupted 判断是否是数据损坏错误
|
||
|
|
func IsCorrupted(err error) bool {
|
||
|
|
code := GetErrorCode(err)
|
||
|
|
return code == ErrCodeCorrupted ||
|
||
|
|
code == ErrCodeWALCorrupted ||
|
||
|
|
code == ErrCodeSSTableCorrupted ||
|
||
|
|
code == ErrCodeIndexCorrupted ||
|
||
|
|
code == ErrCodeChecksumMismatch ||
|
||
|
|
code == ErrCodeSchemaChecksumMismatch
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsClosed 判断是否是已关闭错误
|
||
|
|
func IsClosed(err error) bool {
|
||
|
|
code := GetErrorCode(err)
|
||
|
|
return code == ErrCodeClosed ||
|
||
|
|
code == ErrCodeDatabaseClosed ||
|
||
|
|
code == ErrCodeTableClosed ||
|
||
|
|
code == ErrCodeWALClosed
|
||
|
|
}
|
||
|
|
|
||
|
|
// WrapError 包装错误并添加上下文
|
||
|
|
func WrapError(err error, format string, args ...any) error {
|
||
|
|
if err == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
msg := fmt.Sprintf(format, args...)
|
||
|
|
return fmt.Errorf("%s: %w", msg, err)
|
||
|
|
}
|