| @@ -6,6 +6,10 @@ require ( | |||||
| github.com/BurntSushi/toml v1.1.0 // indirect | github.com/BurntSushi/toml v1.1.0 // indirect | ||||
| github.com/apache/dubbo-getty v1.4.8 | github.com/apache/dubbo-getty v1.4.8 | ||||
| github.com/dubbogo/gost v1.11.23 | github.com/dubbogo/gost v1.11.23 | ||||
| github.com/dubbogo/tools v1.0.9 // indirect | |||||
| github.com/fagongzi/goetty v1.3.1 | |||||
| github.com/fagongzi/log v0.0.0-20170831135209-9a647df25e0e | |||||
| github.com/fagongzi/util v0.0.0-20181102105153-fd38e0f42a4f | |||||
| github.com/golang/snappy v0.0.4 // indirect | github.com/golang/snappy v0.0.4 // indirect | ||||
| github.com/natefinch/lumberjack v2.0.0+incompatible | github.com/natefinch/lumberjack v2.0.0+incompatible | ||||
| github.com/pkg/errors v0.9.1 | github.com/pkg/errors v0.9.1 | ||||
| @@ -1,7 +1,16 @@ | |||||
| package error | package error | ||||
| import ( | |||||
| "github.com/pkg/errors" | |||||
| ) | |||||
| type ErrorCode int32 | type ErrorCode int32 | ||||
| const ( | const ( | ||||
| ErrorCode_IllegalState ErrorCode = 40001 | ErrorCode_IllegalState ErrorCode = 40001 | ||||
| ) | ) | ||||
| var ( | |||||
| Error_TooManySessions = errors.New("too many seeessions") | |||||
| Error_HeartBeatTimeOut = errors.New("heart beat time out") | |||||
| ) | |||||
| @@ -34,6 +34,7 @@ func GetDefaultGettyConfig() GettyConfig { | |||||
| TCPReadTimeout: time.Second, | TCPReadTimeout: time.Second, | ||||
| TCPWriteTimeout: 5 * time.Second, | TCPWriteTimeout: 5 * time.Second, | ||||
| WaitTimeout: time.Second, | WaitTimeout: time.Second, | ||||
| CronPeriod: time.Second, | |||||
| MaxMsgLen: 4096, | MaxMsgLen: 4096, | ||||
| SessionName: "rpc_client", | SessionName: "rpc_client", | ||||
| }, | }, | ||||
| @@ -46,6 +47,7 @@ type GettySessionParam struct { | |||||
| TCPNoDelay bool `default:"true" yaml:"tcp_no_delay" json:"tcp_no_delay,omitempty"` | TCPNoDelay bool `default:"true" yaml:"tcp_no_delay" json:"tcp_no_delay,omitempty"` | ||||
| TCPKeepAlive bool `default:"true" yaml:"tcp_keep_alive" json:"tcp_keep_alive,omitempty"` | TCPKeepAlive bool `default:"true" yaml:"tcp_keep_alive" json:"tcp_keep_alive,omitempty"` | ||||
| KeepAlivePeriod time.Duration `default:"180s" yaml:"keep_alive_period" json:"keep_alive_period,omitempty"` | KeepAlivePeriod time.Duration `default:"180s" yaml:"keep_alive_period" json:"keep_alive_period,omitempty"` | ||||
| CronPeriod time.Duration `default:"1s" yaml:"keep_alive_period" json:"keep_alive_period,omitempty"` | |||||
| TCPRBufSize int `default:"262144" yaml:"tcp_r_buf_size" json:"tcp_r_buf_size,omitempty"` | TCPRBufSize int `default:"262144" yaml:"tcp_r_buf_size" json:"tcp_r_buf_size,omitempty"` | ||||
| TCPWBufSize int `default:"65536" yaml:"tcp_w_buf_size" json:"tcp_w_buf_size,omitempty"` | TCPWBufSize int `default:"65536" yaml:"tcp_w_buf_size" json:"tcp_w_buf_size,omitempty"` | ||||
| TCPReadTimeout time.Duration `default:"1s" yaml:"tcp_read_timeout" json:"tcp_read_timeout,omitempty"` | TCPReadTimeout time.Duration `default:"1s" yaml:"tcp_read_timeout" json:"tcp_read_timeout,omitempty"` | ||||
| @@ -0,0 +1,68 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| ) | |||||
| import ( | |||||
| model2 "github.com/seata/seata-go/pkg/protocol/branch" | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &BranchRegisterRequestCodec{}) | |||||
| } | |||||
| type BranchRegisterRequestCodec struct { | |||||
| } | |||||
| func (g *BranchRegisterRequestCodec) Decode(in []byte) interface{} { | |||||
| buf := goetty.NewByteBuf(len(in)) | |||||
| buf.Write(in) | |||||
| msg := message.BranchRegisterRequest{} | |||||
| length := ReadUInt16(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length) | |||||
| msg.Xid = string(Read(buf, bytes)) | |||||
| } | |||||
| msg.BranchType = model2.BranchType(ReadByte(buf)) | |||||
| length = ReadUInt16(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length) | |||||
| msg.ResourceId = string(Read(buf, bytes)) | |||||
| } | |||||
| length32 := ReadUInt32(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length32) | |||||
| msg.LockKey = string(Read(buf, bytes)) | |||||
| } | |||||
| length32 = ReadUInt32(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length32) | |||||
| msg.ApplicationData = Read(buf, bytes) | |||||
| } | |||||
| return msg | |||||
| } | |||||
| func (c *BranchRegisterRequestCodec) Encode(in interface{}) []byte { | |||||
| buf := goetty.NewByteBuf(0) | |||||
| req, _ := in.(message.BranchRegisterRequest) | |||||
| Write16String(req.Xid, buf) | |||||
| buf.WriteByte(byte(req.BranchType)) | |||||
| Write16String(req.ResourceId, buf) | |||||
| Write32String(req.LockKey, buf) | |||||
| Write32String(string(req.ApplicationData), buf) | |||||
| return buf.RawBuf() | |||||
| } | |||||
| func (g *BranchRegisterRequestCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_BranchRegister | |||||
| } | |||||
| @@ -0,0 +1,74 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "github.com/seata/seata-go/pkg/protocol/transaction" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &BranchRegisterResponseCodec{}) | |||||
| } | |||||
| type BranchRegisterResponseCodec struct { | |||||
| } | |||||
| func (g *BranchRegisterResponseCodec) Decode(in []byte) interface{} { | |||||
| buf := goetty.NewByteBuf(len(in)) | |||||
| buf.Write(in) | |||||
| msg := message.BranchRegisterResponse{} | |||||
| resultCode := ReadByte(buf) | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| length := ReadUInt16(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length) | |||||
| msg.Msg = string(Read(buf, bytes)) | |||||
| } | |||||
| } | |||||
| exceptionCode := ReadByte(buf) | |||||
| msg.TransactionExceptionCode = transaction.TransactionExceptionCode(exceptionCode) | |||||
| msg.BranchId = int64(ReadUInt64(buf)) | |||||
| return msg | |||||
| } | |||||
| func (c *BranchRegisterResponseCodec) Encode(in interface{}) []byte { | |||||
| buf := goetty.NewByteBuf(0) | |||||
| resp, _ := in.(message.BranchRegisterResponse) | |||||
| resultCode := ReadByte(buf) | |||||
| if resultCode == byte(message.ResultCodeFailed) { | |||||
| var msg string | |||||
| if len(resp.Msg) > 128 { | |||||
| msg = resp.Msg[:128] | |||||
| } else { | |||||
| msg = resp.Msg | |||||
| } | |||||
| Write16String(msg, buf) | |||||
| } | |||||
| buf.WriteByte(byte(resp.TransactionExceptionCode)) | |||||
| branchID := uint64(resp.BranchId) | |||||
| branchIdBytes := []byte{ | |||||
| byte(branchID >> 56), | |||||
| byte(branchID >> 48), | |||||
| byte(branchID >> 40), | |||||
| byte(branchID >> 32), | |||||
| byte(branchID >> 24), | |||||
| byte(branchID >> 16), | |||||
| byte(branchID >> 8), | |||||
| byte(branchID), | |||||
| } | |||||
| buf.Write(branchIdBytes) | |||||
| return buf.RawBuf() | |||||
| } | |||||
| func (g *BranchRegisterResponseCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_BranchRegisterResult | |||||
| } | |||||
| @@ -2,244 +2,100 @@ package codec | |||||
| import ( | import ( | ||||
| "bytes" | "bytes" | ||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "sync" | |||||
| ) | ) | ||||
| import ( | import ( | ||||
| "vimagination.zapto.org/byteio" | "vimagination.zapto.org/byteio" | ||||
| ) | ) | ||||
| type SerializerType byte | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| type CodecType byte | |||||
| // TODO 待重构 | // TODO 待重构 | ||||
| const ( | const ( | ||||
| SEATA = byte(0x1) | |||||
| PROTOBUF = byte(0x2) | |||||
| KRYO = byte(0x4) | |||||
| FST = byte(0x8) | |||||
| CodeTypeSeata = CodecType(0x1) | |||||
| CodeTypeProtobuf = CodecType(0x2) | |||||
| CodeTypeKRYO = CodecType(0x4) | |||||
| CodeTypeFST = CodecType(0x8) | |||||
| ) | ) | ||||
| type Encoder func(in interface{}) []byte | |||||
| type Codec interface { | |||||
| Encode(in interface{}) []byte | |||||
| Decode(in []byte) interface{} | |||||
| GetMessageType() message.MessageType | |||||
| } | |||||
| type Decoder func(in []byte) (interface{}, int) | |||||
| var ( | |||||
| codecManager *CodecManager | |||||
| onceCodecManager = &sync.Once{} | |||||
| ) | |||||
| func MessageEncoder(codecType byte, in interface{}) []byte { | |||||
| switch codecType { | |||||
| case SEATA: | |||||
| return SeataEncoder(in) | |||||
| default: | |||||
| log.Errorf("not support codecType, %s", codecType) | |||||
| return nil | |||||
| func GetCodecManager() *CodecManager { | |||||
| if codecManager == nil { | |||||
| onceCodecManager.Do(func() { | |||||
| codecManager = &CodecManager{ | |||||
| codecMap: make(map[CodecType]map[message.MessageType]Codec, 0), | |||||
| } | |||||
| }) | |||||
| } | } | ||||
| return codecManager | |||||
| } | } | ||||
| func MessageDecoder(codecType byte, in []byte) (interface{}, int) { | |||||
| switch codecType { | |||||
| case SEATA: | |||||
| return SeataDecoder(in) | |||||
| default: | |||||
| log.Errorf("not support codecType, %s", codecType) | |||||
| return nil, 0 | |||||
| } | |||||
| type CodecManager struct { | |||||
| mutex sync.Mutex | |||||
| codecMap map[CodecType]map[message.MessageType]Codec | |||||
| } | } | ||||
| func SeataEncoder(in interface{}) []byte { | |||||
| var result = make([]byte, 0) | |||||
| msg := in.(message.MessageTypeAware) | |||||
| typeCode := msg.GetTypeCode() | |||||
| encoder := getMessageEncoder(typeCode) | |||||
| func (c *CodecManager) RegisterCodec(codecType CodecType, codec Codec) { | |||||
| c.mutex.Lock() | |||||
| defer c.mutex.Unlock() | |||||
| codecTypeMap := c.codecMap[codecType] | |||||
| if codecTypeMap == nil { | |||||
| codecTypeMap = make(map[message.MessageType]Codec, 0) | |||||
| c.codecMap[codecType] = codecTypeMap | |||||
| } | |||||
| codecTypeMap[codec.GetMessageType()] = codec | |||||
| } | |||||
| typeC := uint16(typeCode) | |||||
| if encoder != nil { | |||||
| body := encoder(in) | |||||
| result = append(result, []byte{byte(typeC >> 8), byte(typeC)}...) | |||||
| result = append(result, body...) | |||||
| func (c *CodecManager) GetCodec(codecType CodecType, msgType message.MessageType) Codec { | |||||
| if m := c.codecMap[codecType]; m != nil { | |||||
| return m[msgType] | |||||
| } | } | ||||
| return result | |||||
| return nil | |||||
| } | } | ||||
| func SeataDecoder(in []byte) (interface{}, int) { | |||||
| func (c *CodecManager) Decode(codecType CodecType, in []byte) interface{} { | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | ||||
| typeCode, _, _ := r.ReadInt16() | typeCode, _, _ := r.ReadInt16() | ||||
| codec := c.GetCodec(codecType, message.MessageType(typeCode)) | |||||
| decoder := getMessageDecoder(message.MessageType(typeCode)) | |||||
| if decoder != nil { | |||||
| return decoder(in[2:]) | |||||
| } | |||||
| return nil, 0 | |||||
| } | |||||
| func getMessageEncoder(typeCode message.MessageType) Encoder { | |||||
| switch typeCode { | |||||
| case message.MessageType_SeataMerge: | |||||
| return MergedWarpMessageEncoder | |||||
| case message.MessageType_SeataMergeResult: | |||||
| return MergeResultMessageEncoder | |||||
| case message.MessageType_RegClt: | |||||
| return RegisterTMRequestEncoder | |||||
| case message.MessageType_RegCltResult: | |||||
| return RegisterTMResponseEncoder | |||||
| case message.MessageType_RegRm: | |||||
| return RegisterRMRequestEncoder | |||||
| case message.MessageType_RegRmResult: | |||||
| return RegisterRMResponseEncoder | |||||
| case message.MessageType_BranchCommit: | |||||
| return BranchCommitRequestEncoder | |||||
| case message.MessageType_BranchRollback: | |||||
| return BranchRollbackRequestEncoder | |||||
| case message.MessageType_GlobalReport: | |||||
| return GlobalReportRequestEncoder | |||||
| default: | |||||
| var encoder Encoder | |||||
| encoder = getMergeRequestMessageEncoder(typeCode) | |||||
| if encoder != nil { | |||||
| return encoder | |||||
| } | |||||
| encoder = getMergeResponseMessageEncoder(typeCode) | |||||
| if encoder != nil { | |||||
| return encoder | |||||
| } | |||||
| log.Errorf("not support typeCode, %d", typeCode) | |||||
| if codec == nil { | |||||
| log.Errorf("This message type [%v] has no codec to decode", typeCode) | |||||
| return nil | return nil | ||||
| } | } | ||||
| return codec.Decode(in[2:]) | |||||
| } | } | ||||
| func getMergeRequestMessageEncoder(typeCode message.MessageType) Encoder { | |||||
| switch typeCode { | |||||
| case message.MessageType_GlobalBegin: | |||||
| return GlobalBeginRequestEncoder | |||||
| case message.MessageType_GlobalCommit: | |||||
| return GlobalCommitRequestEncoder | |||||
| case message.MessageType_GlobalRollback: | |||||
| return GlobalRollbackRequestEncoder | |||||
| case message.MessageType_GlobalStatus: | |||||
| return GlobalStatusRequestEncoder | |||||
| case message.MessageType_GlobalLockQuery: | |||||
| return GlobalLockQueryRequestEncoder | |||||
| case message.MessageType_BranchRegister: | |||||
| return BranchRegisterRequestEncoder | |||||
| case message.MessageType_BranchStatusReport: | |||||
| return BranchReportRequestEncoder | |||||
| case message.MessageType_GlobalReport: | |||||
| return GlobalReportRequestEncoder | |||||
| default: | |||||
| break | |||||
| } | |||||
| return nil | |||||
| } | |||||
| func getMergeResponseMessageEncoder(typeCode message.MessageType) Encoder { | |||||
| switch typeCode { | |||||
| case message.MessageType_GlobalBeginResult: | |||||
| return GlobalBeginResponseEncoder | |||||
| case message.MessageType_GlobalCommitResult: | |||||
| return GlobalCommitResponseEncoder | |||||
| case message.MessageType_GlobalRollbackResult: | |||||
| return GlobalRollbackResponseEncoder | |||||
| case message.MessageType_GlobalStatusResult: | |||||
| return GlobalStatusResponseEncoder | |||||
| case message.MessageType_GlobalLockQueryResult: | |||||
| return GlobalLockQueryResponseEncoder | |||||
| case message.MessageType_BranchRegisterResult: | |||||
| return BranchRegisterResponseEncoder | |||||
| case message.MessageType_BranchStatusReportResult: | |||||
| return BranchReportResponseEncoder | |||||
| case message.MessageType_BranchCommitResult: | |||||
| return BranchCommitResponseEncoder | |||||
| case message.MessageType_BranchRollbackResult: | |||||
| return BranchRollbackResponseEncoder | |||||
| case message.MessageType_GlobalReportResult: | |||||
| return GlobalReportResponseEncoder | |||||
| default: | |||||
| break | |||||
| } | |||||
| return nil | |||||
| } | |||||
| func (c *CodecManager) Encode(codecType CodecType, in interface{}) []byte { | |||||
| var result = make([]byte, 0) | |||||
| msg := in.(message.MessageTypeAware) | |||||
| typeCode := msg.GetTypeCode() | |||||
| func getMessageDecoder(typeCode message.MessageType) Decoder { | |||||
| switch typeCode { | |||||
| case message.MessageType_SeataMerge: | |||||
| return MergedWarpMessageDecoder | |||||
| case message.MessageType_SeataMergeResult: | |||||
| return MergeResultMessageDecoder | |||||
| case message.MessageType_RegClt: | |||||
| return RegisterTMRequestDecoder | |||||
| case message.MessageType_RegCltResult: | |||||
| return RegisterTMResponseDecoder | |||||
| case message.MessageType_RegRm: | |||||
| return RegisterRMRequestDecoder | |||||
| case message.MessageType_RegRmResult: | |||||
| return RegisterRMResponseDecoder | |||||
| case message.MessageType_BranchCommit: | |||||
| return BranchCommitRequestDecoder | |||||
| case message.MessageType_BranchRollback: | |||||
| return BranchRollbackRequestDecoder | |||||
| case message.MessageType_GlobalReport: | |||||
| return GlobalReportRequestDecoder | |||||
| default: | |||||
| var Decoder Decoder | |||||
| Decoder = getMergeRequestMessageDecoder(typeCode) | |||||
| if Decoder != nil { | |||||
| return Decoder | |||||
| } | |||||
| Decoder = getMergeResponseMessageDecoder(typeCode) | |||||
| if Decoder != nil { | |||||
| return Decoder | |||||
| } | |||||
| log.Errorf("not support typeCode, %d", typeCode) | |||||
| codec := c.GetCodec(codecType, typeCode) | |||||
| if codec == nil { | |||||
| log.Errorf("This message type [%v] has no codec to encode", typeCode) | |||||
| return nil | return nil | ||||
| } | } | ||||
| } | |||||
| func getMergeRequestMessageDecoder(typeCode message.MessageType) Decoder { | |||||
| switch typeCode { | |||||
| case message.MessageType_GlobalBegin: | |||||
| return GlobalBeginRequestDecoder | |||||
| case message.MessageType_GlobalCommit: | |||||
| return GlobalCommitRequestDecoder | |||||
| case message.MessageType_GlobalRollback: | |||||
| return GlobalRollbackRequestDecoder | |||||
| case message.MessageType_GlobalStatus: | |||||
| return GlobalStatusRequestDecoder | |||||
| case message.MessageType_GlobalLockQuery: | |||||
| return GlobalLockQueryRequestDecoder | |||||
| case message.MessageType_BranchRegister: | |||||
| return BranchRegisterRequestDecoder | |||||
| case message.MessageType_BranchStatusReport: | |||||
| return BranchReportRequestDecoder | |||||
| case message.MessageType_GlobalReport: | |||||
| return GlobalReportRequestDecoder | |||||
| default: | |||||
| break | |||||
| } | |||||
| return nil | |||||
| } | |||||
| body := codec.Encode(in) | |||||
| typeC := uint16(typeCode) | |||||
| result = append(result, []byte{byte(typeC >> 8), byte(typeC)}...) | |||||
| result = append(result, body...) | |||||
| func getMergeResponseMessageDecoder(typeCode message.MessageType) Decoder { | |||||
| switch typeCode { | |||||
| case message.MessageType_GlobalBeginResult: | |||||
| return GlobalBeginResponseDecoder | |||||
| case message.MessageType_GlobalCommitResult: | |||||
| return GlobalCommitResponseDecoder | |||||
| case message.MessageType_GlobalRollbackResult: | |||||
| return GlobalRollbackResponseDecoder | |||||
| case message.MessageType_GlobalStatusResult: | |||||
| return GlobalStatusResponseDecoder | |||||
| case message.MessageType_GlobalLockQueryResult: | |||||
| return GlobalLockQueryResponseDecoder | |||||
| case message.MessageType_BranchRegisterResult: | |||||
| return BranchRegisterResponseDecoder | |||||
| case message.MessageType_BranchStatusReportResult: | |||||
| return BranchReportResponseDecoder | |||||
| case message.MessageType_BranchCommitResult: | |||||
| return BranchCommitResponseDecoder | |||||
| case message.MessageType_BranchRollbackResult: | |||||
| return BranchRollbackResponseDecoder | |||||
| case message.MessageType_GlobalReportResult: | |||||
| return GlobalReportResponseDecoder | |||||
| default: | |||||
| break | |||||
| } | |||||
| return nil | |||||
| return result | |||||
| } | } | ||||
| @@ -0,0 +1,189 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| "github.com/fagongzi/util/hack" | |||||
| ) | |||||
| // Write16String write string value with 16 byte length | |||||
| func Write16String(value string, buf *goetty.ByteBuf) { | |||||
| if value != "" { | |||||
| buf.WriteUInt16(uint16(len(value))) | |||||
| buf.WriteString(value) | |||||
| } else { | |||||
| buf.WriteUInt16(uint16(0)) | |||||
| } | |||||
| } | |||||
| // Write16String write string value with 16 byte length | |||||
| func Write32String(value string, buf *goetty.ByteBuf) { | |||||
| if value != "" { | |||||
| buf.WriteUInt32(uint32(len(value))) | |||||
| buf.WriteString(value) | |||||
| } else { | |||||
| buf.WriteUInt32(uint32(0)) | |||||
| } | |||||
| } | |||||
| // Write8String write string value with 8 byte length | |||||
| func Write8String(value string, buf *goetty.ByteBuf) { | |||||
| if value != "" { | |||||
| buf.WriteByte(uint8(len(value))) | |||||
| buf.WriteString(value) | |||||
| } else { | |||||
| buf.WriteByte(uint8(0)) | |||||
| } | |||||
| } | |||||
| // ReadString read string value | |||||
| func ReadString(buf *goetty.ByteBuf) string { | |||||
| size := ReadUInt16(buf) | |||||
| if size == 0 { | |||||
| return "" | |||||
| } | |||||
| _, value, _ := buf.ReadBytes(int(size)) | |||||
| return hack.SliceToString(value) | |||||
| } | |||||
| // MaybeReadString maybe read string value | |||||
| func MaybeReadString(buf *goetty.ByteBuf) (string, bool) { | |||||
| if buf.Readable() < 2 { | |||||
| return "", false | |||||
| } | |||||
| size := ReadUInt16(buf) | |||||
| if size == 0 { | |||||
| return "", true | |||||
| } | |||||
| if buf.Readable() < int(size) { | |||||
| return "", false | |||||
| } | |||||
| _, value, _ := buf.ReadBytes(int(size)) | |||||
| return hack.SliceToString(value), true | |||||
| } | |||||
| // WriteBigString write big string | |||||
| func WriteBigString(value string, buf *goetty.ByteBuf) { | |||||
| if value != "" { | |||||
| buf.WriteInt(len(value)) | |||||
| buf.WriteString(value) | |||||
| } else { | |||||
| buf.WriteInt(0) | |||||
| } | |||||
| } | |||||
| // ReadBigString read big string | |||||
| func ReadBigString(buf *goetty.ByteBuf) string { | |||||
| size := ReadInt(buf) | |||||
| if size == 0 { | |||||
| return "" | |||||
| } | |||||
| _, value, _ := buf.ReadBytes(size) | |||||
| return hack.SliceToString(value) | |||||
| } | |||||
| // MaybeReadBigString maybe read string value | |||||
| func MaybeReadBigString(buf *goetty.ByteBuf) (string, bool) { | |||||
| if buf.Readable() < 4 { | |||||
| return "", false | |||||
| } | |||||
| size := ReadInt(buf) | |||||
| if size == 0 { | |||||
| return "", true | |||||
| } | |||||
| if buf.Readable() < size { | |||||
| return "", false | |||||
| } | |||||
| _, value, _ := buf.ReadBytes(int(size)) | |||||
| return hack.SliceToString(value), true | |||||
| } | |||||
| // ReadUInt64 read uint64 value | |||||
| func ReadUInt64(buf *goetty.ByteBuf) uint64 { | |||||
| value, _ := buf.ReadUInt64() | |||||
| return value | |||||
| } | |||||
| // ReadUInt16 read uint16 value | |||||
| func ReadUInt16(buf *goetty.ByteBuf) uint16 { | |||||
| value, _ := buf.ReadUInt16() | |||||
| return value | |||||
| } | |||||
| // ReadUInt32 read uint16 value | |||||
| func ReadUInt32(buf *goetty.ByteBuf) uint32 { | |||||
| value, _ := buf.ReadUInt32() | |||||
| return value | |||||
| } | |||||
| // ReadUInt32 read uint16 value | |||||
| func Read(buf *goetty.ByteBuf, p []byte) []byte { | |||||
| buf.Read(p) | |||||
| return p | |||||
| } | |||||
| // ReadInt read int value | |||||
| func ReadInt(buf *goetty.ByteBuf) int { | |||||
| value, _ := buf.ReadInt() | |||||
| return value | |||||
| } | |||||
| // ReadByte read byte value | |||||
| func ReadByte(buf *goetty.ByteBuf) byte { | |||||
| value, _ := buf.ReadByte() | |||||
| return value | |||||
| } | |||||
| // ReadBytes read bytes value | |||||
| func ReadBytes(n int, buf *goetty.ByteBuf) []byte { | |||||
| _, value, _ := buf.ReadBytes(n) | |||||
| return value | |||||
| } | |||||
| // WriteBool write bool value | |||||
| func WriteBool(value bool, out *goetty.ByteBuf) { | |||||
| out.WriteByte(boolToByte(value)) | |||||
| } | |||||
| // WriteSlice write slice value | |||||
| func WriteSlice(value []byte, buf *goetty.ByteBuf) { | |||||
| buf.WriteUInt16(uint16(len(value))) | |||||
| if len(value) > 0 { | |||||
| buf.Write(value) | |||||
| } | |||||
| } | |||||
| // ReadSlice read slice value | |||||
| func ReadSlice(buf *goetty.ByteBuf) []byte { | |||||
| l, _ := buf.ReadUInt16() | |||||
| if l == 0 { | |||||
| return nil | |||||
| } | |||||
| _, data, _ := buf.ReadBytes(int(l)) | |||||
| return data | |||||
| } | |||||
| func boolToByte(value bool) byte { | |||||
| if value { | |||||
| return 1 | |||||
| } | |||||
| return 0 | |||||
| } | |||||
| func byteToBool(value byte) bool { | |||||
| if value == 1 { | |||||
| return true | |||||
| } | |||||
| return false | |||||
| } | |||||
| @@ -0,0 +1,51 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| type CommonGlobalEndRequestCodec struct { | |||||
| } | |||||
| func (c *CommonGlobalEndRequestCodec) Encode(in interface{}) []byte { | |||||
| req, _ := in.(message.AbstractGlobalEndRequest) | |||||
| buf := goetty.NewByteBuf(0) | |||||
| Write16String(req.Xid, buf) | |||||
| Write16String(string(req.ExtraData), buf) | |||||
| return buf.RawBuf() | |||||
| } | |||||
| func (c *CommonGlobalEndRequestCodec) Decode(in []byte) interface{} { | |||||
| res := message.AbstractGlobalEndRequest{} | |||||
| buf := goetty.NewByteBuf(len(in)) | |||||
| buf.Write(in) | |||||
| var xidLen int | |||||
| if buf.Readable() >= 2 { | |||||
| xidLen = int(ReadUInt16(buf)) | |||||
| } | |||||
| if buf.Readable() >= xidLen { | |||||
| xidBytes := make([]byte, xidLen) | |||||
| xidBytes = Read(buf, xidBytes) | |||||
| res.Xid = string(xidBytes) | |||||
| } | |||||
| var extraDataLen int | |||||
| if buf.Readable() >= 2 { | |||||
| extraDataLen = int(ReadUInt16(buf)) | |||||
| } | |||||
| if buf.Readable() >= extraDataLen { | |||||
| extraDataBytes := make([]byte, xidLen) | |||||
| extraDataBytes = Read(buf, extraDataBytes) | |||||
| res.ExtraData = extraDataBytes | |||||
| } | |||||
| return res | |||||
| } | |||||
| @@ -0,0 +1,58 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "github.com/seata/seata-go/pkg/protocol/transaction" | |||||
| ) | |||||
| type CommonGlobalEndResponseCodec struct { | |||||
| } | |||||
| func (c *CommonGlobalEndResponseCodec) Encode(in interface{}) []byte { | |||||
| buf := goetty.NewByteBuf(0) | |||||
| resp := in.(message.AbstractGlobalEndResponse) | |||||
| buf.WriteByte(byte(resp.ResultCode)) | |||||
| if resp.ResultCode == message.ResultCodeFailed { | |||||
| var msg string | |||||
| if len(resp.Msg) > 128 { | |||||
| msg = resp.Msg[:128] | |||||
| } else { | |||||
| msg = resp.Msg | |||||
| } | |||||
| Write16String(msg, buf) | |||||
| } | |||||
| buf.WriteByte(byte(resp.TransactionExceptionCode)) | |||||
| buf.WriteByte(byte(resp.GlobalStatus)) | |||||
| return buf.RawBuf() | |||||
| } | |||||
| func (c *CommonGlobalEndResponseCodec) Decode(in []byte) interface{} { | |||||
| buf := goetty.NewByteBuf(len(in)) | |||||
| buf.Write(in) | |||||
| msg := message.AbstractGlobalEndResponse{} | |||||
| resultCode := ReadByte(buf) | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| length := ReadUInt16(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length) | |||||
| msg.Msg = string(Read(buf, bytes)) | |||||
| } | |||||
| } | |||||
| exceptionCode := ReadByte(buf) | |||||
| msg.TransactionExceptionCode = transaction.TransactionExceptionCode(exceptionCode) | |||||
| globalStatus := ReadByte(buf) | |||||
| msg.GlobalStatus = transaction.GlobalStatus(globalStatus) | |||||
| return msg | |||||
| } | |||||
| @@ -0,0 +1,72 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| type AbstractIdentifyRequestCodec struct { | |||||
| } | |||||
| func (c *AbstractIdentifyRequestCodec) Encode(in interface{}) []byte { | |||||
| req := in.(message.AbstractIdentifyRequest) | |||||
| buf := goetty.NewByteBuf(0) | |||||
| Write16String(req.Version, buf) | |||||
| Write16String(req.ApplicationId, buf) | |||||
| Write16String(req.TransactionServiceGroup, buf) | |||||
| Write16String(string(req.ExtraData), buf) | |||||
| return buf.RawBuf() | |||||
| } | |||||
| func (c *AbstractIdentifyRequestCodec) Decode(in []byte) interface{} { | |||||
| msg := message.AbstractIdentifyRequest{} | |||||
| buf := goetty.NewByteBuf(len(in)) | |||||
| buf.Write(in) | |||||
| var len uint16 | |||||
| if buf.Readable() < 2 { | |||||
| return msg | |||||
| } | |||||
| len = ReadUInt16(buf) | |||||
| if uint16(buf.Readable()) < len { | |||||
| return msg | |||||
| } | |||||
| versionBytes := make([]byte, len) | |||||
| msg.Version = string(Read(buf, versionBytes)) | |||||
| if buf.Readable() < 2 { | |||||
| return msg | |||||
| } | |||||
| len = ReadUInt16(buf) | |||||
| if uint16(buf.Readable()) < len { | |||||
| return msg | |||||
| } | |||||
| applicationIdBytes := make([]byte, len) | |||||
| msg.ApplicationId = string(Read(buf, applicationIdBytes)) | |||||
| if buf.Readable() < 2 { | |||||
| return msg | |||||
| } | |||||
| len = ReadUInt16(buf) | |||||
| if uint16(buf.Readable()) < len { | |||||
| return msg | |||||
| } | |||||
| transactionServiceGroupBytes := make([]byte, len) | |||||
| msg.TransactionServiceGroup = string(Read(buf, transactionServiceGroupBytes)) | |||||
| if buf.Readable() < 2 { | |||||
| return msg | |||||
| } | |||||
| len = ReadUInt16(buf) | |||||
| if len > 0 && uint16(buf.Readable()) > len { | |||||
| extraDataBytes := make([]byte, len) | |||||
| msg.ExtraData = Read(buf, extraDataBytes) | |||||
| } | |||||
| return msg | |||||
| } | |||||
| @@ -0,0 +1,47 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| type AbstractIdentifyResponseCodec struct { | |||||
| } | |||||
| func (c *AbstractIdentifyResponseCodec) Encode(in interface{}) []byte { | |||||
| buf := goetty.NewByteBuf(0) | |||||
| resp := in.(message.AbstractIdentifyResponse) | |||||
| if resp.Identified { | |||||
| buf.WriteByte(byte(1)) | |||||
| } else { | |||||
| buf.WriteByte(byte(0)) | |||||
| } | |||||
| Write16String(resp.Version, buf) | |||||
| return buf.RawBuf() | |||||
| } | |||||
| func (c *AbstractIdentifyResponseCodec) Decode(in []byte) interface{} { | |||||
| buf := goetty.NewByteBuf(len(in)) | |||||
| buf.Write(in) | |||||
| msg := message.AbstractIdentifyResponse{} | |||||
| identified, _ := buf.ReadByte() | |||||
| if identified == byte(1) { | |||||
| msg.Identified = true | |||||
| } else if identified == byte(0) { | |||||
| msg.Identified = false | |||||
| } | |||||
| length := ReadUInt16(buf) | |||||
| if length > 0 { | |||||
| versionBytes := make([]byte, length) | |||||
| msg.Version = string(Read(buf, versionBytes)) | |||||
| } | |||||
| return msg | |||||
| } | |||||
| @@ -0,0 +1,45 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalBeginRequestCodec{}) | |||||
| } | |||||
| type GlobalBeginRequestCodec struct { | |||||
| } | |||||
| func (c *GlobalBeginRequestCodec) Encode(in interface{}) []byte { | |||||
| req := in.(message.GlobalBeginRequest) | |||||
| buf := goetty.NewByteBuf(0) | |||||
| buf.WriteUInt32(uint32(req.Timeout)) | |||||
| Write16String(req.TransactionName, buf) | |||||
| return buf.RawBuf() | |||||
| } | |||||
| func (g *GlobalBeginRequestCodec) Decode(in []byte) interface{} { | |||||
| msg := message.GlobalBeginRequest{} | |||||
| buf := goetty.NewByteBuf(len(in)) | |||||
| buf.Write(in) | |||||
| msg.Timeout = int32(ReadUInt32(buf)) | |||||
| len := ReadUInt16(buf) | |||||
| if len > 0 { | |||||
| transactionName := make([]byte, len) | |||||
| msg.TransactionName = string(Read(buf, transactionName)) | |||||
| } | |||||
| return msg | |||||
| } | |||||
| func (g *GlobalBeginRequestCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_GlobalBegin | |||||
| } | |||||
| @@ -0,0 +1,76 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "github.com/seata/seata-go/pkg/protocol/transaction" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalBeginResponseCodec{}) | |||||
| } | |||||
| type GlobalBeginResponseCodec struct { | |||||
| } | |||||
| func (c *GlobalBeginResponseCodec) Encode(in interface{}) []byte { | |||||
| buf := goetty.NewByteBuf(0) | |||||
| resp := in.(message.GlobalBeginResponse) | |||||
| buf.WriteByte(byte(resp.ResultCode)) | |||||
| if resp.ResultCode == message.ResultCodeFailed { | |||||
| var msg string | |||||
| if len(resp.Msg) > 128 { | |||||
| msg = resp.Msg[:128] | |||||
| } else { | |||||
| msg = resp.Msg | |||||
| } | |||||
| Write16String(msg, buf) | |||||
| } | |||||
| buf.WriteByte(byte(resp.TransactionExceptionCode)) | |||||
| Write16String(resp.Xid, buf) | |||||
| Write16String(string(resp.ExtraData), buf) | |||||
| return buf.RawBuf() | |||||
| } | |||||
| func (g *GlobalBeginResponseCodec) Decode(in []byte) interface{} { | |||||
| var lenth uint16 | |||||
| buf := goetty.NewByteBuf(len(in)) | |||||
| buf.Write(in) | |||||
| msg := message.GlobalBeginResponse{} | |||||
| resultCode := ReadByte(buf) | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| lenth = ReadUInt16(buf) | |||||
| if lenth > 0 { | |||||
| bytes := make([]byte, lenth) | |||||
| msg.Msg = string(Read(buf, bytes)) | |||||
| } | |||||
| } | |||||
| exceptionCode := ReadByte(buf) | |||||
| msg.TransactionExceptionCode = transaction.TransactionExceptionCode(exceptionCode) | |||||
| lenth = ReadUInt16(buf) | |||||
| if lenth > 0 { | |||||
| bytes := make([]byte, lenth) | |||||
| msg.Xid = string(Read(buf, bytes)) | |||||
| } | |||||
| lenth = ReadUInt16(buf) | |||||
| if lenth > 0 { | |||||
| bytes := make([]byte, lenth) | |||||
| msg.ExtraData = Read(buf, bytes) | |||||
| } | |||||
| return msg | |||||
| } | |||||
| func (g *GlobalBeginResponseCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_GlobalBeginResult | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalCommitRequestCodec{}) | |||||
| } | |||||
| type GlobalCommitRequestCodec struct { | |||||
| CommonGlobalEndRequestCodec | |||||
| } | |||||
| func (g *GlobalCommitRequestCodec) Decode(in []byte) interface{} { | |||||
| req := g.CommonGlobalEndRequestCodec.Decode(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndRequest) | |||||
| return message.GlobalCommitRequest{ | |||||
| AbstractGlobalEndRequest: abstractGlobalEndRequest, | |||||
| } | |||||
| } | |||||
| func (g *GlobalCommitRequestCodec) Encode(in interface{}) []byte { | |||||
| req := in.(message.GlobalCommitRequest) | |||||
| return g.CommonGlobalEndRequestCodec.Encode(req.AbstractGlobalEndRequest) | |||||
| } | |||||
| func (g *GlobalCommitRequestCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_GlobalCommit | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalCommitResponseCodec{}) | |||||
| } | |||||
| type GlobalCommitResponseCodec struct { | |||||
| CommonGlobalEndResponseCodec | |||||
| } | |||||
| func (g *GlobalCommitResponseCodec) Decode(in []byte) interface{} { | |||||
| req := g.CommonGlobalEndResponseCodec.Decode(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndResponse) | |||||
| return message.GlobalCommitResponse{ | |||||
| AbstractGlobalEndResponse: abstractGlobalEndRequest, | |||||
| } | |||||
| } | |||||
| func (g *GlobalCommitResponseCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_GlobalCommitResult | |||||
| } | |||||
| @@ -0,0 +1,21 @@ | |||||
| package codec | |||||
| //func init() { | |||||
| // GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalReportRequestCodec{}) | |||||
| //} | |||||
| // | |||||
| //type GlobalReportRequestCodec struct { | |||||
| // CommonGlobalEndRequestCodec | |||||
| //} | |||||
| // | |||||
| //func (g *GlobalReportRequestCodec) Decode(in []byte) interface{} { | |||||
| // req := g.CommonGlobalEndRequestCodec.Decode(in) | |||||
| // abstractGlobalEndRequest := req.(message.AbstractGlobalEndRequest) | |||||
| // return message.GlobalCommitRequest{ | |||||
| // AbstractGlobalEndRequest: abstractGlobalEndRequest, | |||||
| // } | |||||
| //} | |||||
| // | |||||
| //func (g *GlobalReportRequestCodec) GetMessageType() message.MessageType { | |||||
| // return message.MessageType_GlobalCommit | |||||
| //} | |||||
| @@ -0,0 +1,25 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalReportResponseCodec{}) | |||||
| } | |||||
| type GlobalReportResponseCodec struct { | |||||
| CommonGlobalEndResponseCodec | |||||
| } | |||||
| func (g *GlobalReportResponseCodec) Decode(in []byte) interface{} { | |||||
| req := g.CommonGlobalEndResponseCodec.Decode(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndResponse) | |||||
| return message.GlobalReportResponse{ | |||||
| AbstractGlobalEndResponse: abstractGlobalEndRequest, | |||||
| } | |||||
| } | |||||
| func (g *GlobalReportResponseCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_GlobalReportResult | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalRollbackRequestCodec{}) | |||||
| } | |||||
| type GlobalRollbackRequestCodec struct { | |||||
| CommonGlobalEndRequestCodec | |||||
| } | |||||
| func (g *GlobalRollbackRequestCodec) Decode(in []byte) interface{} { | |||||
| req := g.CommonGlobalEndRequestCodec.Decode(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndRequest) | |||||
| return message.GlobalCommitRequest{ | |||||
| AbstractGlobalEndRequest: abstractGlobalEndRequest, | |||||
| } | |||||
| } | |||||
| func (g *GlobalRollbackRequestCodec) Encode(in interface{}) []byte { | |||||
| req := in.(message.GlobalRollbackRequest) | |||||
| return g.CommonGlobalEndRequestCodec.Encode(req.AbstractGlobalEndRequest) | |||||
| } | |||||
| func (g *GlobalRollbackRequestCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_GlobalRollback | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalRollbackResponseCodec{}) | |||||
| } | |||||
| type GlobalRollbackResponseCodec struct { | |||||
| CommonGlobalEndResponseCodec | |||||
| } | |||||
| func (g *GlobalRollbackResponseCodec) Decode(in []byte) interface{} { | |||||
| req := g.CommonGlobalEndResponseCodec.Decode(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndResponse) | |||||
| return message.GlobalRollbackResponse{ | |||||
| AbstractGlobalEndResponse: abstractGlobalEndRequest, | |||||
| } | |||||
| } | |||||
| func (g *GlobalRollbackResponseCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_GlobalRollbackResult | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalStatusRequestCodec{}) | |||||
| } | |||||
| type GlobalStatusRequestCodec struct { | |||||
| CommonGlobalEndRequestCodec | |||||
| } | |||||
| func (g *GlobalStatusRequestCodec) Decode(in []byte) interface{} { | |||||
| req := g.CommonGlobalEndRequestCodec.Decode(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndRequest) | |||||
| return message.GlobalStatusRequest{ | |||||
| AbstractGlobalEndRequest: abstractGlobalEndRequest, | |||||
| } | |||||
| } | |||||
| func (g *GlobalStatusRequestCodec) Encode(in interface{}) []byte { | |||||
| req := in.(message.GlobalStatusRequest) | |||||
| return g.CommonGlobalEndRequestCodec.Encode(req.AbstractGlobalEndRequest) | |||||
| } | |||||
| func (g *GlobalStatusRequestCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_GlobalStatus | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &GlobalStatusResponseCodec{}) | |||||
| } | |||||
| type GlobalStatusResponseCodec struct { | |||||
| CommonGlobalEndResponseCodec | |||||
| } | |||||
| func (g *GlobalStatusResponseCodec) Decode(in []byte) interface{} { | |||||
| req := g.CommonGlobalEndResponseCodec.Decode(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndResponse) | |||||
| return message.GlobalStatusResponse{ | |||||
| AbstractGlobalEndResponse: abstractGlobalEndRequest, | |||||
| } | |||||
| } | |||||
| func (g *GlobalStatusResponseCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_GlobalStatusResult | |||||
| } | |||||
| @@ -0,0 +1,71 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/fagongzi/goetty" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &RegisterRMRequestCodec{}) | |||||
| } | |||||
| type RegisterRMRequestCodec struct { | |||||
| } | |||||
| func (g *RegisterRMRequestCodec) Decode(in []byte) interface{} { | |||||
| buf := goetty.NewByteBuf(len(in)) | |||||
| buf.Write(in) | |||||
| msg := message.RegisterRMRequest{} | |||||
| length := ReadUInt16(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length) | |||||
| msg.Version = string(Read(buf, bytes)) | |||||
| } | |||||
| length = ReadUInt16(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length) | |||||
| msg.ApplicationId = string(Read(buf, bytes)) | |||||
| } | |||||
| length = ReadUInt16(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length) | |||||
| msg.TransactionServiceGroup = string(Read(buf, bytes)) | |||||
| } | |||||
| length = ReadUInt16(buf) | |||||
| if length > 0 { | |||||
| bytes := make([]byte, length) | |||||
| msg.ExtraData = Read(buf, bytes) | |||||
| } | |||||
| length32 := ReadUInt32(buf) | |||||
| if length32 > 0 { | |||||
| bytes := make([]byte, length32) | |||||
| msg.ResourceIds = string(Read(buf, bytes)) | |||||
| } | |||||
| return msg | |||||
| } | |||||
| func (c *RegisterRMRequestCodec) Encode(in interface{}) []byte { | |||||
| req := in.(message.RegisterRMRequest) | |||||
| buf := goetty.NewByteBuf(0) | |||||
| Write16String(req.Version, buf) | |||||
| Write16String(req.ApplicationId, buf) | |||||
| Write16String(req.TransactionServiceGroup, buf) | |||||
| Write16String(string(req.ExtraData), buf) | |||||
| Write16String(req.ResourceIds, buf) | |||||
| return buf.RawBuf() | |||||
| } | |||||
| func (g *RegisterRMRequestCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_RegRm | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &RegisterRMResponseCodec{}) | |||||
| } | |||||
| type RegisterRMResponseCodec struct { | |||||
| AbstractIdentifyResponseCodec | |||||
| } | |||||
| func (g *RegisterRMResponseCodec) Decode(in []byte) interface{} { | |||||
| req := g.AbstractIdentifyResponseCodec.Decode(in) | |||||
| abstractIdentifyResponse := req.(message.AbstractIdentifyResponse) | |||||
| return message.RegisterRMResponse{ | |||||
| AbstractIdentifyResponse: abstractIdentifyResponse, | |||||
| } | |||||
| } | |||||
| func (g *RegisterRMResponseCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_RegRmResult | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &RegisterTMRequestCodec{}) | |||||
| } | |||||
| type RegisterTMRequestCodec struct { | |||||
| AbstractIdentifyRequestCodec | |||||
| } | |||||
| func (g *RegisterTMRequestCodec) Decode(in []byte) interface{} { | |||||
| req := g.AbstractIdentifyRequestCodec.Decode(in) | |||||
| abstractIdentifyRequest := req.(message.AbstractIdentifyRequest) | |||||
| return message.RegisterTMRequest{ | |||||
| AbstractIdentifyRequest: abstractIdentifyRequest, | |||||
| } | |||||
| } | |||||
| func (c *RegisterTMRequestCodec) Encode(in interface{}) []byte { | |||||
| req := in.(message.RegisterTMRequest) | |||||
| return c.AbstractIdentifyRequestCodec.Encode(req.AbstractIdentifyRequest) | |||||
| } | |||||
| func (g *RegisterTMRequestCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_RegClt | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| package codec | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| func init() { | |||||
| GetCodecManager().RegisterCodec(CodeTypeSeata, &RegisterTMResponseCodec{}) | |||||
| } | |||||
| type RegisterTMResponseCodec struct { | |||||
| AbstractIdentifyResponseCodec | |||||
| } | |||||
| func (g *RegisterTMResponseCodec) Decode(in []byte) interface{} { | |||||
| req := g.AbstractIdentifyResponseCodec.Decode(in) | |||||
| abstractIdentifyResponse := req.(message.AbstractIdentifyResponse) | |||||
| return message.RegisterTMResponse{ | |||||
| AbstractIdentifyResponse: abstractIdentifyResponse, | |||||
| } | |||||
| } | |||||
| func (c *RegisterTMResponseCodec) Encode(in interface{}) []byte { | |||||
| resp := in.(message.RegisterTMResponse) | |||||
| return c.AbstractIdentifyResponseCodec.Encode(resp.AbstractIdentifyResponse) | |||||
| } | |||||
| func (g *RegisterTMResponseCodec) GetMessageType() message.MessageType { | |||||
| return message.MessageType_RegCltResult | |||||
| } | |||||
| @@ -1,779 +0,0 @@ | |||||
| package codec | |||||
| import ( | |||||
| "bytes" | |||||
| model2 "github.com/seata/seata-go/pkg/protocol/branch" | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "github.com/seata/seata-go/pkg/protocol/transaction" | |||||
| ) | |||||
| import ( | |||||
| "vimagination.zapto.org/byteio" | |||||
| ) | |||||
| // TODO 待重构 | |||||
| func AbstractResultMessageDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.AbstractResultMessage{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| resultCode, _ := r.ReadByte() | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| totalReadN += 1 | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Msg, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func MergedWarpMessageDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| size16 int16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| result := message.MergedWarpMessage{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| r.ReadInt32() | |||||
| totalReadN += 4 | |||||
| size16, readN, _ = r.ReadInt16() | |||||
| totalReadN += readN | |||||
| result.Msgs = make([]message.MessageTypeAware, 0) | |||||
| for index := 0; index < int(size16); index++ { | |||||
| typeCode, _, _ := r.ReadInt16() | |||||
| totalReadN += 2 | |||||
| decoder := getMessageDecoder(message.MessageType(typeCode)) | |||||
| if decoder != nil { | |||||
| msg, readN := decoder(in[totalReadN:]) | |||||
| totalReadN += readN | |||||
| result.Msgs = append(result.Msgs, msg.(message.MessageTypeAware)) | |||||
| } | |||||
| } | |||||
| return result, totalReadN | |||||
| } | |||||
| func MergeResultMessageDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| size16 int16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| result := message.MergeResultMessage{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| r.ReadInt32() | |||||
| totalReadN += 4 | |||||
| size16, readN, _ = r.ReadInt16() | |||||
| totalReadN += readN | |||||
| result.Msgs = make([]message.MessageTypeAware, 0) | |||||
| for index := 0; index < int(size16); index++ { | |||||
| typeCode, _, _ := r.ReadInt16() | |||||
| totalReadN += 2 | |||||
| decoder := getMessageDecoder(message.MessageType(typeCode)) | |||||
| if decoder != nil { | |||||
| msg, readN := decoder(in[totalReadN:]) | |||||
| totalReadN += readN | |||||
| result.Msgs = append(result.Msgs, msg.(message.MessageTypeAware)) | |||||
| } | |||||
| } | |||||
| return result, totalReadN | |||||
| } | |||||
| func AbstractIdentifyRequestDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.AbstractIdentifyRequest{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Version, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ApplicationId, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.TransactionServiceGroup, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ExtraData = make([]byte, int(length16)) | |||||
| readN, _ := r.Read(msg.ExtraData) | |||||
| totalReadN += readN | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func AbstractIdentifyResponseDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.AbstractIdentifyResponse{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| identified, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| if identified == byte(1) { | |||||
| msg.Identified = true | |||||
| } else if identified == byte(0) { | |||||
| msg.Identified = false | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Version, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func RegisterRMRequestDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length32 uint32 = 0 | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.RegisterRMRequest{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Version, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ApplicationId, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.TransactionServiceGroup, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ExtraData = make([]byte, int(length16)) | |||||
| readN, _ := r.Read(msg.ExtraData) | |||||
| totalReadN += readN | |||||
| } | |||||
| length32, readN, _ = r.ReadUint32() | |||||
| totalReadN += readN | |||||
| if length32 > 0 { | |||||
| msg.ResourceIds, readN, _ = r.ReadString(int(length32)) | |||||
| totalReadN += readN | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func RegisterRMResponseDecoder(in []byte) (interface{}, int) { | |||||
| resp, totalReadN := AbstractIdentifyResponseDecoder(in) | |||||
| abstractIdentifyResponse := resp.(message.AbstractIdentifyResponse) | |||||
| msg := message.RegisterRMResponse{AbstractIdentifyResponse: abstractIdentifyResponse} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func RegisterTMRequestDecoder(in []byte) (interface{}, int) { | |||||
| req, totalReadN := AbstractIdentifyRequestDecoder(in) | |||||
| abstractIdentifyRequest := req.(message.AbstractIdentifyRequest) | |||||
| msg := message.RegisterTMRequest{AbstractIdentifyRequest: abstractIdentifyRequest} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func RegisterTMResponseDecoder(in []byte) (interface{}, int) { | |||||
| resp, totalReadN := AbstractIdentifyResponseDecoder(in) | |||||
| abstractIdentifyResponse := resp.(message.AbstractIdentifyResponse) | |||||
| msg := message.RegisterRMResponse{AbstractIdentifyResponse: abstractIdentifyResponse} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func AbstractTransactionResponseDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.AbstractTransactionResponse{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| resultCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Msg, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| } | |||||
| exceptionCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.TransactionExceptionCode = transaction.TransactionExceptionCode(exceptionCode) | |||||
| return msg, totalReadN | |||||
| } | |||||
| func AbstractBranchEndRequestDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.AbstractBranchEndRequest{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Xid, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| msg.BranchId, _, _ = r.ReadInt64() | |||||
| totalReadN += 8 | |||||
| branchType, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.BranchType = model2.BranchType(branchType) | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ResourceId, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ApplicationData = make([]byte, int(length16)) | |||||
| readN, _ := r.Read(msg.ApplicationData) | |||||
| totalReadN += readN | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func AbstractBranchEndResponseDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.AbstractBranchEndResponse{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| resultCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Msg, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| } | |||||
| exceptionCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.TransactionExceptionCode = transaction.TransactionExceptionCode(exceptionCode) | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Xid, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| msg.BranchId, _, _ = r.ReadInt64() | |||||
| totalReadN += 8 | |||||
| branchStatus, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.BranchStatus = model2.BranchStatus(branchStatus) | |||||
| return msg, totalReadN | |||||
| } | |||||
| func AbstractGlobalEndRequestDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.AbstractGlobalEndRequest{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Xid, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ExtraData = make([]byte, int(length16)) | |||||
| readN, _ := r.Read(msg.ExtraData) | |||||
| totalReadN += readN | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func AbstractGlobalEndResponseDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.AbstractGlobalEndResponse{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| resultCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Msg, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| } | |||||
| exceptionCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.TransactionExceptionCode = transaction.TransactionExceptionCode(exceptionCode) | |||||
| globalStatus, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.GlobalStatus = transaction.GlobalStatus(globalStatus) | |||||
| return msg, totalReadN | |||||
| } | |||||
| func BranchCommitRequestDecoder(in []byte) (interface{}, int) { | |||||
| req, totalReadN := AbstractBranchEndRequestDecoder(in) | |||||
| abstractBranchEndRequest := req.(message.AbstractBranchEndRequest) | |||||
| msg := message.BranchCommitRequest{AbstractBranchEndRequest: abstractBranchEndRequest} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func BranchCommitResponseDecoder(in []byte) (interface{}, int) { | |||||
| resp, totalReadN := AbstractBranchEndResponseDecoder(in) | |||||
| abstractBranchEndResponse := resp.(message.AbstractBranchEndResponse) | |||||
| msg := message.BranchCommitResponse{AbstractBranchEndResponse: abstractBranchEndResponse} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func BranchRegisterRequestDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length32 uint32 = 0 | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.BranchRegisterRequest{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Xid, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| branchType, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.BranchType = model2.BranchType(branchType) | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ResourceId, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length32, readN, _ = r.ReadUint32() | |||||
| totalReadN += readN | |||||
| if length32 > 0 { | |||||
| msg.LockKey, readN, _ = r.ReadString(int(length32)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length32, readN, _ = r.ReadUint32() | |||||
| totalReadN += readN | |||||
| if length32 > 0 { | |||||
| msg.ApplicationData = make([]byte, int(length32)) | |||||
| readN, _ := r.Read(msg.ApplicationData) | |||||
| totalReadN += readN | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func BranchRegisterResponseDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.BranchRegisterResponse{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| resultCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Msg, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| } | |||||
| exceptionCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.TransactionExceptionCode = transaction.TransactionExceptionCode(exceptionCode) | |||||
| msg.BranchId, readN, _ = r.ReadInt64() | |||||
| totalReadN += readN | |||||
| return msg, totalReadN | |||||
| } | |||||
| func BranchReportRequestDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.BranchReportRequest{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Xid, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| msg.BranchId, _, _ = r.ReadInt64() | |||||
| branchStatus, _ := r.ReadByte() | |||||
| msg.Status = model2.BranchStatus(branchStatus) | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ResourceId, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ApplicationData = make([]byte, int(length16)) | |||||
| readN, _ := r.Read(msg.ApplicationData) | |||||
| totalReadN += readN | |||||
| } | |||||
| branchType, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.BranchType = model2.BranchType(branchType) | |||||
| return msg, totalReadN | |||||
| } | |||||
| func BranchReportResponseDecoder(in []byte) (interface{}, int) { | |||||
| resp, totalReadN := AbstractTransactionResponseDecoder(in) | |||||
| abstractTransactionResponse := resp.(message.AbstractTransactionResponse) | |||||
| msg := message.BranchReportResponse{AbstractTransactionResponse: abstractTransactionResponse} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func BranchRollbackRequestDecoder(in []byte) (interface{}, int) { | |||||
| req, totalReadN := AbstractBranchEndRequestDecoder(in) | |||||
| abstractBranchEndRequest := req.(message.AbstractBranchEndRequest) | |||||
| msg := message.BranchRollbackRequest{AbstractBranchEndRequest: abstractBranchEndRequest} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func BranchRollbackResponseDecoder(in []byte) (interface{}, int) { | |||||
| resp, totalReadN := AbstractBranchEndResponseDecoder(in) | |||||
| abstractBranchEndResponse := resp.(message.AbstractBranchEndResponse) | |||||
| msg := message.BranchRollbackResponse{AbstractBranchEndResponse: abstractBranchEndResponse} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalBeginRequestDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.GlobalBeginRequest{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| timeout, readN, _ := r.ReadInt32() | |||||
| totalReadN += readN | |||||
| msg.Timeout = timeout | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.TransactionName, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalBeginResponseDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.GlobalBeginResponse{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| resultCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Msg, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| } | |||||
| exceptionCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.TransactionExceptionCode = transaction.TransactionExceptionCode(exceptionCode) | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Xid, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ExtraData = make([]byte, int(length16)) | |||||
| readN, _ := r.Read(msg.ExtraData) | |||||
| totalReadN += readN | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalCommitRequestDecoder(in []byte) (interface{}, int) { | |||||
| req, totalReadN := AbstractGlobalEndRequestDecoder(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndRequest) | |||||
| msg := message.GlobalCommitRequest{AbstractGlobalEndRequest: abstractGlobalEndRequest} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalCommitResponseDecoder(in []byte) (interface{}, int) { | |||||
| resp, totalReadN := AbstractGlobalEndResponseDecoder(in) | |||||
| abstractGlobalEndResponse := resp.(message.AbstractGlobalEndResponse) | |||||
| msg := message.GlobalCommitResponse{AbstractGlobalEndResponse: abstractGlobalEndResponse} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalLockQueryRequestDecoder(in []byte) (interface{}, int) { | |||||
| req, totalReadN := BranchRegisterRequestDecoder(in) | |||||
| branchRegisterRequest := req.(message.BranchRegisterRequest) | |||||
| msg := message.GlobalLockQueryRequest{BranchRegisterRequest: branchRegisterRequest} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalLockQueryResponseDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.GlobalLockQueryResponse{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| resultCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.ResultCode = message.ResultCode(resultCode) | |||||
| if msg.ResultCode == message.ResultCodeFailed { | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Msg, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| } | |||||
| exceptionCode, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.TransactionExceptionCode = transaction.TransactionExceptionCode(exceptionCode) | |||||
| lockable, readN, _ := r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if lockable == uint16(1) { | |||||
| msg.Lockable = true | |||||
| } else if lockable == uint16(0) { | |||||
| msg.Lockable = false | |||||
| } | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalReportRequestDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.GlobalReportRequest{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.Xid, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ExtraData = make([]byte, int(length16)) | |||||
| readN, _ := r.Read(msg.ExtraData) | |||||
| totalReadN += readN | |||||
| } | |||||
| globalStatus, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.GlobalStatus = transaction.GlobalStatus(globalStatus) | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalReportResponseDecoder(in []byte) (interface{}, int) { | |||||
| resp, totalReadN := AbstractGlobalEndResponseDecoder(in) | |||||
| abstractGlobalEndResponse := resp.(message.AbstractGlobalEndResponse) | |||||
| msg := message.GlobalReportResponse{AbstractGlobalEndResponse: abstractGlobalEndResponse} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalRollbackRequestDecoder(in []byte) (interface{}, int) { | |||||
| req, totalReadN := AbstractGlobalEndRequestDecoder(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndRequest) | |||||
| msg := message.GlobalRollbackRequest{AbstractGlobalEndRequest: abstractGlobalEndRequest} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalRollbackResponseDecoder(in []byte) (interface{}, int) { | |||||
| resp, totalReadN := AbstractGlobalEndResponseDecoder(in) | |||||
| abstractGlobalEndResponse := resp.(message.AbstractGlobalEndResponse) | |||||
| msg := message.GlobalRollbackResponse{AbstractGlobalEndResponse: abstractGlobalEndResponse} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalStatusRequestDecoder(in []byte) (interface{}, int) { | |||||
| req, totalReadN := AbstractGlobalEndRequestDecoder(in) | |||||
| abstractGlobalEndRequest := req.(message.AbstractGlobalEndRequest) | |||||
| msg := message.GlobalStatusRequest{AbstractGlobalEndRequest: abstractGlobalEndRequest} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func GlobalStatusResponseDecoder(in []byte) (interface{}, int) { | |||||
| resp, totalReadN := AbstractGlobalEndResponseDecoder(in) | |||||
| abstractGlobalEndResponse := resp.(message.AbstractGlobalEndResponse) | |||||
| msg := message.GlobalStatusResponse{AbstractGlobalEndResponse: abstractGlobalEndResponse} | |||||
| return msg, totalReadN | |||||
| } | |||||
| func UndoLogDeleteRequestDecoder(in []byte) (interface{}, int) { | |||||
| var ( | |||||
| length16 uint16 = 0 | |||||
| readN = 0 | |||||
| totalReadN = 0 | |||||
| ) | |||||
| msg := message.UndoLogDeleteRequest{} | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(in)} | |||||
| branchType, _ := r.ReadByte() | |||||
| totalReadN += 1 | |||||
| msg.BranchType = model2.BranchType(branchType) | |||||
| length16, readN, _ = r.ReadUint16() | |||||
| totalReadN += readN | |||||
| if length16 > 0 { | |||||
| msg.ResourceId, readN, _ = r.ReadString(int(length16)) | |||||
| totalReadN += readN | |||||
| } | |||||
| day, readN, _ := r.ReadInt16() | |||||
| msg.SaveDays = message.MessageType(day) | |||||
| totalReadN += readN | |||||
| return msg, totalReadN | |||||
| } | |||||
| @@ -1,563 +0,0 @@ | |||||
| package codec | |||||
| import ( | |||||
| "bytes" | |||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| import ( | |||||
| "vimagination.zapto.org/byteio" | |||||
| ) | |||||
| // TODO 待重构 | |||||
| func AbstractResultMessageEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| msgs := in.(message.AbstractResultMessage) | |||||
| w.WriteByte(byte(msgs.ResultCode)) | |||||
| if msgs.ResultCode == message.ResultCodeFailed { | |||||
| var msg string | |||||
| if msgs.Msg != "" { | |||||
| if len(msgs.Msg) > 128 { | |||||
| msg = msgs.Msg[:128] | |||||
| } else { | |||||
| msg = msgs.Msg | |||||
| } | |||||
| // 暂时不考虑 msg.Msg 包含中文的情况,这样字符串的长度就是 byte 数组的长度 | |||||
| w.WriteInt16(int16(len(msg))) | |||||
| w.WriteString(msg) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| } | |||||
| return b.Bytes() | |||||
| } | |||||
| func MergedWarpMessageEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| b bytes.Buffer | |||||
| result = make([]byte, 0) | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| req, _ := in.(message.MergedWarpMessage) | |||||
| w.WriteInt16(int16(len(req.Msgs))) | |||||
| for _, msg := range req.Msgs { | |||||
| encoder := getMessageEncoder(msg.GetTypeCode()) | |||||
| if encoder != nil { | |||||
| data := encoder(msg) | |||||
| w.WriteInt16(int16(msg.GetTypeCode())) | |||||
| w.Write(data) | |||||
| } | |||||
| } | |||||
| size := uint32(b.Len()) | |||||
| result = append(result, []byte{byte(size >> 24), byte(size >> 16), byte(size >> 8), byte(size)}...) | |||||
| result = append(result, b.Bytes()...) | |||||
| if len(req.Msgs) > 20 { | |||||
| log.Debugf("msg in one packet: %s ,buffer size: %s", len(req.Msgs), size) | |||||
| } | |||||
| return result | |||||
| } | |||||
| func MergeResultMessageEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| b bytes.Buffer | |||||
| result = make([]byte, 0) | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| req, _ := in.(message.MergeResultMessage) | |||||
| w.WriteInt16(int16(len(req.Msgs))) | |||||
| for _, msg := range req.Msgs { | |||||
| encoder := getMessageEncoder(msg.GetTypeCode()) | |||||
| if encoder != nil { | |||||
| data := encoder(msg) | |||||
| w.WriteInt16(int16(msg.GetTypeCode())) | |||||
| w.Write(data) | |||||
| } | |||||
| } | |||||
| size := uint32(b.Len()) | |||||
| result = append(result, []byte{byte(size >> 24), byte(size >> 16), byte(size >> 8), byte(size)}...) | |||||
| result = append(result, b.Bytes()...) | |||||
| if len(req.Msgs) > 20 { | |||||
| log.Debugf("msg in one packet: %s ,buffer size: %s", len(req.Msgs), size) | |||||
| } | |||||
| return result | |||||
| } | |||||
| func AbstractIdentifyRequestEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| req := in.(message.AbstractIdentifyRequest) | |||||
| if req.Version != "" { | |||||
| w.WriteInt16(int16(len(req.Version))) | |||||
| w.WriteString(req.Version) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| if req.ApplicationId != "" { | |||||
| w.WriteInt16(int16(len(req.ApplicationId))) | |||||
| w.WriteString(req.ApplicationId) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| if req.TransactionServiceGroup != "" { | |||||
| w.WriteInt16(int16(len(req.TransactionServiceGroup))) | |||||
| w.WriteString(req.TransactionServiceGroup) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| if req.ExtraData != nil { | |||||
| w.WriteUint16(uint16(len(req.ExtraData))) | |||||
| w.Write(req.ExtraData) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| return b.Bytes() | |||||
| } | |||||
| func AbstractIdentifyResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.AbstractIdentifyResponse) | |||||
| var ( | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| if resp.Identified { | |||||
| w.WriteByte(byte(1)) | |||||
| } else { | |||||
| w.WriteByte(byte(0)) | |||||
| } | |||||
| if resp.Version != "" { | |||||
| w.WriteInt16(int16(len(resp.Version))) | |||||
| w.WriteString(resp.Version) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| return b.Bytes() | |||||
| } | |||||
| func RegisterRMRequestEncoder(in interface{}) []byte { | |||||
| req := in.(message.RegisterRMRequest) | |||||
| data := AbstractIdentifyRequestEncoder(req.AbstractIdentifyRequest) | |||||
| var ( | |||||
| zero32 int32 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| if req.ResourceIds != "" { | |||||
| w.WriteInt32(int32(len(req.ResourceIds))) | |||||
| w.WriteString(req.ResourceIds) | |||||
| } else { | |||||
| w.WriteInt32(zero32) | |||||
| } | |||||
| result := append(data, b.Bytes()...) | |||||
| return result | |||||
| } | |||||
| func RegisterRMResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.RegisterRMResponse) | |||||
| return AbstractIdentifyResponseEncoder(resp.AbstractIdentifyResponse) | |||||
| } | |||||
| func RegisterTMRequestEncoder(in interface{}) []byte { | |||||
| req := in.(message.RegisterTMRequest) | |||||
| return AbstractIdentifyRequestEncoder(req.AbstractIdentifyRequest) | |||||
| } | |||||
| func RegisterTMResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.RegisterTMResponse) | |||||
| return AbstractIdentifyResponseEncoder(resp.AbstractIdentifyResponse) | |||||
| } | |||||
| func AbstractTransactionResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.AbstractTransactionResponse) | |||||
| data := AbstractResultMessageEncoder(resp.AbstractResultMessage) | |||||
| result := append(data, byte(resp.TransactionExceptionCode)) | |||||
| return result | |||||
| } | |||||
| func AbstractBranchEndRequestEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| zero32 int32 = 0 | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| req, _ := in.(message.AbstractBranchEndRequest) | |||||
| if req.Xid != "" { | |||||
| w.WriteInt16(int16(len(req.Xid))) | |||||
| w.WriteString(req.Xid) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| w.WriteInt64(req.BranchId) | |||||
| w.WriteByte(byte(req.BranchType)) | |||||
| if req.ResourceId != "" { | |||||
| w.WriteInt16(int16(len(req.ResourceId))) | |||||
| w.WriteString(req.ResourceId) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| if req.ApplicationData != nil { | |||||
| w.WriteUint32(uint32(len(req.ApplicationData))) | |||||
| w.Write(req.ApplicationData) | |||||
| } else { | |||||
| w.WriteInt32(zero32) | |||||
| } | |||||
| return b.Bytes() | |||||
| } | |||||
| func AbstractBranchEndResponseEncoder(in interface{}) []byte { | |||||
| resp, _ := in.(message.AbstractBranchEndResponse) | |||||
| data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse) | |||||
| var ( | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| if resp.Xid != "" { | |||||
| w.WriteInt16(int16(len(resp.Xid))) | |||||
| w.WriteString(resp.Xid) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| w.WriteInt64(resp.BranchId) | |||||
| w.WriteByte(byte(resp.BranchStatus)) | |||||
| result := append(data, b.Bytes()...) | |||||
| return result | |||||
| } | |||||
| func AbstractGlobalEndRequestEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| req, _ := in.(message.AbstractGlobalEndRequest) | |||||
| if req.Xid != "" { | |||||
| w.WriteInt16(int16(len(req.Xid))) | |||||
| w.WriteString(req.Xid) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| if req.ExtraData != nil { | |||||
| w.WriteUint16(uint16(len(req.ExtraData))) | |||||
| w.Write(req.ExtraData) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| return b.Bytes() | |||||
| } | |||||
| func AbstractGlobalEndResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.AbstractGlobalEndResponse) | |||||
| data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse) | |||||
| result := append(data, byte(resp.GlobalStatus)) | |||||
| return result | |||||
| } | |||||
| func BranchCommitRequestEncoder(in interface{}) []byte { | |||||
| req := in.(message.BranchCommitRequest) | |||||
| return AbstractBranchEndRequestEncoder(req.AbstractBranchEndRequest) | |||||
| } | |||||
| func BranchCommitResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.BranchCommitResponse) | |||||
| return AbstractBranchEndResponseEncoder(resp.AbstractBranchEndResponse) | |||||
| } | |||||
| func BranchRegisterRequestEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| zero32 int32 = 0 | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| req, _ := in.(message.BranchRegisterRequest) | |||||
| if req.Xid != "" { | |||||
| w.WriteInt16(int16(len(req.Xid))) | |||||
| w.WriteString(req.Xid) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| w.WriteByte(byte(req.BranchType)) | |||||
| if req.ResourceId != "" { | |||||
| w.WriteInt16(int16(len(req.ResourceId))) | |||||
| w.WriteString(req.ResourceId) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| if req.LockKey != "" { | |||||
| w.WriteInt32(int32(len(req.LockKey))) | |||||
| w.WriteString(req.LockKey) | |||||
| } else { | |||||
| w.WriteInt32(zero32) | |||||
| } | |||||
| if req.ApplicationData != nil { | |||||
| w.WriteUint32(uint32(len(req.ApplicationData))) | |||||
| w.Write(req.ApplicationData) | |||||
| } else { | |||||
| w.WriteInt32(zero32) | |||||
| } | |||||
| return b.Bytes() | |||||
| } | |||||
| func BranchRegisterResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.BranchRegisterResponse) | |||||
| data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse) | |||||
| c := uint64(resp.BranchId) | |||||
| branchIdBytes := []byte{ | |||||
| byte(c >> 56), | |||||
| byte(c >> 48), | |||||
| byte(c >> 40), | |||||
| byte(c >> 32), | |||||
| byte(c >> 24), | |||||
| byte(c >> 16), | |||||
| byte(c >> 8), | |||||
| byte(c), | |||||
| } | |||||
| result := append(data, branchIdBytes...) | |||||
| return result | |||||
| } | |||||
| func BranchReportRequestEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| zero32 int32 = 0 | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| req, _ := in.(message.BranchReportRequest) | |||||
| if req.Xid != "" { | |||||
| w.WriteInt16(int16(len(req.Xid))) | |||||
| w.WriteString(req.Xid) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| w.WriteInt64(req.BranchId) | |||||
| w.WriteByte(byte(req.Status)) | |||||
| if req.ResourceId != "" { | |||||
| w.WriteInt16(int16(len(req.ResourceId))) | |||||
| w.WriteString(req.ResourceId) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| if req.ApplicationData != nil { | |||||
| w.WriteUint32(uint32(len(req.ApplicationData))) | |||||
| w.Write(req.ApplicationData) | |||||
| } else { | |||||
| w.WriteInt32(zero32) | |||||
| } | |||||
| w.WriteByte(byte(req.BranchType)) | |||||
| return b.Bytes() | |||||
| } | |||||
| func BranchReportResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.BranchReportResponse) | |||||
| return AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse) | |||||
| } | |||||
| func BranchRollbackRequestEncoder(in interface{}) []byte { | |||||
| req := in.(message.BranchRollbackRequest) | |||||
| return AbstractBranchEndRequestEncoder(req.AbstractBranchEndRequest) | |||||
| } | |||||
| func BranchRollbackResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.BranchRollbackResponse) | |||||
| return AbstractBranchEndResponseEncoder(resp.AbstractBranchEndResponse) | |||||
| } | |||||
| func GlobalBeginRequestEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| req, _ := in.(message.GlobalBeginRequest) | |||||
| w.WriteInt32(req.Timeout) | |||||
| if req.TransactionName != "" { | |||||
| w.WriteInt16(int16(len(req.TransactionName))) | |||||
| w.WriteString(req.TransactionName) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| return b.Bytes() | |||||
| } | |||||
| func GlobalBeginResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.GlobalBeginResponse) | |||||
| data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse) | |||||
| var ( | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| if resp.Xid != "" { | |||||
| w.WriteInt16(int16(len(resp.Xid))) | |||||
| w.WriteString(resp.Xid) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| if resp.ExtraData != nil { | |||||
| w.WriteUint16(uint16(len(resp.ExtraData))) | |||||
| w.Write(resp.ExtraData) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| result := append(data, b.Bytes()...) | |||||
| return result | |||||
| } | |||||
| func GlobalCommitRequestEncoder(in interface{}) []byte { | |||||
| req := in.(message.GlobalCommitRequest) | |||||
| return AbstractGlobalEndRequestEncoder(req.AbstractGlobalEndRequest) | |||||
| } | |||||
| func GlobalCommitResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.GlobalCommitResponse) | |||||
| return AbstractGlobalEndResponseEncoder(resp.AbstractGlobalEndResponse) | |||||
| } | |||||
| func GlobalLockQueryRequestEncoder(in interface{}) []byte { | |||||
| return BranchRegisterRequestEncoder(in) | |||||
| } | |||||
| func GlobalLockQueryResponseEncoder(in interface{}) []byte { | |||||
| resp, _ := in.(message.GlobalLockQueryResponse) | |||||
| data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse) | |||||
| var result []byte | |||||
| if resp.Lockable { | |||||
| result = append(data, byte(0), byte(1)) | |||||
| } else { | |||||
| result = append(data, byte(0), byte(0)) | |||||
| } | |||||
| return result | |||||
| } | |||||
| func GlobalReportRequestEncoder(in interface{}) []byte { | |||||
| req, _ := in.(message.GlobalReportRequest) | |||||
| data := AbstractGlobalEndRequestEncoder(req.AbstractGlobalEndRequest) | |||||
| result := append(data, byte(req.GlobalStatus)) | |||||
| return result | |||||
| } | |||||
| func GlobalReportResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.GlobalReportResponse) | |||||
| return AbstractGlobalEndResponseEncoder(resp.AbstractGlobalEndResponse) | |||||
| } | |||||
| func GlobalRollbackRequestEncoder(in interface{}) []byte { | |||||
| req := in.(message.GlobalRollbackRequest) | |||||
| return AbstractGlobalEndRequestEncoder(req.AbstractGlobalEndRequest) | |||||
| } | |||||
| func GlobalRollbackResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.GlobalRollbackResponse) | |||||
| return AbstractGlobalEndResponseEncoder(resp.AbstractGlobalEndResponse) | |||||
| } | |||||
| func GlobalStatusRequestEncoder(in interface{}) []byte { | |||||
| req := in.(message.GlobalStatusRequest) | |||||
| return AbstractGlobalEndRequestEncoder(req.AbstractGlobalEndRequest) | |||||
| } | |||||
| func GlobalStatusResponseEncoder(in interface{}) []byte { | |||||
| resp := in.(message.GlobalStatusResponse) | |||||
| return AbstractGlobalEndResponseEncoder(resp.AbstractGlobalEndResponse) | |||||
| } | |||||
| func UndoLogDeleteRequestEncoder(in interface{}) []byte { | |||||
| var ( | |||||
| zero16 int16 = 0 | |||||
| b bytes.Buffer | |||||
| ) | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| req, _ := in.(message.UndoLogDeleteRequest) | |||||
| w.WriteByte(byte(req.BranchType)) | |||||
| if req.ResourceId != "" { | |||||
| w.WriteInt16(int16(len(req.ResourceId))) | |||||
| w.WriteString(req.ResourceId) | |||||
| } else { | |||||
| w.WriteInt16(zero16) | |||||
| } | |||||
| w.WriteInt16(int16(req.SaveDays)) | |||||
| return b.Bytes() | |||||
| } | |||||
| @@ -6,6 +6,7 @@ import ( | |||||
| ) | ) | ||||
| type AbstractBranchEndRequest struct { | type AbstractBranchEndRequest struct { | ||||
| MessageTypeAware | |||||
| Xid string | Xid string | ||||
| BranchId int64 | BranchId int64 | ||||
| BranchType model2.BranchType | BranchType model2.BranchType | ||||
| @@ -2,10 +2,13 @@ package resource | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "github.com/seata/seata-go/pkg/protocol/branch" | |||||
| "sync" | "sync" | ||||
| ) | ) | ||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/branch" | |||||
| ) | |||||
| // Resource that can be managed by Resource Manager and involved into global transaction | // Resource that can be managed by Resource Manager and involved into global transaction | ||||
| type Resource interface { | type Resource interface { | ||||
| GetResourceGroupId() string | GetResourceGroupId() string | ||||
| @@ -1,22 +1,58 @@ | |||||
| package transaction | |||||
| package seatactx | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common" | "github.com/seata/seata-go/pkg/common" | ||||
| "github.com/seata/seata-go/pkg/protocol/transaction" | |||||
| "github.com/seata/seata-go/pkg/rm/tcc/api" | "github.com/seata/seata-go/pkg/rm/tcc/api" | ||||
| ) | ) | ||||
| type ContextVariable struct { | type ContextVariable struct { | ||||
| TxName string | |||||
| Xid string | Xid string | ||||
| Status *GlobalStatus | |||||
| Role *GlobalTransactionRole | |||||
| Status *transaction.GlobalStatus | |||||
| TxRole *transaction.GlobalTransactionRole | |||||
| BusinessActionContext *api.BusinessActionContext | BusinessActionContext *api.BusinessActionContext | ||||
| TxStatus *transaction.GlobalStatus | |||||
| } | } | ||||
| func InitSeataContext(ctx context.Context) context.Context { | func InitSeataContext(ctx context.Context) context.Context { | ||||
| return context.WithValue(ctx, common.CONTEXT_VARIABLE, &ContextVariable{}) | return context.WithValue(ctx, common.CONTEXT_VARIABLE, &ContextVariable{}) | ||||
| } | } | ||||
| func GetTxStatus(ctx context.Context) *transaction.GlobalStatus { | |||||
| variable := ctx.Value(common.CONTEXT_VARIABLE) | |||||
| if variable == nil { | |||||
| return nil | |||||
| } | |||||
| return variable.(*ContextVariable).TxStatus | |||||
| } | |||||
| func SetTxStatus(ctx context.Context, status transaction.GlobalStatus) { | |||||
| variable := ctx.Value(common.CONTEXT_VARIABLE) | |||||
| if variable != nil { | |||||
| variable.(*ContextVariable).TxStatus = &status | |||||
| } | |||||
| } | |||||
| func GetTxName(ctx context.Context) string { | |||||
| variable := ctx.Value(common.CONTEXT_VARIABLE) | |||||
| if variable == nil { | |||||
| return "" | |||||
| } | |||||
| return variable.(*ContextVariable).TxName | |||||
| } | |||||
| func SetTxName(ctx context.Context, name string) { | |||||
| variable := ctx.Value(common.TccBusinessActionContext) | |||||
| if variable != nil { | |||||
| variable.(*ContextVariable).TxName = name | |||||
| } | |||||
| } | |||||
| func IsSeataContext(ctx context.Context) bool { | func IsSeataContext(ctx context.Context) bool { | ||||
| return ctx.Value(common.CONTEXT_VARIABLE) != nil | return ctx.Value(common.CONTEXT_VARIABLE) != nil | ||||
| } | } | ||||
| @@ -36,18 +72,18 @@ func SetBusinessActionContext(ctx context.Context, businessActionContext *api.Bu | |||||
| } | } | ||||
| } | } | ||||
| func GetTransactionRole(ctx context.Context) *GlobalTransactionRole { | |||||
| func GetTransactionRole(ctx context.Context) *transaction.GlobalTransactionRole { | |||||
| variable := ctx.Value(common.CONTEXT_VARIABLE) | variable := ctx.Value(common.CONTEXT_VARIABLE) | ||||
| if variable == nil { | if variable == nil { | ||||
| return nil | return nil | ||||
| } | } | ||||
| return variable.(*ContextVariable).Role | |||||
| return variable.(*ContextVariable).TxRole | |||||
| } | } | ||||
| func SetTransactionRole(ctx context.Context, role GlobalTransactionRole) { | |||||
| func SetTransactionRole(ctx context.Context, role transaction.GlobalTransactionRole) { | |||||
| variable := ctx.Value(common.CONTEXT_VARIABLE) | variable := ctx.Value(common.CONTEXT_VARIABLE) | ||||
| if variable != nil { | if variable != nil { | ||||
| variable.(*ContextVariable).Role = &role | |||||
| variable.(*ContextVariable).TxRole = &role | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,81 @@ | |||||
| package api | |||||
| import ( | |||||
| "context" | |||||
| "fmt" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/protocol/seatactx" | |||||
| "github.com/seata/seata-go/pkg/protocol/transaction" | |||||
| "github.com/seata/seata-go/pkg/protocol/transaction/manager" | |||||
| ) | |||||
| type TransactionalExecutor interface { | |||||
| Execute(ctx context.Context, param interface{}) (interface{}, error) | |||||
| GetTransactionInfo() transaction.TransactionInfo | |||||
| } | |||||
| func Begin(ctx context.Context, name string) context.Context { | |||||
| if !seatactx.IsSeataContext(ctx) { | |||||
| ctx = seatactx.InitSeataContext(ctx) | |||||
| } | |||||
| seatactx.SetTxName(ctx, name) | |||||
| if seatactx.GetTransactionRole(ctx) == nil { | |||||
| seatactx.SetTransactionRole(ctx, transaction.LAUNCHER) | |||||
| } | |||||
| var tx *manager.GlobalTransaction | |||||
| if seatactx.HasXID(ctx) { | |||||
| tx = &manager.GlobalTransaction{ | |||||
| Xid: seatactx.GetXID(ctx), | |||||
| Status: transaction.GlobalStatusBegin, | |||||
| Role: transaction.PARTICIPANT, | |||||
| } | |||||
| seatactx.SetTxStatus(ctx, transaction.GlobalStatusBegin) | |||||
| } | |||||
| // todo: Handle the transaction propagation. | |||||
| if tx == nil { | |||||
| tx = &manager.GlobalTransaction{ | |||||
| Xid: seatactx.GetXID(ctx), | |||||
| Status: transaction.GlobalStatusUnKnown, | |||||
| Role: transaction.LAUNCHER, | |||||
| } | |||||
| seatactx.SetTxStatus(ctx, transaction.GlobalStatusUnKnown) | |||||
| } | |||||
| // todo timeout should read from config | |||||
| err := manager.GetGlobalTransactionManager().Begin(ctx, tx, 50, name) | |||||
| if err != nil { | |||||
| panic(fmt.Sprintf("transactionTemplate: begin transaction failed, error %v", err)) | |||||
| } | |||||
| return ctx | |||||
| } | |||||
| // commit global transaction | |||||
| func CommitOrRollback(ctx context.Context, err error) error { | |||||
| tx := &manager.GlobalTransaction{ | |||||
| Xid: seatactx.GetXID(ctx), | |||||
| Status: *seatactx.GetTxStatus(ctx), | |||||
| Role: *seatactx.GetTransactionRole(ctx), | |||||
| } | |||||
| var resp error | |||||
| if err == nil { | |||||
| resp = manager.GetGlobalTransactionManager().Commit(ctx, tx) | |||||
| if resp != nil { | |||||
| log.Infof("transactionTemplate: commit transaction failed, error %v", err) | |||||
| } | |||||
| } else { | |||||
| resp = manager.GetGlobalTransactionManager().Rollback(ctx, tx) | |||||
| if resp != nil { | |||||
| log.Infof("transactionTemplate: Rollback transaction failed, error %v", err) | |||||
| } | |||||
| } | |||||
| return resp | |||||
| } | |||||
| @@ -1,96 +0,0 @@ | |||||
| package executor | |||||
| import ( | |||||
| "context" | |||||
| "github.com/pkg/errors" | |||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/protocol/transaction" | |||||
| "github.com/seata/seata-go/pkg/protocol/transaction/manager" | |||||
| "sync" | |||||
| ) | |||||
| type TransactionalExecutor interface { | |||||
| Execute(ctx context.Context, param interface{}) (interface{}, error) | |||||
| GetTransactionInfo() transaction.TransactionInfo | |||||
| } | |||||
| var ( | |||||
| transactionTemplate *TransactionTemplate | |||||
| onceTransactionTemplate = &sync.Once{} | |||||
| ) | |||||
| func GetTransactionTemplate() *TransactionTemplate { | |||||
| if transactionTemplate == nil { | |||||
| onceTransactionTemplate.Do(func() { | |||||
| transactionTemplate = &TransactionTemplate{} | |||||
| }) | |||||
| } | |||||
| return transactionTemplate | |||||
| } | |||||
| type TransactionTemplate struct { | |||||
| } | |||||
| func (t *TransactionTemplate) Execute(ctx context.Context, business TransactionalExecutor, param interface{}) (interface{}, error) { | |||||
| if !transaction.IsSeataContext(ctx) { | |||||
| err := errors.New("context should be inited as seata context!") | |||||
| log.Error(err) | |||||
| return nil, err | |||||
| } | |||||
| if transaction.GetTransactionRole(ctx) == nil { | |||||
| transaction.SetTransactionRole(ctx, transaction.LAUNCHER) | |||||
| } | |||||
| var tx *manager.GlobalTransaction | |||||
| if transaction.HasXID(ctx) { | |||||
| tx = &manager.GlobalTransaction{ | |||||
| Xid: transaction.GetXID(ctx), | |||||
| Status: transaction.Begin, | |||||
| Role: transaction.PARTICIPANT, | |||||
| } | |||||
| } | |||||
| // todo: Handle the transaction propagation. | |||||
| if tx == nil { | |||||
| tx = &manager.GlobalTransaction{ | |||||
| Xid: transaction.GetXID(ctx), | |||||
| Status: transaction.UnKnown, | |||||
| Role: transaction.LAUNCHER, | |||||
| } | |||||
| } | |||||
| // todo: set current tx config to holder | |||||
| // begin global transaction | |||||
| err := t.BeginTransaction(ctx, tx, business.GetTransactionInfo().TimeOut, business.GetTransactionInfo().Name) | |||||
| if err != nil { | |||||
| log.Infof("transactionTemplate: begin transaction failed, error %v", err) | |||||
| return nil, err | |||||
| } | |||||
| // do your business | |||||
| res, err := business.Execute(ctx, param) | |||||
| if err != nil { | |||||
| log.Infof("transactionTemplate: execute business failed, error %v", err) | |||||
| return nil, manager.GetGlobalTransactionManager().Rollback(ctx, tx) | |||||
| } | |||||
| // commit global transaction | |||||
| err = t.CommitTransaction(ctx, tx) | |||||
| if err != nil { | |||||
| log.Infof("transactionTemplate: commit transaction failed, error %v", err) | |||||
| // rollback transaction | |||||
| return nil, manager.GetGlobalTransactionManager().Rollback(ctx, tx) | |||||
| } | |||||
| return res, err | |||||
| } | |||||
| func (TransactionTemplate) BeginTransaction(ctx context.Context, tx *manager.GlobalTransaction, timeout int32, name string) error { | |||||
| return manager.GetGlobalTransactionManager().Begin(ctx, tx, timeout, name) | |||||
| } | |||||
| func (TransactionTemplate) CommitTransaction(ctx context.Context, tx *manager.GlobalTransaction) error { | |||||
| return manager.GetGlobalTransactionManager().Commit(ctx, tx) | |||||
| } | |||||
| @@ -3,13 +3,20 @@ package manager | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "fmt" | "fmt" | ||||
| "sync" | |||||
| ) | |||||
| import ( | |||||
| "github.com/pkg/errors" | "github.com/pkg/errors" | ||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| "github.com/seata/seata-go/pkg/protocol/seatactx" | |||||
| "github.com/seata/seata-go/pkg/protocol/transaction" | "github.com/seata/seata-go/pkg/protocol/transaction" | ||||
| "github.com/seata/seata-go/pkg/remoting/getty" | "github.com/seata/seata-go/pkg/remoting/getty" | ||||
| "github.com/seata/seata-go/pkg/tm/api" | "github.com/seata/seata-go/pkg/tm/api" | ||||
| "sync" | |||||
| ) | ) | ||||
| type GlobalTransaction struct { | type GlobalTransaction struct { | ||||
| @@ -39,7 +46,7 @@ type GlobalTransactionManager struct { | |||||
| // Begin a new global transaction with given timeout and given name. | // Begin a new global transaction with given timeout and given name. | ||||
| func (g *GlobalTransactionManager) Begin(ctx context.Context, gtr *GlobalTransaction, timeout int32, name string) error { | func (g *GlobalTransactionManager) Begin(ctx context.Context, gtr *GlobalTransaction, timeout int32, name string) error { | ||||
| if gtr.Role != transaction.LAUNCHER { | if gtr.Role != transaction.LAUNCHER { | ||||
| log.Infof("Ignore Begin(): just involved in global transaction %s", gtr.Xid) | |||||
| log.Infof("Ignore GlobalStatusBegin(): just involved in global transaction %s", gtr.Xid) | |||||
| return nil | return nil | ||||
| } | } | ||||
| if gtr.Xid != "" { | if gtr.Xid != "" { | ||||
| @@ -61,9 +68,9 @@ func (g *GlobalTransactionManager) Begin(ctx context.Context, gtr *GlobalTransac | |||||
| } | } | ||||
| log.Infof("GlobalBeginRequest success, xid %s, res %v", gtr.Xid, res) | log.Infof("GlobalBeginRequest success, xid %s, res %v", gtr.Xid, res) | ||||
| gtr.Status = transaction.Begin | |||||
| gtr.Status = transaction.GlobalStatusBegin | |||||
| gtr.Xid = res.(message.GlobalBeginResponse).Xid | gtr.Xid = res.(message.GlobalBeginResponse).Xid | ||||
| transaction.SetXID(ctx, res.(message.GlobalBeginResponse).Xid) | |||||
| seatactx.SetXID(ctx, res.(message.GlobalBeginResponse).Xid) | |||||
| return nil | return nil | ||||
| } | } | ||||
| @@ -98,7 +105,7 @@ func (g *GlobalTransactionManager) Commit(ctx context.Context, gtr *GlobalTransa | |||||
| if err == nil && res != nil { | if err == nil && res != nil { | ||||
| gtr.Status = res.(message.GlobalCommitResponse).GlobalStatus | gtr.Status = res.(message.GlobalCommitResponse).GlobalStatus | ||||
| } | } | ||||
| transaction.UnbindXid(ctx) | |||||
| seatactx.UnbindXid(ctx) | |||||
| log.Infof("GlobalCommitRequest commit success, xid %s", gtr.Xid) | log.Infof("GlobalCommitRequest commit success, xid %s", gtr.Xid) | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -134,7 +141,7 @@ func (g *GlobalTransactionManager) Rollback(ctx context.Context, gtr *GlobalTran | |||||
| if err == nil && res != nil { | if err == nil && res != nil { | ||||
| gtr.Status = res.(message.GlobalRollbackResponse).GlobalStatus | gtr.Status = res.(message.GlobalRollbackResponse).GlobalStatus | ||||
| } | } | ||||
| transaction.UnbindXid(ctx) | |||||
| seatactx.UnbindXid(ctx) | |||||
| return err | return err | ||||
| } | } | ||||
| @@ -8,7 +8,7 @@ const ( | |||||
| ) | ) | ||||
| type TransactionManager interface { | type TransactionManager interface { | ||||
| // Begin a new global transaction. | |||||
| // GlobalStatusBegin a new global transaction. | |||||
| Begin(applicationId, transactionServiceGroup, name string, timeout int64) (string, error) | Begin(applicationId, transactionServiceGroup, name string, timeout int64) (string, error) | ||||
| // Global commit. | // Global commit. | ||||
| @@ -8,95 +8,95 @@ const ( | |||||
| * Un known global status. | * Un known global status. | ||||
| */ | */ | ||||
| // Unknown | // Unknown | ||||
| UnKnown GlobalStatus = 0 | |||||
| GlobalStatusUnKnown GlobalStatus = 0 | |||||
| /** | /** | ||||
| * The Begin. | |||||
| * The GlobalStatusBegin. | |||||
| */ | */ | ||||
| // PHASE 1: can accept new branch registering. | // PHASE 1: can accept new branch registering. | ||||
| Begin GlobalStatus = 1 | |||||
| GlobalStatusBegin GlobalStatus = 1 | |||||
| /** | /** | ||||
| * PHASE 2: Running Status: may be changed any time. | * PHASE 2: Running Status: may be changed any time. | ||||
| */ | */ | ||||
| // Committing. | // Committing. | ||||
| Committing GlobalStatus = 2 | |||||
| GlobalStatusCommitting GlobalStatus = 2 | |||||
| /** | /** | ||||
| * The Commit retrying. | * The Commit retrying. | ||||
| */ | */ | ||||
| // Retrying commit after a recoverable failure. | // Retrying commit after a recoverable failure. | ||||
| CommitRetrying GlobalStatus = 3 | |||||
| GlobalStatusCommitRetrying GlobalStatus = 3 | |||||
| /** | /** | ||||
| * Rollbacking global status. | * Rollbacking global status. | ||||
| */ | */ | ||||
| // Rollbacking | // Rollbacking | ||||
| Rollbacking GlobalStatus = 4 | |||||
| GlobalStatusRollbacking GlobalStatus = 4 | |||||
| /** | /** | ||||
| * The Rollback retrying. | * The Rollback retrying. | ||||
| */ | */ | ||||
| // Retrying rollback after a recoverable failure. | // Retrying rollback after a recoverable failure. | ||||
| RollbackRetrying GlobalStatus = 5 | |||||
| GlobalStatusRollbackRetrying GlobalStatus = 5 | |||||
| /** | /** | ||||
| * The Timeout rollbacking. | * The Timeout rollbacking. | ||||
| */ | */ | ||||
| // Rollbacking since timeout | // Rollbacking since timeout | ||||
| TimeoutRollbacking GlobalStatus = 6 | |||||
| GlobalStatusTimeoutRollbacking GlobalStatus = 6 | |||||
| /** | /** | ||||
| * The Timeout rollback retrying. | * The Timeout rollback retrying. | ||||
| */ | */ | ||||
| // Retrying rollback GlobalStatus = since timeout) after a recoverable failure. | // Retrying rollback GlobalStatus = since timeout) after a recoverable failure. | ||||
| TimeoutRollbackRetrying GlobalStatus = 7 | |||||
| GlobalStatusTimeoutRollbackRetrying GlobalStatus = 7 | |||||
| /** | /** | ||||
| * All branches can be async committed. The committing is NOT done yet, but it can be seen as committed for TM/RM | * All branches can be async committed. The committing is NOT done yet, but it can be seen as committed for TM/RM | ||||
| * client. | * client. | ||||
| */ | */ | ||||
| AsyncCommitting GlobalStatus = 8 | |||||
| GlobalStatusAsyncCommitting GlobalStatus = 8 | |||||
| /** | /** | ||||
| * PHASE 2: Final Status: will NOT change any more. | * PHASE 2: Final Status: will NOT change any more. | ||||
| */ | */ | ||||
| // Finally: global transaction is successfully committed. | // Finally: global transaction is successfully committed. | ||||
| Committed GlobalStatus = 9 | |||||
| GlobalStatusCommitted GlobalStatus = 9 | |||||
| /** | /** | ||||
| * The Commit failed. | * The Commit failed. | ||||
| */ | */ | ||||
| // Finally: failed to commit | // Finally: failed to commit | ||||
| CommitFailed GlobalStatus = 10 | |||||
| GlobalStatusCommitFailed GlobalStatus = 10 | |||||
| /** | /** | ||||
| * The Rollbacked. | * The Rollbacked. | ||||
| */ | */ | ||||
| // Finally: global transaction is successfully rollbacked. | // Finally: global transaction is successfully rollbacked. | ||||
| Rollbacked GlobalStatus = 11 | |||||
| GlobalStatusRollbacked GlobalStatus = 11 | |||||
| /** | /** | ||||
| * The Rollback failed. | * The Rollback failed. | ||||
| */ | */ | ||||
| // Finally: failed to rollback | // Finally: failed to rollback | ||||
| RollbackFailed GlobalStatus = 12 | |||||
| GlobalStatusRollbackFailed GlobalStatus = 12 | |||||
| /** | /** | ||||
| * The Timeout rollbacked. | * The Timeout rollbacked. | ||||
| */ | */ | ||||
| // Finally: global transaction is successfully rollbacked since timeout. | // Finally: global transaction is successfully rollbacked since timeout. | ||||
| TimeoutRollbacked GlobalStatus = 13 | |||||
| GlobalStatusTimeoutRollbacked GlobalStatus = 13 | |||||
| /** | /** | ||||
| * The Timeout rollback failed. | * The Timeout rollback failed. | ||||
| */ | */ | ||||
| // Finally: failed to rollback since timeout | // Finally: failed to rollback since timeout | ||||
| TimeoutRollbackFailed GlobalStatus = 14 | |||||
| GlobalStatusTimeoutRollbackFailed GlobalStatus = 14 | |||||
| /** | /** | ||||
| * The Finished. | * The Finished. | ||||
| */ | */ | ||||
| // Not managed in session MAP any more | // Not managed in session MAP any more | ||||
| Finished GlobalStatus = 15 | |||||
| GlobalStatusFinished GlobalStatus = 15 | |||||
| ) | ) | ||||
| @@ -1,7 +1,6 @@ | |||||
| package getty | package getty | ||||
| import ( | import ( | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "sync" | "sync" | ||||
| "time" | "time" | ||||
| ) | ) | ||||
| @@ -12,6 +11,7 @@ import ( | |||||
| import ( | import ( | ||||
| "github.com/seata/seata-go/pkg/protocol/codec" | "github.com/seata/seata-go/pkg/protocol/codec" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | ) | ||||
| var ( | var ( | ||||
| @@ -44,7 +44,7 @@ func (client *GettyRemotingClient) SendAsyncRequest(msg interface{}) error { | |||||
| rpcMessage := message.RpcMessage{ | rpcMessage := message.RpcMessage{ | ||||
| ID: int32(client.idGenerator.Inc()), | ID: int32(client.idGenerator.Inc()), | ||||
| Type: msgType, | Type: msgType, | ||||
| Codec: codec.SEATA, | |||||
| Codec: byte(codec.CodeTypeSeata), | |||||
| Compressor: 0, | Compressor: 0, | ||||
| Body: msg, | Body: msg, | ||||
| } | } | ||||
| @@ -55,7 +55,7 @@ func (client *GettyRemotingClient) SendAsyncResponse(msg interface{}) error { | |||||
| rpcMessage := message.RpcMessage{ | rpcMessage := message.RpcMessage{ | ||||
| ID: int32(client.idGenerator.Inc()), | ID: int32(client.idGenerator.Inc()), | ||||
| Type: message.GettyRequestType_Response, | Type: message.GettyRequestType_Response, | ||||
| Codec: codec.SEATA, | |||||
| Codec: byte(codec.CodeTypeSeata), | |||||
| Compressor: 0, | Compressor: 0, | ||||
| Body: msg, | Body: msg, | ||||
| } | } | ||||
| @@ -66,7 +66,7 @@ func (client *GettyRemotingClient) SendSyncRequest(msg interface{}) (interface{} | |||||
| rpcMessage := message.RpcMessage{ | rpcMessage := message.RpcMessage{ | ||||
| ID: int32(client.idGenerator.Inc()), | ID: int32(client.idGenerator.Inc()), | ||||
| Type: message.GettyRequestType_RequestSync, | Type: message.GettyRequestType_RequestSync, | ||||
| Codec: codec.SEATA, | |||||
| Codec: byte(codec.CodeTypeSeata), | |||||
| Compressor: 0, | Compressor: 0, | ||||
| Body: msg, | Body: msg, | ||||
| } | } | ||||
| @@ -77,7 +77,7 @@ func (client *GettyRemotingClient) SendSyncRequestWithTimeout(msg interface{}, t | |||||
| rpcMessage := message.RpcMessage{ | rpcMessage := message.RpcMessage{ | ||||
| ID: int32(client.idGenerator.Inc()), | ID: int32(client.idGenerator.Inc()), | ||||
| Type: message.GettyRequestType_RequestSync, | Type: message.GettyRequestType_RequestSync, | ||||
| Codec: codec.SEATA, | |||||
| Codec: byte(codec.CodeTypeSeata), | |||||
| Compressor: 0, | Compressor: 0, | ||||
| Body: msg, | Body: msg, | ||||
| } | } | ||||
| @@ -1,8 +1,6 @@ | |||||
| package getty | package getty | ||||
| import ( | import ( | ||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "sync" | "sync" | ||||
| "time" | "time" | ||||
| ) | ) | ||||
| @@ -15,6 +13,11 @@ import ( | |||||
| "github.com/pkg/errors" | "github.com/pkg/errors" | ||||
| ) | ) | ||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | |||||
| const ( | const ( | ||||
| RPC_REQUEST_TIMEOUT = 30 * time.Second | RPC_REQUEST_TIMEOUT = 30 * time.Second | ||||
| ) | ) | ||||
| @@ -42,17 +45,17 @@ func GetGettyRemotingInstance() *GettyRemoting { | |||||
| } | } | ||||
| func (client *GettyRemoting) SendSync(msg message.RpcMessage) (interface{}, error) { | func (client *GettyRemoting) SendSync(msg message.RpcMessage) (interface{}, error) { | ||||
| ss := clientSessionManager.AcquireGettySession() | |||||
| ss := sessionManager.AcquireGettySession() | |||||
| return client.sendAsync(ss, msg, RPC_REQUEST_TIMEOUT) | return client.sendAsync(ss, msg, RPC_REQUEST_TIMEOUT) | ||||
| } | } | ||||
| func (client *GettyRemoting) SendSyncWithTimeout(msg message.RpcMessage, timeout time.Duration) (interface{}, error) { | func (client *GettyRemoting) SendSyncWithTimeout(msg message.RpcMessage, timeout time.Duration) (interface{}, error) { | ||||
| ss := clientSessionManager.AcquireGettySession() | |||||
| ss := sessionManager.AcquireGettySession() | |||||
| return client.sendAsync(ss, msg, timeout) | return client.sendAsync(ss, msg, timeout) | ||||
| } | } | ||||
| func (client *GettyRemoting) SendASync(msg message.RpcMessage) error { | func (client *GettyRemoting) SendASync(msg message.RpcMessage) error { | ||||
| ss := clientSessionManager.AcquireGettySession() | |||||
| ss := sessionManager.AcquireGettySession() | |||||
| _, err := client.sendAsync(ss, msg, 0*time.Second) | _, err := client.sendAsync(ss, msg, 0*time.Second) | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -131,7 +134,7 @@ func (client *GettyRemoting) NotifyRpcMessageResponse(rpcMessage message.RpcMess | |||||
| // todo add messageFuture.Err | // todo add messageFuture.Err | ||||
| //messageFuture.Err = rpcMessage.Err | //messageFuture.Err = rpcMessage.Err | ||||
| messageFuture.Done <- true | messageFuture.Done <- true | ||||
| //client.msgFutures.Delete(rpcMessage.ID) | |||||
| //client.msgFutures.Delete(rpcMessage.RequestID) | |||||
| } else { | } else { | ||||
| log.Infof("msg: {} is not found in msgFutures.", rpcMessage.ID) | log.Infof("msg: {} is not found in msgFutures.", rpcMessage.ID) | ||||
| } | } | ||||
| @@ -2,9 +2,6 @@ package getty | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "github.com/seata/seata-go/pkg/remoting/processor" | |||||
| "sync" | "sync" | ||||
| ) | ) | ||||
| @@ -15,7 +12,10 @@ import ( | |||||
| ) | ) | ||||
| import ( | import ( | ||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/config" | "github.com/seata/seata-go/pkg/config" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "github.com/seata/seata-go/pkg/remoting/processor" | |||||
| ) | ) | ||||
| var ( | var ( | ||||
| @@ -47,7 +47,7 @@ func GetGettyClientHandlerInstance() *gettyClientHandler { | |||||
| } | } | ||||
| func (client *gettyClientHandler) OnOpen(session getty.Session) error { | func (client *gettyClientHandler) OnOpen(session getty.Session) error { | ||||
| clientSessionManager.RegisterGettySession(session) | |||||
| sessionManager.RegisterGettySession(session) | |||||
| go func() { | go func() { | ||||
| request := message.RegisterTMRequest{AbstractIdentifyRequest: message.AbstractIdentifyRequest{ | request := message.RegisterTMRequest{AbstractIdentifyRequest: message.AbstractIdentifyRequest{ | ||||
| Version: client.conf.SeataVersion, | Version: client.conf.SeataVersion, | ||||
| @@ -58,7 +58,7 @@ func (client *gettyClientHandler) OnOpen(session getty.Session) error { | |||||
| //client.sendAsyncRequestWithResponse(session, request, RPC_REQUEST_TIMEOUT) | //client.sendAsyncRequestWithResponse(session, request, RPC_REQUEST_TIMEOUT) | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("OnOpen error: {%#v}", err.Error()) | log.Error("OnOpen error: {%#v}", err.Error()) | ||||
| clientSessionManager.ReleaseGettySession(session) | |||||
| sessionManager.ReleaseGettySession(session) | |||||
| return | return | ||||
| } | } | ||||
| @@ -70,11 +70,11 @@ func (client *gettyClientHandler) OnOpen(session getty.Session) error { | |||||
| } | } | ||||
| func (client *gettyClientHandler) OnError(session getty.Session, err error) { | func (client *gettyClientHandler) OnError(session getty.Session, err error) { | ||||
| clientSessionManager.ReleaseGettySession(session) | |||||
| sessionManager.ReleaseGettySession(session) | |||||
| } | } | ||||
| func (client *gettyClientHandler) OnClose(session getty.Session) { | func (client *gettyClientHandler) OnClose(session getty.Session) { | ||||
| clientSessionManager.ReleaseGettySession(session) | |||||
| sessionManager.ReleaseGettySession(session) | |||||
| } | } | ||||
| func (client *gettyClientHandler) OnMessage(session getty.Session, pkg interface{}) { | func (client *gettyClientHandler) OnMessage(session getty.Session, pkg interface{}) { | ||||
| @@ -1,21 +1,20 @@ | |||||
| package getty | package getty | ||||
| import ( | import ( | ||||
| "bytes" | |||||
| "encoding/binary" | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| "fmt" | |||||
| ) | ) | ||||
| import ( | import ( | ||||
| getty "github.com/apache/dubbo-getty" | getty "github.com/apache/dubbo-getty" | ||||
| "github.com/pkg/errors" | |||||
| "github.com/fagongzi/goetty" | |||||
| "vimagination.zapto.org/byteio" | |||||
| "github.com/pkg/errors" | |||||
| ) | ) | ||||
| import ( | import ( | ||||
| "github.com/seata/seata-go/pkg/protocol/codec" | "github.com/seata/seata-go/pkg/protocol/codec" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | |||||
| ) | ) | ||||
| /** | /** | ||||
| @@ -42,15 +41,14 @@ import ( | |||||
| * https://github.com/seata/seata/issues/893 | * https://github.com/seata/seata/issues/893 | ||||
| */ | */ | ||||
| const ( | const ( | ||||
| SeataV1PackageHeaderReservedLength = 16 | |||||
| Seatav1HeaderLength = 16 | |||||
| ) | ) | ||||
| var ( | var ( | ||||
| // RpcPkgHandler | |||||
| magics = []uint8{0xda, 0xda} | |||||
| rpcPkgHandler = &RpcPackageHandler{} | rpcPkgHandler = &RpcPackageHandler{} | ||||
| ) | ) | ||||
| // TODO 待重构 | |||||
| var ( | var ( | ||||
| ErrNotEnoughStream = errors.New("packet stream is not enough") | ErrNotEnoughStream = errors.New("packet stream is not enough") | ||||
| ErrTooLargePackage = errors.New("package length is exceed the getty package's legal maximum length.") | ErrTooLargePackage = errors.New("package length is exceed the getty package's legal maximum length.") | ||||
| @@ -69,90 +67,50 @@ type SeataV1PackageHeader struct { | |||||
| MessageType message.GettyRequestType | MessageType message.GettyRequestType | ||||
| CodecType byte | CodecType byte | ||||
| CompressType byte | CompressType byte | ||||
| ID uint32 | |||||
| RequestID uint32 | |||||
| Meta map[string]string | Meta map[string]string | ||||
| BodyLength uint32 | BodyLength uint32 | ||||
| Body interface{} | |||||
| } | } | ||||
| func (h *SeataV1PackageHeader) Unmarshal(buf *bytes.Buffer) (int, error) { | |||||
| bufLen := buf.Len() | |||||
| if bufLen < SeataV1PackageHeaderReservedLength { | |||||
| return 0, ErrNotEnoughStream | |||||
| } | |||||
| func (p *RpcPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) { | |||||
| in := goetty.NewByteBuf(len(data)) | |||||
| in.Write(data) | |||||
| // magic | |||||
| if err := binary.Read(buf, binary.BigEndian, &(h.Magic0)); err != nil { | |||||
| return 0, err | |||||
| header := SeataV1PackageHeader{} | |||||
| if in.Readable() < Seatav1HeaderLength { | |||||
| return nil, 0, fmt.Errorf("invalid package length") | |||||
| } | } | ||||
| if err := binary.Read(buf, binary.BigEndian, &(h.Magic1)); err != nil { | |||||
| return 0, err | |||||
| } | |||||
| if h.Magic0 != message.MAGIC_CODE_BYTES[0] || h.Magic1 != message.MAGIC_CODE_BYTES[1] { | |||||
| return 0, ErrIllegalMagic | |||||
| } | |||||
| // version | |||||
| if err := binary.Read(buf, binary.BigEndian, &(h.Version)); err != nil { | |||||
| return 0, err | |||||
| } | |||||
| // TODO check version compatible here | |||||
| // total length | |||||
| if err := binary.Read(buf, binary.BigEndian, &(h.TotalLength)); err != nil { | |||||
| return 0, err | |||||
| } | |||||
| // head length | |||||
| if err := binary.Read(buf, binary.BigEndian, &(h.HeadLength)); err != nil { | |||||
| return 0, err | |||||
| } | |||||
| // message type | |||||
| if err := binary.Read(buf, binary.BigEndian, &(h.MessageType)); err != nil { | |||||
| return 0, err | |||||
| } | |||||
| // codec type | |||||
| if err := binary.Read(buf, binary.BigEndian, &(h.CodecType)); err != nil { | |||||
| return 0, err | |||||
| magic0 := codec.ReadByte(in) | |||||
| magic1 := codec.ReadByte(in) | |||||
| if magic0 != magics[0] || magic1 != magics[1] { | |||||
| return nil, 0, fmt.Errorf("codec decode not found magic offset") | |||||
| } | } | ||||
| // compress type | |||||
| if err := binary.Read(buf, binary.BigEndian, &(h.CompressType)); err != nil { | |||||
| return 0, err | |||||
| } | |||||
| // id | |||||
| if err := binary.Read(buf, binary.BigEndian, &(h.ID)); err != nil { | |||||
| return 0, err | |||||
| } | |||||
| // todo meta map | |||||
| if h.HeadLength > SeataV1PackageHeaderReservedLength { | |||||
| headMapLength := h.HeadLength - SeataV1PackageHeaderReservedLength | |||||
| h.Meta = headMapDecode(buf.Bytes()[:headMapLength]) | |||||
| } | |||||
| h.BodyLength = h.TotalLength - uint32(h.HeadLength) | |||||
| return int(h.TotalLength), nil | |||||
| } | |||||
| header.Magic0 = magic0 | |||||
| header.Magic1 = magic1 | |||||
| header.Version = codec.ReadByte(in) | |||||
| // length of head and body | |||||
| header.TotalLength = codec.ReadUInt32(in) | |||||
| header.HeadLength = codec.ReadUInt16(in) | |||||
| header.MessageType = message.GettyRequestType(codec.ReadByte(in)) | |||||
| header.CodecType = codec.ReadByte(in) | |||||
| header.CompressType = codec.ReadByte(in) | |||||
| header.RequestID = codec.ReadUInt32(in) | |||||
| // Read read binary data from to rpc message | |||||
| func (p *RpcPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) { | |||||
| var header SeataV1PackageHeader | |||||
| headMapLength := header.HeadLength - Seatav1HeaderLength | |||||
| header.Meta = decodeHeapMap(in, headMapLength) | |||||
| header.BodyLength = header.TotalLength - uint32(header.HeadLength) | |||||
| buf := bytes.NewBuffer(data) | |||||
| _, err := header.Unmarshal(buf) | |||||
| if err != nil { | |||||
| if err == ErrNotEnoughStream { | |||||
| // getty case2 | |||||
| return nil, 0, nil | |||||
| } | |||||
| // getty case1 | |||||
| return nil, 0, err | |||||
| } | |||||
| if uint32(len(data)) < header.TotalLength { | if uint32(len(data)) < header.TotalLength { | ||||
| // get case3 | |||||
| return nil, int(header.TotalLength), nil | return nil, int(header.TotalLength), nil | ||||
| } | } | ||||
| //r := byteio.BigEndianReader{Reader: bytes.NewReader(data)} | //r := byteio.BigEndianReader{Reader: bytes.NewReader(data)} | ||||
| rpcMessage := message.RpcMessage{ | rpcMessage := message.RpcMessage{ | ||||
| Codec: header.CodecType, | Codec: header.CodecType, | ||||
| ID: int32(header.ID), | |||||
| ID: int32(header.RequestID), | |||||
| Compressor: header.CompressType, | Compressor: header.CompressType, | ||||
| Type: header.MessageType, | Type: header.MessageType, | ||||
| HeadMap: header.Meta, | HeadMap: header.Meta, | ||||
| @@ -164,8 +122,7 @@ func (p *RpcPackageHandler) Read(ss getty.Session, data []byte) (interface{}, in | |||||
| rpcMessage.Body = message.HeartBeatMessagePong | rpcMessage.Body = message.HeartBeatMessagePong | ||||
| } else { | } else { | ||||
| if header.BodyLength > 0 { | if header.BodyLength > 0 { | ||||
| //todo compress | |||||
| msg, _ := codec.MessageDecoder(header.CodecType, data[header.HeadLength:]) | |||||
| msg := codec.GetCodecManager().Decode(codec.CodecType(header.CodecType), data[header.HeadLength:]) | |||||
| rpcMessage.Body = msg | rpcMessage.Body = msg | ||||
| } | } | ||||
| } | } | ||||
| @@ -180,101 +137,91 @@ func (p *RpcPackageHandler) Write(ss getty.Session, pkg interface{}) ([]byte, er | |||||
| return nil, ErrInvalidPackage | return nil, ErrInvalidPackage | ||||
| } | } | ||||
| fullLength := message.V1HeadLength | |||||
| totalLength := message.V1HeadLength | |||||
| headLength := message.V1HeadLength | headLength := message.V1HeadLength | ||||
| var result = make([]byte, 0, fullLength) | |||||
| var b bytes.Buffer | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| result = append(result, message.MAGIC_CODE_BYTES[:2]...) | |||||
| result = append(result, message.VERSION) | |||||
| w.WriteByte(byte(msg.Type)) | |||||
| w.WriteByte(msg.Codec) | |||||
| w.WriteByte(msg.Compressor) | |||||
| w.WriteInt32(msg.ID) | |||||
| var headMapBytes []byte | |||||
| if msg.HeadMap != nil && len(msg.HeadMap) > 0 { | if msg.HeadMap != nil && len(msg.HeadMap) > 0 { | ||||
| headMapBytes, headMapLength := headMapEncode(msg.HeadMap) | |||||
| hb, headMapLength := encodeHeapMap(msg.HeadMap) | |||||
| headMapBytes = hb | |||||
| headLength += headMapLength | headLength += headMapLength | ||||
| fullLength += headMapLength | |||||
| w.Write(headMapBytes) | |||||
| totalLength += headMapLength | |||||
| } | } | ||||
| var bodyBytes []byte | |||||
| if msg.Type != message.GettyRequestType_HeartbeatRequest && | if msg.Type != message.GettyRequestType_HeartbeatRequest && | ||||
| msg.Type != message.GettyRequestType_HeartbeatResponse { | msg.Type != message.GettyRequestType_HeartbeatResponse { | ||||
| bodyBytes := codec.MessageEncoder(msg.Codec, msg.Body) | |||||
| fullLength += len(bodyBytes) | |||||
| w.Write(bodyBytes) | |||||
| } | |||||
| fullLen := int32(fullLength) | |||||
| headLen := int16(headLength) | |||||
| result = append(result, []byte{byte(fullLen >> 24), byte(fullLen >> 16), byte(fullLen >> 8), byte(fullLen)}...) | |||||
| result = append(result, []byte{byte(headLen >> 8), byte(headLen)}...) | |||||
| result = append(result, b.Bytes()...) | |||||
| return result, nil | |||||
| bodyBytes = codec.GetCodecManager().Encode(codec.CodecType(msg.Codec), msg.Body) | |||||
| totalLength += len(bodyBytes) | |||||
| } | |||||
| buf := goetty.NewByteBuf(0) | |||||
| buf.WriteByte(message.MAGIC_CODE_BYTES[0]) | |||||
| buf.WriteByte(message.MAGIC_CODE_BYTES[1]) | |||||
| buf.WriteByte(message.VERSION) | |||||
| buf.WriteUInt32(uint32(totalLength)) | |||||
| buf.WriteUInt16(uint16(headLength)) | |||||
| buf.WriteByte(byte(msg.Type)) | |||||
| buf.WriteByte(msg.Codec) | |||||
| buf.WriteByte(msg.Compressor) | |||||
| buf.WriteUInt32(uint32(msg.ID)) | |||||
| buf.Write(headMapBytes) | |||||
| buf.Write(bodyBytes) | |||||
| return buf.RawBuf(), nil | |||||
| } | } | ||||
| func headMapDecode(data []byte) map[string]string { | |||||
| size := len(data) | |||||
| if size == 0 { | |||||
| return nil | |||||
| } | |||||
| mp := make(map[string]string) | |||||
| r := byteio.BigEndianReader{Reader: bytes.NewReader(data)} | |||||
| readLength := 0 | |||||
| for readLength < size { | |||||
| var key, value string | |||||
| lengthK, _, _ := r.ReadUint16() | |||||
| if lengthK < 0 { | |||||
| break | |||||
| } else if lengthK == 0 { | |||||
| key = "" | |||||
| func encodeHeapMap(data map[string]string) ([]byte, int) { | |||||
| buf := goetty.NewByteBuf(0) | |||||
| for k, v := range data { | |||||
| if k == "" { | |||||
| buf.WriteUInt16(uint16(0)) | |||||
| } else { | } else { | ||||
| key, _, _ = r.ReadString(int(lengthK)) | |||||
| buf.WriteUInt16(uint16(len(k))) | |||||
| buf.WriteString(k) | |||||
| } | } | ||||
| lengthV, _, _ := r.ReadUint16() | |||||
| if lengthV < 0 { | |||||
| break | |||||
| } else if lengthV == 0 { | |||||
| value = "" | |||||
| if v == "" { | |||||
| buf.WriteUInt16(uint16(0)) | |||||
| } else { | } else { | ||||
| value, _, _ = r.ReadString(int(lengthV)) | |||||
| buf.WriteUInt16(uint16(len(v))) | |||||
| buf.WriteString(v) | |||||
| } | } | ||||
| mp[key] = value | |||||
| readLength += int(lengthK + lengthV) | |||||
| } | } | ||||
| return mp | |||||
| res := buf.RawBuf() | |||||
| return res, len(res) | |||||
| } | } | ||||
| func headMapEncode(data map[string]string) ([]byte, int) { | |||||
| var b bytes.Buffer | |||||
| func decodeHeapMap(in *goetty.ByteBuf, length uint16) map[string]string { | |||||
| res := make(map[string]string, 0) | |||||
| if length == 0 { | |||||
| return res | |||||
| } | |||||
| w := byteio.BigEndianWriter{Writer: &b} | |||||
| for k, v := range data { | |||||
| if k == "" { | |||||
| w.WriteUint16(0) | |||||
| readedLength := uint16(0) | |||||
| for readedLength < length { | |||||
| var key, value string | |||||
| keyLength := codec.ReadUInt16(in) | |||||
| if keyLength == 0 { | |||||
| key = "" | |||||
| } else { | } else { | ||||
| w.WriteUint16(uint16(len(k))) | |||||
| w.WriteString(k) | |||||
| keyBytes := make([]byte, keyLength) | |||||
| keyBytes = codec.Read(in, keyBytes) | |||||
| key = string(keyBytes) | |||||
| } | } | ||||
| if v == "" { | |||||
| w.WriteUint16(0) | |||||
| valueLength := codec.ReadUInt16(in) | |||||
| if valueLength == 0 { | |||||
| key = "" | |||||
| } else { | } else { | ||||
| w.WriteUint16(uint16(len(v))) | |||||
| w.WriteString(v) | |||||
| valueBytes := make([]byte, valueLength) | |||||
| valueBytes = codec.Read(in, valueBytes) | |||||
| value = string(valueBytes) | |||||
| } | } | ||||
| } | |||||
| return b.Bytes(), b.Len() | |||||
| res[key] = value | |||||
| readedLength += 4 + keyLength + valueLength | |||||
| fmt.Sprintln("done") | |||||
| } | |||||
| return res | |||||
| } | } | ||||
| @@ -1,8 +1,8 @@ | |||||
| package getty | package getty | ||||
| import ( | import ( | ||||
| "crypto/tls" | |||||
| "fmt" | "fmt" | ||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "net" | "net" | ||||
| "sync" | "sync" | ||||
| ) | ) | ||||
| @@ -11,9 +11,12 @@ import ( | |||||
| getty "github.com/apache/dubbo-getty" | getty "github.com/apache/dubbo-getty" | ||||
| gxsync "github.com/dubbogo/gost/sync" | gxsync "github.com/dubbogo/gost/sync" | ||||
| "github.com/pkg/errors" | |||||
| ) | ) | ||||
| import ( | import ( | ||||
| "github.com/seata/seata-go/pkg/common/log" | |||||
| "github.com/seata/seata-go/pkg/config" | "github.com/seata/seata-go/pkg/config" | ||||
| ) | ) | ||||
| @@ -62,23 +65,51 @@ func (c *RpcClient) newSession(session getty.Session) error { | |||||
| var ( | var ( | ||||
| ok bool | ok bool | ||||
| tcpConn *net.TCPConn | tcpConn *net.TCPConn | ||||
| err error | |||||
| ) | ) | ||||
| if c.conf.GettyConfig.GettySessionParam.CompressEncoding { | if c.conf.GettyConfig.GettySessionParam.CompressEncoding { | ||||
| session.SetCompressType(getty.CompressZip) | session.SetCompressType(getty.CompressZip) | ||||
| } | } | ||||
| if tcpConn, ok = session.Conn().(*net.TCPConn); !ok { | |||||
| panic(fmt.Sprintf("%s, session.conn{%#v} is not tcp connection\n", session.Stat(), session.Conn())) | |||||
| if _, ok = session.Conn().(*tls.Conn); ok { | |||||
| session.SetName(c.conf.GettyConfig.GettySessionParam.SessionName) | |||||
| session.SetMaxMsgLen(c.conf.GettyConfig.GettySessionParam.MaxMsgLen) | |||||
| session.SetPkgHandler(rpcPkgHandler) | |||||
| session.SetEventListener(GetGettyClientHandlerInstance()) | |||||
| session.SetReadTimeout(c.conf.GettyConfig.GettySessionParam.TCPReadTimeout) | |||||
| session.SetWriteTimeout(c.conf.GettyConfig.GettySessionParam.TCPWriteTimeout) | |||||
| session.SetCronPeriod((int)(c.conf.GettyConfig.GettySessionParam.CronPeriod)) | |||||
| session.SetWaitTime(c.conf.GettyConfig.GettySessionParam.WaitTimeout) | |||||
| log.Debugf("server accepts new tls session:%s\n", session.Stat()) | |||||
| return nil | |||||
| } | |||||
| if _, ok = session.Conn().(*net.TCPConn); !ok { | |||||
| panic(fmt.Sprintf("%s, session.conn{%#v} is not a tcp connection\n", session.Stat(), session.Conn())) | |||||
| } | } | ||||
| tcpConn.SetNoDelay(c.conf.GettyConfig.GettySessionParam.TCPNoDelay) | |||||
| tcpConn.SetKeepAlive(c.conf.GettyConfig.GettySessionParam.TCPKeepAlive) | |||||
| if c.conf.GettyConfig.GettySessionParam.TCPKeepAlive { | |||||
| tcpConn.SetKeepAlivePeriod(c.conf.GettyConfig.GettySessionParam.KeepAlivePeriod) | |||||
| if _, ok = session.Conn().(*tls.Conn); !ok { | |||||
| if tcpConn, ok = session.Conn().(*net.TCPConn); !ok { | |||||
| return errors.New(fmt.Sprintf("%s, session.conn{%#v} is not tcp connection", session.Stat(), session.Conn())) | |||||
| } | |||||
| if err = tcpConn.SetNoDelay(c.conf.GettyConfig.GettySessionParam.TCPNoDelay); err != nil { | |||||
| return err | |||||
| } | |||||
| if err = tcpConn.SetKeepAlive(c.conf.GettyConfig.GettySessionParam.TCPKeepAlive); err != nil { | |||||
| return err | |||||
| } | |||||
| if c.conf.GettyConfig.GettySessionParam.TCPKeepAlive { | |||||
| if err = tcpConn.SetKeepAlivePeriod(c.conf.GettyConfig.GettySessionParam.KeepAlivePeriod); err != nil { | |||||
| return err | |||||
| } | |||||
| } | |||||
| if err = tcpConn.SetReadBuffer(c.conf.GettyConfig.GettySessionParam.TCPRBufSize); err != nil { | |||||
| return err | |||||
| } | |||||
| if err = tcpConn.SetWriteBuffer(c.conf.GettyConfig.GettySessionParam.TCPWBufSize); err != nil { | |||||
| return err | |||||
| } | |||||
| } | } | ||||
| tcpConn.SetReadBuffer(c.conf.GettyConfig.GettySessionParam.TCPRBufSize) | |||||
| tcpConn.SetWriteBuffer(c.conf.GettyConfig.GettySessionParam.TCPWBufSize) | |||||
| session.SetName(c.conf.GettyConfig.GettySessionParam.SessionName) | session.SetName(c.conf.GettyConfig.GettySessionParam.SessionName) | ||||
| session.SetMaxMsgLen(c.conf.GettyConfig.GettySessionParam.MaxMsgLen) | session.SetMaxMsgLen(c.conf.GettyConfig.GettySessionParam.MaxMsgLen) | ||||
| @@ -86,7 +117,7 @@ func (c *RpcClient) newSession(session getty.Session) error { | |||||
| session.SetEventListener(GetGettyClientHandlerInstance()) | session.SetEventListener(GetGettyClientHandlerInstance()) | ||||
| session.SetReadTimeout(c.conf.GettyConfig.GettySessionParam.TCPReadTimeout) | session.SetReadTimeout(c.conf.GettyConfig.GettySessionParam.TCPReadTimeout) | ||||
| session.SetWriteTimeout(c.conf.GettyConfig.GettySessionParam.TCPWriteTimeout) | session.SetWriteTimeout(c.conf.GettyConfig.GettySessionParam.TCPWriteTimeout) | ||||
| session.SetCronPeriod((int)(c.conf.GettyConfig.HeartbeatPeriod.Nanoseconds() / 1e6)) | |||||
| session.SetCronPeriod((int)(c.conf.GettyConfig.GettySessionParam.CronPeriod.Nanoseconds() / 1e6)) | |||||
| session.SetWaitTime(c.conf.GettyConfig.GettySessionParam.WaitTimeout) | session.SetWaitTime(c.conf.GettyConfig.GettySessionParam.WaitTimeout) | ||||
| log.Debugf("rpc_client new session:%s\n", session.Stat()) | log.Debugf("rpc_client new session:%s\n", session.Stat()) | ||||
| @@ -22,12 +22,12 @@ var ( | |||||
| sessionSize int32 = 0 | sessionSize int32 = 0 | ||||
| clientSessionManager = &GettyClientSessionManager{} | |||||
| sessionManager = &GettySessionManager{} | |||||
| ) | ) | ||||
| type GettyClientSessionManager struct{} | |||||
| type GettySessionManager struct{} | |||||
| func (sessionManager *GettyClientSessionManager) AcquireGettySession() getty.Session { | |||||
| func (sessionManager *GettySessionManager) AcquireGettySession() getty.Session { | |||||
| // map 遍历是随机的 | // map 遍历是随机的 | ||||
| var session getty.Session | var session getty.Session | ||||
| allSessions.Range(func(key, value interface{}) bool { | allSessions.Range(func(key, value interface{}) bool { | ||||
| @@ -64,7 +64,7 @@ func (sessionManager *GettyClientSessionManager) AcquireGettySession() getty.Ses | |||||
| return nil | return nil | ||||
| } | } | ||||
| func (sessionManager *GettyClientSessionManager) AcquireGettySessionByServerAddress(serverAddress string) getty.Session { | |||||
| func (sessionManager *GettySessionManager) AcquireGettySessionByServerAddress(serverAddress string) getty.Session { | |||||
| m, _ := serverSessions.LoadOrStore(serverAddress, &sync.Map{}) | m, _ := serverSessions.LoadOrStore(serverAddress, &sync.Map{}) | ||||
| sMap := m.(*sync.Map) | sMap := m.(*sync.Map) | ||||
| @@ -81,7 +81,7 @@ func (sessionManager *GettyClientSessionManager) AcquireGettySessionByServerAddr | |||||
| return session | return session | ||||
| } | } | ||||
| func (sessionManager *GettyClientSessionManager) ReleaseGettySession(session getty.Session) { | |||||
| func (sessionManager *GettySessionManager) ReleaseGettySession(session getty.Session) { | |||||
| allSessions.Delete(session) | allSessions.Delete(session) | ||||
| if !session.IsClosed() { | if !session.IsClosed() { | ||||
| m, _ := serverSessions.LoadOrStore(session.RemoteAddr(), &sync.Map{}) | m, _ := serverSessions.LoadOrStore(session.RemoteAddr(), &sync.Map{}) | ||||
| @@ -92,7 +92,7 @@ func (sessionManager *GettyClientSessionManager) ReleaseGettySession(session get | |||||
| atomic.AddInt32(&sessionSize, -1) | atomic.AddInt32(&sessionSize, -1) | ||||
| } | } | ||||
| func (sessionManager *GettyClientSessionManager) RegisterGettySession(session getty.Session) { | |||||
| func (sessionManager *GettySessionManager) RegisterGettySession(session getty.Session) { | |||||
| allSessions.Store(session, true) | allSessions.Store(session, true) | ||||
| m, _ := serverSessions.LoadOrStore(session.RemoteAddr(), &sync.Map{}) | m, _ := serverSessions.LoadOrStore(session.RemoteAddr(), &sync.Map{}) | ||||
| sMap := m.(*sync.Map) | sMap := m.(*sync.Map) | ||||
| @@ -2,6 +2,9 @@ package client | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| "github.com/seata/seata-go/pkg/remoting/getty" | "github.com/seata/seata-go/pkg/remoting/getty" | ||||
| @@ -2,6 +2,9 @@ package client | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| getty2 "github.com/seata/seata-go/pkg/remoting/getty" | getty2 "github.com/seata/seata-go/pkg/remoting/getty" | ||||
| @@ -2,6 +2,9 @@ package client | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| getty2 "github.com/seata/seata-go/pkg/remoting/getty" | getty2 "github.com/seata/seata-go/pkg/remoting/getty" | ||||
| @@ -2,6 +2,9 @@ package client | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| getty2 "github.com/seata/seata-go/pkg/remoting/getty" | getty2 "github.com/seata/seata-go/pkg/remoting/getty" | ||||
| @@ -2,6 +2,9 @@ package processor | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| ) | ) | ||||
| @@ -2,6 +2,9 @@ package handler | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| "github.com/seata/seata-go/pkg/protocol/branch" | "github.com/seata/seata-go/pkg/protocol/branch" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| @@ -2,9 +2,12 @@ package handler | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "sync" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/branch" | "github.com/seata/seata-go/pkg/protocol/branch" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| "sync" | |||||
| ) | ) | ||||
| var ( | var ( | ||||
| @@ -1,12 +1,15 @@ | |||||
| package remoting | package remoting | ||||
| import ( | |||||
| "sync" | |||||
| ) | |||||
| import ( | import ( | ||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| "github.com/seata/seata-go/pkg/protocol/branch" | "github.com/seata/seata-go/pkg/protocol/branch" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| "github.com/seata/seata-go/pkg/protocol/resource" | "github.com/seata/seata-go/pkg/protocol/resource" | ||||
| "github.com/seata/seata-go/pkg/remoting/getty" | "github.com/seata/seata-go/pkg/remoting/getty" | ||||
| "sync" | |||||
| ) | ) | ||||
| var ( | var ( | ||||
| @@ -3,9 +3,12 @@ package rm | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "fmt" | "fmt" | ||||
| "sync" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/protocol/branch" | "github.com/seata/seata-go/pkg/protocol/branch" | ||||
| "github.com/seata/seata-go/pkg/protocol/resource" | "github.com/seata/seata-go/pkg/protocol/resource" | ||||
| "sync" | |||||
| ) | ) | ||||
| var ( | var ( | ||||
| @@ -3,18 +3,18 @@ package tcc | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "fmt" | "fmt" | ||||
| "sync" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| "github.com/seata/seata-go/pkg/protocol/branch" | "github.com/seata/seata-go/pkg/protocol/branch" | ||||
| "github.com/seata/seata-go/pkg/protocol/message" | "github.com/seata/seata-go/pkg/protocol/message" | ||||
| "github.com/seata/seata-go/pkg/protocol/resource" | "github.com/seata/seata-go/pkg/protocol/resource" | ||||
| "github.com/seata/seata-go/pkg/remoting/getty" | "github.com/seata/seata-go/pkg/remoting/getty" | ||||
| "github.com/seata/seata-go/pkg/rm" | |||||
| "github.com/seata/seata-go/pkg/rm/common/remoting" | "github.com/seata/seata-go/pkg/rm/common/remoting" | ||||
| "github.com/seata/seata-go/pkg/rm/tcc/api" | "github.com/seata/seata-go/pkg/rm/tcc/api" | ||||
| "sync" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/rm" | |||||
| ) | ) | ||||
| var ( | var ( | ||||
| @@ -111,7 +111,7 @@ func (t *TCCResourceManager) GetManagedResources() sync.Map { | |||||
| func (t *TCCResourceManager) BranchCommit(ctx context.Context, ranchType branch.BranchType, xid string, branchID int64, resourceID string, applicationData []byte) (branch.BranchStatus, error) { | func (t *TCCResourceManager) BranchCommit(ctx context.Context, ranchType branch.BranchType, xid string, branchID int64, resourceID string, applicationData []byte) (branch.BranchStatus, error) { | ||||
| var tccResource *TCCResource | var tccResource *TCCResource | ||||
| if resource, ok := t.resourceManagerMap.Load(resourceID); !ok { | if resource, ok := t.resourceManagerMap.Load(resourceID); !ok { | ||||
| err := fmt.Errorf("CC resource is not exist, resourceId: %s", resourceID) | |||||
| err := fmt.Errorf("TCC resource is not exist, resourceId: %s", resourceID) | |||||
| return 0, err | return 0, err | ||||
| } else { | } else { | ||||
| tccResource, _ = resource.(*TCCResource) | tccResource, _ = resource.(*TCCResource) | ||||
| @@ -4,20 +4,22 @@ import ( | |||||
| "context" | "context" | ||||
| "encoding/json" | "encoding/json" | ||||
| "fmt" | "fmt" | ||||
| "time" | |||||
| ) | |||||
| import ( | |||||
| "github.com/pkg/errors" | "github.com/pkg/errors" | ||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common" | "github.com/seata/seata-go/pkg/common" | ||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| "github.com/seata/seata-go/pkg/common/net" | "github.com/seata/seata-go/pkg/common/net" | ||||
| "github.com/seata/seata-go/pkg/protocol/branch" | "github.com/seata/seata-go/pkg/protocol/branch" | ||||
| "github.com/seata/seata-go/pkg/protocol/seatactx" | |||||
| context2 "github.com/seata/seata-go/pkg/protocol/transaction" | context2 "github.com/seata/seata-go/pkg/protocol/transaction" | ||||
| "github.com/seata/seata-go/pkg/protocol/transaction/executor" | |||||
| "github.com/seata/seata-go/pkg/rm" | "github.com/seata/seata-go/pkg/rm" | ||||
| api2 "github.com/seata/seata-go/pkg/rm/tcc/api" | api2 "github.com/seata/seata-go/pkg/rm/tcc/api" | ||||
| "time" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/rm/tcc/remoting" | |||||
| ) | ) | ||||
| type TCCService interface { | type TCCService interface { | ||||
| @@ -26,8 +28,8 @@ type TCCService interface { | |||||
| Rollback(ctx context.Context, businessActionContext api2.BusinessActionContext) error | Rollback(ctx context.Context, businessActionContext api2.BusinessActionContext) error | ||||
| GetActionName() string | GetActionName() string | ||||
| GetRemoteType() remoting.RemoteType | |||||
| GetServiceType() remoting.ServiceType | |||||
| //GetRemoteType() remoting.RemoteType | |||||
| //GetServiceType() remoting.ServiceType | |||||
| } | } | ||||
| type TCCServiceProxy struct { | type TCCServiceProxy struct { | ||||
| @@ -57,30 +59,18 @@ func NewTCCServiceProxy(tccService TCCService) TCCService { | |||||
| } | } | ||||
| func (t *TCCServiceProxy) Prepare(ctx context.Context, param interface{}) error { | func (t *TCCServiceProxy) Prepare(ctx context.Context, param interface{}) error { | ||||
| var err error | |||||
| if context2.IsSeataContext(ctx) { | |||||
| // execute transaction | |||||
| _, err = executor.GetTransactionTemplate().Execute(ctx, t, param) | |||||
| } else { | |||||
| log.Warn("context is not inited as seata context, will not execute transaction!") | |||||
| err = t.TCCService.Prepare(ctx, param) | |||||
| } | |||||
| return err | |||||
| } | |||||
| // register transaction branch, and then execute business | |||||
| func (t *TCCServiceProxy) Execute(ctx context.Context, param interface{}) (interface{}, error) { | |||||
| // register transaction branch | |||||
| err := t.RegisteBranch(ctx, param) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| if seatactx.HasXID(ctx) { | |||||
| err := t.RegisteBranch(ctx, param) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| } | } | ||||
| return nil, t.TCCService.Prepare(ctx, param) | |||||
| return t.TCCService.Prepare(ctx, param) | |||||
| } | } | ||||
| func (t *TCCServiceProxy) RegisteBranch(ctx context.Context, param interface{}) error { | func (t *TCCServiceProxy) RegisteBranch(ctx context.Context, param interface{}) error { | ||||
| // register transaction branch | // register transaction branch | ||||
| if !context2.HasXID(ctx) { | |||||
| if !seatactx.HasXID(ctx) { | |||||
| err := errors.New("BranchRegister error, xid should not be nil") | err := errors.New("BranchRegister error, xid should not be nil") | ||||
| log.Errorf(err.Error()) | log.Errorf(err.Error()) | ||||
| return err | return err | ||||
| @@ -91,7 +81,7 @@ func (t *TCCServiceProxy) RegisteBranch(ctx context.Context, param interface{}) | |||||
| tccContextStr, _ := json.Marshal(tccContext) | tccContextStr, _ := json.Marshal(tccContext) | ||||
| branchId, err := rm.GetResourceManagerInstance().GetResourceManager(branch.BranchTypeTCC).BranchRegister( | branchId, err := rm.GetResourceManagerInstance().GetResourceManager(branch.BranchTypeTCC).BranchRegister( | ||||
| ctx, branch.BranchTypeTCC, t.GetActionName(), "", context2.GetXID(ctx), string(tccContextStr), "") | |||||
| ctx, branch.BranchTypeTCC, t.GetActionName(), "", seatactx.GetXID(ctx), string(tccContextStr), "") | |||||
| if err != nil { | if err != nil { | ||||
| err = errors.New(fmt.Sprintf("BranchRegister error: %v", err.Error())) | err = errors.New(fmt.Sprintf("BranchRegister error: %v", err.Error())) | ||||
| log.Error(err.Error()) | log.Error(err.Error()) | ||||
| @@ -99,12 +89,12 @@ func (t *TCCServiceProxy) RegisteBranch(ctx context.Context, param interface{}) | |||||
| } | } | ||||
| actionContext := &api2.BusinessActionContext{ | actionContext := &api2.BusinessActionContext{ | ||||
| Xid: context2.GetXID(ctx), | |||||
| Xid: seatactx.GetXID(ctx), | |||||
| BranchId: string(branchId), | BranchId: string(branchId), | ||||
| ActionName: t.GetActionName(), | ActionName: t.GetActionName(), | ||||
| ActionContext: param, | ActionContext: param, | ||||
| } | } | ||||
| context2.SetBusinessActionContext(ctx, actionContext) | |||||
| seatactx.SetBusinessActionContext(ctx, actionContext) | |||||
| return nil | return nil | ||||
| } | } | ||||
| @@ -1,11 +1,14 @@ | |||||
| package test | package test | ||||
| import ( | import ( | ||||
| _ "github.com/seata/seata-go/pkg/imports" | |||||
| "testing" | "testing" | ||||
| "time" | "time" | ||||
| ) | ) | ||||
| import ( | |||||
| _ "github.com/seata/seata-go/pkg/imports" | |||||
| ) | |||||
| func TestSendMsgWithResponse(test *testing.T) { | func TestSendMsgWithResponse(test *testing.T) { | ||||
| //request := protocol.RegisterRMRequest{ | //request := protocol.RegisterRMRequest{ | ||||
| // ResourceIds: "1111", | // ResourceIds: "1111", | ||||
| @@ -2,13 +2,16 @@ package test | |||||
| import ( | import ( | ||||
| "context" | "context" | ||||
| "testing" | |||||
| "time" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/common/log" | "github.com/seata/seata-go/pkg/common/log" | ||||
| _ "github.com/seata/seata-go/pkg/imports" | _ "github.com/seata/seata-go/pkg/imports" | ||||
| context2 "github.com/seata/seata-go/pkg/protocol/transaction" | |||||
| txapi "github.com/seata/seata-go/pkg/protocol/transaction/api" | |||||
| "github.com/seata/seata-go/pkg/rm/tcc" | "github.com/seata/seata-go/pkg/rm/tcc" | ||||
| "github.com/seata/seata-go/pkg/rm/tcc/api" | "github.com/seata/seata-go/pkg/rm/tcc/api" | ||||
| "github.com/seata/seata-go/pkg/rm/tcc/remoting" | |||||
| "testing" | |||||
| ) | ) | ||||
| type TestTCCServiceBusiness struct { | type TestTCCServiceBusiness struct { | ||||
| @@ -33,17 +36,41 @@ func (T TestTCCServiceBusiness) GetActionName() string { | |||||
| return "TestTCCServiceBusiness" | return "TestTCCServiceBusiness" | ||||
| } | } | ||||
| func (T TestTCCServiceBusiness) GetRemoteType() remoting.RemoteType { | |||||
| return remoting.RemoteTypeLocalService | |||||
| type TestTCCServiceBusiness2 struct { | |||||
| } | |||||
| func (T TestTCCServiceBusiness2) Prepare(ctx context.Context, params interface{}) error { | |||||
| log.Infof("TestTCCServiceBusiness2 Prepare, param %v", params) | |||||
| return nil | |||||
| } | |||||
| func (T TestTCCServiceBusiness2) Commit(ctx context.Context, businessActionContext api.BusinessActionContext) error { | |||||
| log.Infof("TestTCCServiceBusiness2 Commit, param %v", businessActionContext) | |||||
| return nil | |||||
| } | |||||
| func (T TestTCCServiceBusiness2) Rollback(ctx context.Context, businessActionContext api.BusinessActionContext) error { | |||||
| log.Infof("TestTCCServiceBusiness2 Rollback, param %v", businessActionContext) | |||||
| return nil | |||||
| } | } | ||||
| func (T TestTCCServiceBusiness) GetServiceType() remoting.ServiceType { | |||||
| return remoting.ServiceTypeProvider | |||||
| func (T TestTCCServiceBusiness2) GetActionName() string { | |||||
| return "TestTCCServiceBusiness2" | |||||
| } | } | ||||
| func TestNew(test *testing.T) { | func TestNew(test *testing.T) { | ||||
| var err error | |||||
| ctx := txapi.Begin(context.Background(), "TestTCCServiceBusiness") | |||||
| defer func() { | |||||
| resp := txapi.CommitOrRollback(ctx, err) | |||||
| log.Infof("tx result %v", resp) | |||||
| }() | |||||
| tccService := tcc.NewTCCServiceProxy(TestTCCServiceBusiness{}) | tccService := tcc.NewTCCServiceProxy(TestTCCServiceBusiness{}) | ||||
| tccService.Prepare(context2.InitSeataContext(context.Background()), 1) | |||||
| err = tccService.Prepare(ctx, 1) | |||||
| tccService2 := tcc.NewTCCServiceProxy(TestTCCServiceBusiness2{}) | |||||
| err = tccService2.Prepare(ctx, 3) | |||||
| //time.Sleep(time.Second * 1000) | |||||
| time.Sleep(time.Second * 1000) | |||||
| } | } | ||||
| @@ -1,51 +0,0 @@ | |||||
| package mock | |||||
| import ( | |||||
| "context" | |||||
| "fmt" | |||||
| "github.com/seata/seata-go/pkg/common/xid" | |||||
| "github.com/seata/seata-go/pkg/rm/tcc/api" | |||||
| ) | |||||
| import ( | |||||
| "github.com/seata/seata-go/pkg/rm/tcc/remoting" | |||||
| _ "github.com/seata/seata-go/pkg/utils/xid" | |||||
| ) | |||||
| // 注册RM资源 | |||||
| func init() { | |||||
| } | |||||
| type MockTccService struct { | |||||
| } | |||||
| func (*MockTccService) Prepare(ctx context.Context, params interface{}) error { | |||||
| xid := xid_utils.xid_utils.GetXID(ctx) | |||||
| fmt.Printf("TccActionOne prepare, xid:" + xid) | |||||
| return nil | |||||
| } | |||||
| func (*MockTccService) Commit(ctx context.Context, businessActionContext api.BusinessActionContext) error { | |||||
| xid := xid_utils.GetXID(ctx) | |||||
| fmt.Printf("TccActionOne commit, xid:" + xid) | |||||
| return nil | |||||
| } | |||||
| func (*MockTccService) Rollback(ctx context.Context, businessActionContext api.BusinessActionContext) error { | |||||
| xid := xid_utils.GetXID(ctx) | |||||
| fmt.Printf("TccActionOne rollback, xid:" + xid) | |||||
| return nil | |||||
| } | |||||
| func (*MockTccService) GetRemoteType() remoting.RemoteType { | |||||
| return remoting.RemoteTypeLocalService | |||||
| } | |||||
| func (*MockTccService) GetActionName() string { | |||||
| return "MockTccService" | |||||
| } | |||||
| func (*MockTccService) GetServiceType() remoting.ServiceType { | |||||
| return remoting.ServiceTypeProvider | |||||
| } | |||||