network/frame/data_frame.go

167 lines
4.0 KiB
Go

package frame
import (
"fmt"
coder "git.hpds.cc/Component/mq_coder"
"sync"
)
var dataFramePool sync.Pool
// DataFrame defines the data structure carried with user's data
type DataFrame struct {
metaFrame *MetaFrame
payloadFrame *PayloadFrame
}
func (d *DataFrame) String() string {
data := d.GetCarriage()
length := len(data)
if length > debugFrameSize {
data = data[:debugFrameSize]
}
return fmt.Sprintf("tid=%s | tag=%#x | source=%s | data[%d]=%# x", d.metaFrame.tid, d.Tag(), d.SourceId(), length, data)
}
// NewDataFrame create `DataFrame` with a transactionId string,
// consider change transactionID to UUID type later
func NewDataFrame() *DataFrame {
data := newDataFrame()
data.metaFrame.tid = randString()
return data
}
func newDataFrame() (data *DataFrame) {
v := dataFramePool.Get()
if v == nil {
data = new(DataFrame)
data.metaFrame = new(MetaFrame)
data.payloadFrame = new(PayloadFrame)
} else {
data = v.(*DataFrame)
}
return
}
// Clean cleans DataFrame.
// Note that:
// 1/ if the client is calling WriteFrame(), it will automatically invoke Clean(), so there is no need to call Clean() separately.
// 2/ The DataFrame will be unavailable after cleaned, do not access DataFrame after Clean() called.
func (d *DataFrame) Clean() {
// reset metadataFrame
d.metaFrame.tid = ""
d.metaFrame.metadata = d.metaFrame.metadata[:0]
d.metaFrame.sourceId = ""
d.metaFrame.broadcast = false
// reset payloadFrame
d.payloadFrame.Tag = Tag(0)
d.payloadFrame.Carriage = d.payloadFrame.Carriage[:0]
dataFramePool.Put(d)
}
// Type gets the type of Frame.
func (d *DataFrame) Type() Type {
return TagOfDataFrame
}
// Tag return the tag of carriage data.
func (d *DataFrame) Tag() Tag {
return d.payloadFrame.Tag
}
// SetCarriage set user's raw data in `DataFrame`
func (d *DataFrame) SetCarriage(tag Tag, carriage []byte) {
d.payloadFrame = &PayloadFrame{
Tag: tag,
Carriage: carriage,
}
}
// GetCarriage return user's raw data in `DataFrame`
func (d *DataFrame) GetCarriage() []byte {
return d.payloadFrame.Carriage
}
// TransactionId return transactionId string
func (d *DataFrame) TransactionId() string {
return d.metaFrame.TransactionId()
}
// SetTransactionId set transactionId string
func (d *DataFrame) SetTransactionId(transactionId string) {
d.metaFrame.SetTransactionId(transactionId)
}
// GetMetaFrame return MetaFrame.
func (d *DataFrame) GetMetaFrame() *MetaFrame {
return d.metaFrame
}
// GetDataTag return the Tag of user's data
func (d *DataFrame) GetDataTag() Tag {
return d.payloadFrame.Tag
}
// SetSourceId set the source id.
func (d *DataFrame) SetSourceId(sourceId string) {
d.metaFrame.SetSourceId(sourceId)
}
// SourceId returns source id
func (d *DataFrame) SourceId() string {
return d.metaFrame.SourceId()
}
// SetBroadcast set broadcast mode
func (d *DataFrame) SetBroadcast(enabled bool) {
d.metaFrame.SetBroadcast(enabled)
}
// IsBroadcast returns the broadcast mode is enabled
func (d *DataFrame) IsBroadcast() bool {
return d.metaFrame.IsBroadcast()
}
// Encode return coder encoded bytes of `DataFrame`
func (d *DataFrame) Encode() []byte {
data := coder.NewNodePacketEncoder(byte(d.Type()))
// MetaFrame
data.AddBytes(d.metaFrame.Encode())
// PayloadFrame
data.AddBytes(d.payloadFrame.Encode())
return data.Encode()
}
// DecodeToDataFrame decode coder encoded bytes to `DataFrame`
func DecodeToDataFrame(buf []byte) (*DataFrame, error) {
packet := coder.NodePacket{}
_, err := coder.DecodeToNodePacket(buf, &packet)
if err != nil {
return nil, err
}
data := new(DataFrame)
data.metaFrame = new(MetaFrame)
data.payloadFrame = new(PayloadFrame)
if metaBlock, ok := packet.NodePackets[byte(TagOfMetaFrame)]; ok {
err := DecodeToMetaFrame(metaBlock.GetRawBytes(), data.metaFrame)
if err != nil {
return nil, err
}
}
if payloadBlock, ok := packet.NodePackets[byte(TagOfPayloadFrame)]; ok {
err := DecodeToPayloadFrame(payloadBlock.GetRawBytes(), data.payloadFrame)
if err != nil {
return nil, err
}
}
return data, nil
}