github.com/matrixorigin/matrixone@v1.2.0/pkg/logservice/errors.go (about) 1 // Copyright 2021 - 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package logservice 16 17 import ( 18 "context" 19 "fmt" 20 "net" 21 22 "github.com/cockroachdb/errors" 23 "github.com/lni/dragonboat/v4" 24 25 "github.com/matrixorigin/matrixone/pkg/common/moerr" 26 "github.com/matrixorigin/matrixone/pkg/logutil" 27 pb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 28 ) 29 30 type errorToCode struct { 31 err error 32 code uint16 33 reverse bool 34 } 35 36 var errorToCodeMappings = getErrorToCodeMapping() 37 38 // XXX This is strange code mapping. Esp, the those mapped to 39 // timeout -- per dragonbat, ErrTimeout is temp, but TimeoutTooSmall 40 // and InvalidDeadline are not temp. 41 func getErrorToCodeMapping() []errorToCode { 42 return []errorToCode{ 43 {dragonboat.ErrTimeout, moerr.ErrDragonboatTimeout, true}, 44 {dragonboat.ErrTimeoutTooSmall, moerr.ErrDragonboatTimeout, false}, 45 {dragonboat.ErrInvalidDeadline, moerr.ErrDragonboatTimeout, false}, 46 {dragonboat.ErrPayloadTooBig, moerr.ErrDragonboatInvalidPayloadSize, true}, 47 {dragonboat.ErrRejected, moerr.ErrDragonboatRejected, true}, 48 {dragonboat.ErrShardNotReady, moerr.ErrDragonboatShardNotReady, true}, 49 {dragonboat.ErrSystemBusy, moerr.ErrDragonboatShardNotReady, false}, 50 {dragonboat.ErrClosed, moerr.ErrDragonboatSystemClosed, true}, 51 {dragonboat.ErrInvalidRange, moerr.ErrDragonboatInvalidRange, true}, 52 {dragonboat.ErrShardNotFound, moerr.ErrDragonboatShardNotFound, true}, 53 } 54 } 55 56 func toErrorCode(err error) (uint32, string) { 57 if err == nil { 58 return uint32(moerr.Ok), "" 59 } 60 for _, rec := range errorToCodeMappings { 61 if errors.Is(err, rec.err) { 62 logutil.Error(fmt.Sprintf("error: %v, converted to code %d", err, rec.code)) 63 return uint32(rec.code), "" 64 } 65 } 66 67 merr, ok := err.(*moerr.Error) 68 if ok { 69 return uint32(merr.ErrorCode()), merr.Error() 70 } 71 return uint32(moerr.ErrDragonboatOtherSystemError), err.Error() 72 } 73 74 // toError reverse the response to dragonboat error. 75 func toError(ctx context.Context, resp pb.Response) error { 76 if resp.ErrorCode == uint32(moerr.Ok) { 77 return nil 78 } else if resp.ErrorCode == uint32(moerr.ErrDragonboatOtherSystemError) { 79 return moerr.NewDragonboatOtherSystemError(ctx, resp.ErrorMessage) 80 } 81 // Mapped errors, not that we return a dragonboat error in these cases. 82 for _, rec := range errorToCodeMappings { 83 if uint32(rec.code) == resp.ErrorCode && rec.reverse { 84 return rec.err 85 } 86 } 87 // Three of our own errors. 88 if resp.ErrorCode == uint32(moerr.ErrNoHAKeeper) { 89 return moerr.NewNoHAKeeper(ctx) 90 } else if resp.ErrorCode == uint32(moerr.ErrInvalidTruncateLsn) { 91 return moerr.NewInvalidTruncateLsn(ctx, 0, 0) 92 } else if resp.ErrorCode == uint32(moerr.ErrNotLeaseHolder) { 93 // holder id get lost? 94 return moerr.NewNotLeaseHolder(ctx, 0xDEADBEEF) 95 } else if resp.ErrorCode == uint32(moerr.ErrInternal) { 96 // internal error 97 return moerr.NewInternalError(ctx, resp.ErrorMessage) 98 } else { 99 // will logger.Panicf panic? 100 panic(moerr.NewInternalError(ctx, "unknown error code: %d", resp.ErrorCode)) 101 } 102 // will never reach here 103 } 104 105 func isTempError(err error) bool { 106 // non mo errors reached here, we handle first. 107 if dragonboat.IsTempError(err) { 108 return true 109 } 110 111 // XXX this error, while dragonboat says it is not temp 112 // we say yes. 113 if errors.Is(err, dragonboat.ErrShardNotFound) { 114 return true 115 } 116 117 // 118 if _, ok := err.(net.Error); ok { 119 return true 120 } 121 122 // How about those mapped from dragonboat errors? 123 // ErrDragonboatTimeout 124 // ErrDragonboatShardNotReady 125 // ErrDragonboatSystemClosed 126 // 127 // But, dragonboad ShardNotFound was not temp, but the code 128 // says we treat it as temp. 129 // 130 // Note that drgonboat errors are handled before moerr. 131 if moerr.IsMoErrCode(err, moerr.ErrNoHAKeeper) || 132 moerr.IsMoErrCode(err, moerr.ErrDragonboatShardNotFound) { 133 return true 134 } 135 136 return false 137 }