github.com/matrixorigin/matrixone@v0.7.0/pkg/pb/txn/txn.go (about)

     1  // Copyright 2021 - 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package txn
    16  
    17  import (
    18  	"bytes"
    19  	"encoding/hex"
    20  	"fmt"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    24  )
    25  
    26  const (
    27  	// SkipResponseFlag skip response.
    28  	SkipResponseFlag uint32 = 1
    29  )
    30  
    31  // NewTxnRequest create TxnRequest by CNOpRequest
    32  func NewTxnRequest(request *CNOpRequest) TxnRequest {
    33  	return TxnRequest{CNRequest: request}
    34  }
    35  
    36  // GetCNOpResponse returns the CNOpResponse from TxnResponse
    37  func GetCNOpResponse(response TxnResponse) CNOpResponse {
    38  	return *response.CNOpResponse
    39  }
    40  
    41  // HasFlag returns true if has the spec flag
    42  func (m TxnResponse) HasFlag(flag uint32) bool {
    43  	return m.Flag&flag > 0
    44  }
    45  
    46  // DebugString returns debug string
    47  func (m TxnRequest) DebugString() string {
    48  	return m.DebugStringWithPayload(true)
    49  }
    50  
    51  // DebugStringWithPayload returns debug string with payload bytes if
    52  // withPayload is true
    53  func (m TxnRequest) DebugStringWithPayload(withPayload bool) string {
    54  	var buffer bytes.Buffer
    55  
    56  	buffer.WriteString(fmt.Sprintf("%d: ", m.RequestID))
    57  
    58  	buffer.WriteString("<")
    59  	buffer.WriteString(m.Txn.DebugString())
    60  	buffer.WriteString(">/")
    61  
    62  	buffer.WriteString(m.Method.String())
    63  	buffer.WriteString("/")
    64  	buffer.WriteString(fmt.Sprintf("F-%d", m.Flag))
    65  
    66  	if withPayload && m.CNRequest != nil {
    67  		buffer.WriteString("/<")
    68  		buffer.WriteString(m.CNRequest.DebugString())
    69  		buffer.WriteString(">")
    70  	}
    71  	buffer.WriteString("/=><")
    72  	buffer.WriteString(m.GetTargetDN().DebugString())
    73  	buffer.WriteString(">")
    74  	return buffer.String()
    75  }
    76  
    77  // DebugString returns debug string
    78  func (m TxnError) DebugString() string {
    79  	return fmt.Sprintf("%d: %s", m.TxnErrCode, m.UnwrapError().Error())
    80  }
    81  
    82  // DebugString returns debug string
    83  func (m TxnResponse) DebugString() string {
    84  	var buffer bytes.Buffer
    85  
    86  	buffer.WriteString(fmt.Sprintf("%d: ",
    87  		m.RequestID))
    88  
    89  	if m.Txn != nil {
    90  		buffer.WriteString("<")
    91  		buffer.WriteString(m.Txn.DebugString())
    92  		buffer.WriteString(">/")
    93  	}
    94  
    95  	buffer.WriteString(m.Method.String())
    96  	buffer.WriteString("/")
    97  	buffer.WriteString(fmt.Sprintf("F:%d", m.Flag))
    98  
    99  	if m.TxnError != nil {
   100  		buffer.WriteString("/")
   101  		buffer.WriteString(m.TxnError.DebugString())
   102  	}
   103  
   104  	if m.CNOpResponse != nil {
   105  		buffer.WriteString("/")
   106  		buffer.WriteString(m.CNOpResponse.DebugString())
   107  	}
   108  
   109  	return buffer.String()
   110  }
   111  
   112  // DebugString returns debug string
   113  func (m CNOpRequest) DebugString() string {
   114  	return fmt.Sprintf("O:%d-D:%d", m.OpCode, len(m.Payload))
   115  }
   116  
   117  // DebugString returns debug string
   118  func (m CNOpResponse) DebugString() string {
   119  	return fmt.Sprintf("D:%d", len(m.Payload))
   120  }
   121  
   122  // DebugString returns debug string
   123  func (m TxnMeta) DebugString() string {
   124  	var buffer bytes.Buffer
   125  
   126  	buffer.WriteString(hex.EncodeToString(m.ID))
   127  	buffer.WriteString("/")
   128  	buffer.WriteString(m.Status.String())
   129  	buffer.WriteString("/S:")
   130  	buffer.WriteString(m.SnapshotTS.DebugString())
   131  
   132  	if !m.PreparedTS.IsEmpty() {
   133  		buffer.WriteString("/P:")
   134  		buffer.WriteString(m.PreparedTS.DebugString())
   135  	}
   136  
   137  	if !m.CommitTS.IsEmpty() {
   138  		buffer.WriteString("/C:")
   139  		buffer.WriteString(m.CommitTS.DebugString())
   140  	}
   141  
   142  	n := len(m.DNShards)
   143  	var buf bytes.Buffer
   144  	buf.WriteString("/<")
   145  	for idx, dn := range m.DNShards {
   146  		buf.WriteString(dn.DebugString())
   147  		if idx < n-1 {
   148  			buf.WriteString(", ")
   149  		}
   150  	}
   151  	buf.WriteString(">")
   152  	return buffer.String()
   153  }
   154  
   155  // GetTargetDN return dn shard ID that message need send to.
   156  func (m TxnRequest) GetTargetDN() metadata.DNShard {
   157  	switch m.Method {
   158  	case TxnMethod_Read, TxnMethod_Write, TxnMethod_DEBUG:
   159  		return m.CNRequest.Target
   160  	case TxnMethod_Commit:
   161  		return m.Txn.DNShards[0]
   162  	case TxnMethod_Rollback:
   163  		return m.Txn.DNShards[0]
   164  	case TxnMethod_Prepare:
   165  		return m.PrepareRequest.DNShard
   166  	case TxnMethod_GetStatus:
   167  		return m.GetStatusRequest.DNShard
   168  	case TxnMethod_CommitDNShard:
   169  		return m.CommitDNShardRequest.DNShard
   170  	case TxnMethod_RollbackDNShard:
   171  		return m.RollbackDNShardRequest.DNShard
   172  	default:
   173  		panic("unknown txn request method")
   174  	}
   175  }
   176  
   177  // SetID implement morpc Messgae
   178  func (m *TxnRequest) SetID(id uint64) {
   179  	m.RequestID = id
   180  }
   181  
   182  // GetID implement morpc Messgae
   183  func (m *TxnRequest) GetID() uint64 {
   184  	return m.RequestID
   185  }
   186  
   187  // GetPayloadField implement morpc PayloadMessgae
   188  func (m TxnRequest) GetPayloadField() []byte {
   189  	if m.CNRequest != nil {
   190  		return m.CNRequest.Payload
   191  	}
   192  	return nil
   193  }
   194  
   195  // SetPayloadField implement morpc PayloadMessgae
   196  func (m *TxnRequest) SetPayloadField(data []byte) {
   197  	if m.CNRequest != nil {
   198  		m.CNRequest.Payload = data
   199  	}
   200  }
   201  
   202  // SetID implement morpc Messgae
   203  func (m *TxnResponse) SetID(id uint64) {
   204  	m.RequestID = id
   205  }
   206  
   207  // GetID implement morpc Messgae
   208  func (m *TxnResponse) GetID() uint64 {
   209  	return m.RequestID
   210  }
   211  
   212  // RequestsDebugString returns requests debug string
   213  func RequestsDebugString(requests []TxnRequest, withPayload bool) string {
   214  	n := len(requests)
   215  	var buf bytes.Buffer
   216  	buf.WriteString("[")
   217  	for idx, req := range requests {
   218  		buf.WriteString(req.DebugStringWithPayload(withPayload))
   219  		if idx < n-1 {
   220  			buf.WriteString(", ")
   221  		}
   222  	}
   223  	buf.WriteString("]")
   224  	return buf.String()
   225  }
   226  
   227  // ResponsesDebugString returns responses debug string
   228  func ResponsesDebugString(responses []TxnResponse) string {
   229  	n := len(responses)
   230  	var buf bytes.Buffer
   231  	buf.WriteString("[")
   232  	for idx, resp := range responses {
   233  		buf.WriteString(resp.DebugString())
   234  		if idx < n-1 {
   235  			buf.WriteString(", ")
   236  		}
   237  	}
   238  	buf.WriteString("]")
   239  	return buf.String()
   240  }
   241  
   242  // WrapError wrapper error to TxnError
   243  func WrapError(err error, internalCode uint16) *TxnError {
   244  	if me, ok := err.(*moerr.Error); ok {
   245  		data, e := me.MarshalBinary()
   246  		if e != nil {
   247  			panic(e)
   248  		}
   249  		v := &TxnError{Error: data, Code: uint32(me.ErrorCode())}
   250  		v.TxnErrCode = v.Code
   251  		if internalCode != 0 {
   252  			v.TxnErrCode = uint32(internalCode)
   253  		}
   254  		return v
   255  	}
   256  
   257  	panic("only moerr supported")
   258  }
   259  
   260  // UnwrapError unwrap the moerr from the TxnError
   261  func (m TxnError) UnwrapError() error {
   262  	err := &moerr.Error{}
   263  	if e := err.UnmarshalBinary(m.Error); e != nil {
   264  		panic(e)
   265  	}
   266  	return err
   267  }