Browse Source

Adjust the structure of the project

tags/v0.1.0-rc1
luky116_Liuyuecai 3 years ago
parent
commit
1e3201b026
56 changed files with 2077 additions and 1959 deletions
  1. +4
    -0
      go.mod
  2. +533
    -0
      go.sum
  3. +9
    -0
      pkg/common/error/error.go
  4. +2
    -0
      pkg/config/getty_config.go
  5. +68
    -0
      pkg/protocol/codec/branch_register_req_codec.go
  6. +74
    -0
      pkg/protocol/codec/branch_register_response_codec.go
  7. +62
    -206
      pkg/protocol/codec/codec.go
  8. +189
    -0
      pkg/protocol/codec/codec_help.go
  9. +51
    -0
      pkg/protocol/codec/common_global_end_request_codec.go
  10. +58
    -0
      pkg/protocol/codec/common_global_end_response_codec.go
  11. +72
    -0
      pkg/protocol/codec/common_identify_request_codec.go
  12. +47
    -0
      pkg/protocol/codec/common_identify_response_codec.go
  13. +45
    -0
      pkg/protocol/codec/global_begin_request_codec.go
  14. +76
    -0
      pkg/protocol/codec/global_begin_response_codec.go
  15. +30
    -0
      pkg/protocol/codec/global_commit_req_codec.go
  16. +25
    -0
      pkg/protocol/codec/global_commit_response_codec.go
  17. +21
    -0
      pkg/protocol/codec/global_report_request_codec.go.go
  18. +25
    -0
      pkg/protocol/codec/global_report_response_codec.go
  19. +30
    -0
      pkg/protocol/codec/global_rollback_req_codec.go
  20. +25
    -0
      pkg/protocol/codec/global_rollback_response_codec.go
  21. +30
    -0
      pkg/protocol/codec/global_status_req_codec.go
  22. +25
    -0
      pkg/protocol/codec/global_status_response_codec.go
  23. +71
    -0
      pkg/protocol/codec/register_rm_request_codec.go
  24. +25
    -0
      pkg/protocol/codec/register_rm_response_codec.go
  25. +30
    -0
      pkg/protocol/codec/register_tm_request_codec.go
  26. +30
    -0
      pkg/protocol/codec/register_tm_response_codec.go
  27. +0
    -779
      pkg/protocol/codec/seata_decoder.go
  28. +0
    -563
      pkg/protocol/codec/seata_encoder.go
  29. +1
    -0
      pkg/protocol/message/request_message.go
  30. +4
    -1
      pkg/protocol/resource/resource.go
  31. +43
    -7
      pkg/protocol/seatactx/context.go
  32. +81
    -0
      pkg/protocol/transaction/api/api.go
  33. +0
    -96
      pkg/protocol/transaction/executor/transactional_template.go
  34. +13
    -6
      pkg/protocol/transaction/manager/global_transaction_manager.go
  35. +1
    -1
      pkg/protocol/transaction/transaction_manager.go
  36. +17
    -17
      pkg/protocol/transaction/transaction_status.go
  37. +5
    -5
      pkg/remoting/getty/getty_client.go
  38. +9
    -6
      pkg/remoting/getty/getty_remoting.go
  39. +7
    -7
      pkg/remoting/getty/listener.go
  40. +95
    -148
      pkg/remoting/getty/readwriter.go
  41. +42
    -11
      pkg/remoting/getty/rpc_client.go
  42. +6
    -6
      pkg/remoting/getty/session_manager.go
  43. +3
    -0
      pkg/remoting/processor/client/client_heart_beat_processon.go
  44. +3
    -0
      pkg/remoting/processor/client/client_on_response_processor.go
  45. +3
    -0
      pkg/remoting/processor/client/rm_branch_commit_processor.go
  46. +3
    -0
      pkg/remoting/processor/client/rm_branch_rollback_processor.go
  47. +3
    -0
      pkg/remoting/processor/remoting_processor.go
  48. +3
    -0
      pkg/rm/common/handler/rm_handler.go
  49. +4
    -1
      pkg/rm/common/handler/rm_handler_facade.go
  50. +4
    -1
      pkg/rm/common/remoting/rm_remoting.go
  51. +4
    -1
      pkg/rm/resource_manager.go
  52. +6
    -6
      pkg/rm/tcc/tcc_resource.go
  53. +20
    -30
      pkg/rm/tcc/tcc_service.go
  54. +4
    -1
      test/rpc_remoting_client_test.go
  55. +36
    -9
      test/tcc_service_test.go
  56. +0
    -51
      testdata/mock/mock_tcc_service.go

+ 4
- 0
go.mod View File

@@ -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


+ 533
- 0
go.sum
File diff suppressed because it is too large
View File


+ 9
- 0
pkg/common/error/error.go View File

@@ -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")
)

+ 2
- 0
pkg/config/getty_config.go View File

@@ -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"`


+ 68
- 0
pkg/protocol/codec/branch_register_req_codec.go View File

@@ -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
}

+ 74
- 0
pkg/protocol/codec/branch_register_response_codec.go View File

@@ -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
}

