blob: 881c562a50a7b94a15daa23b575d0f0d95959ddd [file] [log] [blame]
package session
import (
"bytes"
"github.com/pkg/errors"
"github.com/dk-lockdown/seata-golang/logging"
"github.com/dk-lockdown/seata-golang/meta"
"github.com/dk-lockdown/seata-golang/tc/config"
"github.com/dk-lockdown/seata-golang/util"
"vimagination.zapto.org/byteio"
)
type BranchSession struct{
Xid string
TransactionId int64
BranchId int64
ResourceGroupId string
ResourceId string
LockKey string
BranchType meta.BranchType
Status meta.BranchStatus
ClientId string
ApplicationData []byte
}
func NewBranchSession() *BranchSession {
return &BranchSession{}
}
func NewBranchSessionByGlobal(gs GlobalSession,
branchType meta.BranchType,
resourceId string,
applicationData []byte,
lockKeys string,
clientId string) *BranchSession {
bs := NewBranchSession()
bs.SetXid(gs.Xid)
bs.SetTransactionId(gs.TransactionId)
bs.SetBranchId(util.GeneratorUUID())
bs.SetBranchType(branchType)
bs.SetResourceId(resourceId)
bs.SetLockKey(lockKeys)
bs.SetClientId(clientId)
bs.SetApplicationData(applicationData)
return bs
}
func (bs *BranchSession) SetXid(xid string) *BranchSession {
bs.Xid = xid
return bs
}
func (bs *BranchSession) SetTransactionId(transactionId int64) *BranchSession {
bs.TransactionId = transactionId
return bs
}
func (bs *BranchSession) SetBranchId(branchId int64) *BranchSession {
bs.BranchId = branchId
return bs
}
func (bs *BranchSession) SetResourceGroupId(ResourceGroupId string) *BranchSession {
bs.ResourceGroupId = ResourceGroupId
return bs
}
func (bs *BranchSession) SetResourceId(resourceId string) *BranchSession {
bs.ResourceId = resourceId
return bs
}
func (bs *BranchSession) SetLockKey(lockKey string) *BranchSession {
bs.LockKey = lockKey
return bs
}
func (bs *BranchSession) SetBranchType(branchType meta.BranchType) *BranchSession {
bs.BranchType = branchType
return bs
}
func (bs *BranchSession) SetStatus(status meta.BranchStatus) *BranchSession {
bs.Status = status
return bs
}
func (bs *BranchSession) SetClientId(clientId string) *BranchSession {
bs.ClientId = clientId
return bs
}
func (bs *BranchSession) SetApplicationData(applicationData []byte) *BranchSession {
bs.ApplicationData = applicationData
return bs
}
func (bs *BranchSession) CompareTo(session *BranchSession) int {
return int(bs.BranchId - session.BranchId)
}
func (bs *BranchSession) Encode() ([]byte, error) {
var (
zero32 int32 = 0
zero16 int16 = 0
)
size := calBranchSessionSize(len(bs.ResourceId),len(bs.LockKey),len(bs.ClientId),len(bs.ApplicationData),len(bs.Xid))
if size > config.GetStoreConfig().MaxBranchSessionSize {
if bs.LockKey == "" {
logging.Logger.Errorf("branch session size exceeded, size : %d maxBranchSessionSize : %d", size, config.GetStoreConfig().MaxBranchSessionSize)
//todo compress
return nil, errors.New("branch session size exceeded.")
}
}
var b bytes.Buffer
w := byteio.BigEndianWriter{Writer: &b}
w.WriteInt64(bs.TransactionId)
w.WriteInt64(bs.BranchId)
if bs.ResourceId != "" {
w.WriteUint32(uint32(len(bs.ResourceId)))
w.WriteString( bs.ResourceId)
} else {
w.WriteInt32(zero32)
}
if bs.LockKey != "" {
w.WriteUint32(uint32(len(bs.LockKey)))
w.WriteString( bs.LockKey)
} else {
w.WriteInt32(zero32)
}
if bs.ClientId != "" {
w.WriteUint16(uint16(len(bs.ClientId)))
w.WriteString(bs.ClientId)
} else {
w.WriteInt16(zero16)
}
if bs.ApplicationData != nil {
w.WriteUint32(uint32(len(bs.ApplicationData)))
w.Write(bs.ApplicationData)
} else {
w.WriteInt32(zero32)
}
if bs.Xid != "" {
w.WriteUint32(uint32(len(bs.Xid)))
w.WriteString( bs.Xid)
} else {
w.WriteInt32(zero32)
}
w.WriteByte(byte(bs.BranchType))
w.WriteByte(byte(bs.Status))
return b.Bytes(), nil
}
func (bs *BranchSession) Decode(b []byte) {
var length32 uint32 = 0
var length16 uint16 = 0
r := byteio.BigEndianReader{Reader:bytes.NewReader(b)}
bs.TransactionId, _, _ = r.ReadInt64()
bs.BranchId, _, _ = r.ReadInt64()
length32, _, _ = r.ReadUint32()
if length32 > 0 { bs.ResourceId, _, _ = r.ReadString(int(length32)) }
length32, _, _ = r.ReadUint32()
if length32 > 0 { bs.LockKey, _, _ = r.ReadString(int(length32)) }
length16, _, _ = r.ReadUint16()
if length16 > 0 { bs.ClientId, _, _ = r.ReadString(int(length16)) }
length32, _, _ = r.ReadUint32()
if length32 > 0 {
bs.ApplicationData = make([]byte,int(length32))
r.Read(bs.ApplicationData)
}
length32, _, _ = r.ReadUint32()
if length32 > 0 { bs.Xid, _, _ = r.ReadString(int(length32)) }
branchType, _ := r.ReadByte()
bs.BranchType = meta.BranchType(branchType)
status, _ := r.ReadByte()
bs.Status = meta.BranchStatus(status)
}
func calBranchSessionSize(resourceIdLen int,
lockKeyLen int,
clientIdLen int,
applicationDataLen int,
xidLen int) int{
size := 8 + // transactionId
8 + // branchId
4 + // resourceIdBytes.length
4 + // lockKeyBytes.length
2 + // clientIdBytes.length
4 + // applicationDataBytes.length
4 + // xidBytes.size
1 + // statusCode
resourceIdLen +
lockKeyLen +
clientIdLen +
applicationDataLen +
xidLen +
1
return size
}