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 }