+ 62
- 206
pkg/protocol/codec/codec.go View File

@@ -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
} }

+ 189
- 0
pkg/protocol/codec/codec_help.go View File

@@ -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
}

+ 51
- 0
pkg/protocol/codec/common_global_end_request_codec.go View File

@@ -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
}

+ 58
- 0
pkg/protocol/codec/common_global_end_response_codec.go View File

@@ -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
}

+ 72
- 0
pkg/protocol/codec/common_identify_request_codec.go View File

@@ -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
}

+ 47
- 0
pkg/protocol/codec/common_identify_response_codec.go View File

@@ -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
}

+ 45
- 0
pkg/protocol/codec/global_begin_request_codec.go View File

@@ -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
}

+ 76
- 0
pkg/protocol/codec/global_begin_response_codec.go View File

@@ -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
}

+ 30
- 0
pkg/protocol/codec/global_commit_req_codec.go View File

@@ -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
}

+ 25
- 0
pkg/protocol/codec/global_commit_response_codec.go View File

@@ -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
}

+ 21
- 0
pkg/protocol/codec/global_report_request_codec.go.go View File

@@ -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
//}

+ 25
- 0
pkg/protocol/codec/global_report_response_codec.go View File

@@ -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
}

+ 30
- 0
pkg/protocol/codec/global_rollback_req_codec.go View File

@@ -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
}

+ 25
- 0
pkg/protocol/codec/global_rollback_response_codec.go View File

@@ -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
}

+ 30
- 0
pkg/protocol/codec/global_status_req_codec.go View File

@@ -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
}

+ 25
- 0
pkg/protocol/codec/global_status_response_codec.go View File

@@ -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
}

+ 71
- 0
pkg/protocol/codec/register_rm_request_codec.go View File

@@ -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
}

+ 25
- 0
pkg/protocol/codec/register_rm_response_codec.go View File

@@ -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
}

+ 30
- 0
pkg/protocol/codec/register_tm_request_codec.go View File

@@ -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
}

+ 30
- 0
pkg/protocol/codec/register_tm_response_codec.go View File

@@ -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
}

+ 0
- 779
pkg/protocol/codec/seata_decoder.go View File

@@ -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
}

+ 0
- 563
pkg/protocol/codec/seata_encoder.go View File

@@ -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()
}

+ 1
- 0
pkg/protocol/message/request_message.go View File

@@ -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


+ 4
- 1
pkg/protocol/resource/resource.go View File

@@ -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


pkg/protocol/transaction/context.go → pkg/protocol/seatactx/context.go View File

@@ -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
} }
} }



+ 81
- 0
pkg/protocol/transaction/api/api.go View File

@@ -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
}

+ 0
- 96
pkg/protocol/transaction/executor/transactional_template.go View File

@@ -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)
}

+ 13
- 6
pkg/protocol/transaction/manager/global_transaction_manager.go View File

@@ -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
} }




+ 1
- 1
pkg/protocol/transaction/transaction_manager.go View File

@@ -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.


+ 17
- 17
pkg/protocol/transaction/transaction_status.go View File

@@ -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
) )

+ 5
- 5
pkg/remoting/getty/getty_client.go View File

@@ -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,
} }


+ 9
- 6
pkg/remoting/getty/getty_remoting.go View File

@@ -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)
} }


+ 7
- 7
pkg/remoting/getty/listener.go View File

@@ -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{}) {


+ 95
- 148
pkg/remoting/getty/readwriter.go View File

@@ -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
} }

+ 42
- 11
pkg/remoting/getty/rpc_client.go View File

@@ -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())




+ 6
- 6
pkg/remoting/getty/session_manager.go View File

@@ -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)


+ 3
- 0
pkg/remoting/processor/client/client_heart_beat_processon.go View File

@@ -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"


+ 3
- 0
pkg/remoting/processor/client/client_on_response_processor.go View File

@@ -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"


+ 3
- 0
pkg/remoting/processor/client/rm_branch_commit_processor.go View File

@@ -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"


+ 3
- 0
pkg/remoting/processor/client/rm_branch_rollback_processor.go View File

@@ -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"


+ 3
- 0
pkg/remoting/processor/remoting_processor.go View File

@@ -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"
) )




+ 3
- 0
pkg/rm/common/handler/rm_handler.go View File

@@ -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"


+ 4
- 1
pkg/rm/common/handler/rm_handler_facade.go View File

@@ -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 (


+ 4
- 1
pkg/rm/common/remoting/rm_remoting.go View File

@@ -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 (


+ 4
- 1
pkg/rm/resource_manager.go View File

@@ -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 (


+ 6
- 6
pkg/rm/tcc/tcc_resource.go View File

@@ -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)


+ 20
- 30
pkg/rm/tcc/tcc_service.go View File

@@ -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
} }




+ 4
- 1
test/rpc_remoting_client_test.go View File

@@ -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",


+ 36
- 9
test/tcc_service_test.go View File

@@ -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)
} }

+ 0
- 51
testdata/mock/mock_tcc_service.go View File

@@ -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
}

Loading…
Cancel
Save