github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/catalog/command.go (about) 1 // Copyright 2021 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 catalog 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "fmt" 21 "io" 22 23 "github.com/matrixorigin/matrixone/pkg/container/types" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal" 28 ) 29 30 const ( 31 CmdUpdateDatabase = int16(256) + iota 32 CmdUpdateTable 33 CmdUpdateSegment 34 CmdUpdateBlock 35 ) 36 37 var cmdNames = map[int16]string{ 38 CmdUpdateDatabase: "UDB", 39 CmdUpdateTable: "UTBL", 40 CmdUpdateSegment: "USEG", 41 CmdUpdateBlock: "UBLK", 42 } 43 44 func CmdName(t int16) string { 45 return cmdNames[t] 46 } 47 48 func init() { 49 txnif.RegisterCmdFactory(CmdUpdateDatabase, func(cmdType int16) txnif.TxnCmd { 50 return newEmptyEntryCmd(cmdType) 51 }) 52 txnif.RegisterCmdFactory(CmdUpdateTable, func(cmdType int16) txnif.TxnCmd { 53 return newEmptyEntryCmd(cmdType) 54 }) 55 txnif.RegisterCmdFactory(CmdUpdateSegment, func(cmdType int16) txnif.TxnCmd { 56 return newEmptyEntryCmd(cmdType) 57 }) 58 txnif.RegisterCmdFactory(CmdUpdateBlock, func(cmdType int16) txnif.TxnCmd { 59 return newEmptyEntryCmd(cmdType) 60 }) 61 } 62 63 type EntryCommand struct { 64 *txnbase.BaseCustomizedCmd 65 cmdType int16 66 entry BaseEntry 67 DBID uint64 68 TableID uint64 69 SegmentID uint64 70 DB *DBEntry 71 Table *TableEntry 72 Segment *SegmentEntry 73 Block *BlockEntry 74 } 75 76 func newEmptyEntryCmd(cmdType int16) *EntryCommand { 77 impl := &EntryCommand{ 78 DB: nil, 79 cmdType: cmdType, 80 } 81 impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(0, impl) 82 return impl 83 } 84 85 func newBlockCmd(id uint32, cmdType int16, entry *BlockEntry) *EntryCommand { 86 impl := &EntryCommand{ 87 DB: entry.GetSegment().GetTable().GetDB(), 88 Table: entry.GetSegment().GetTable(), 89 Segment: entry.GetSegment(), 90 Block: entry, 91 cmdType: cmdType, 92 entry: entry.MetaBaseEntry, 93 } 94 impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(id, impl) 95 return impl 96 } 97 98 func newSegmentCmd(id uint32, cmdType int16, entry *SegmentEntry) *EntryCommand { 99 impl := &EntryCommand{ 100 DB: entry.GetTable().GetDB(), 101 Table: entry.GetTable(), 102 Segment: entry, 103 cmdType: cmdType, 104 entry: entry.MetaBaseEntry, 105 } 106 impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(id, impl) 107 return impl 108 } 109 110 func newTableCmd(id uint32, cmdType int16, entry *TableEntry) *EntryCommand { 111 impl := &EntryCommand{ 112 DB: entry.GetDB(), 113 Table: entry, 114 cmdType: cmdType, 115 entry: entry.TableBaseEntry, 116 } 117 impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(id, impl) 118 return impl 119 } 120 121 func newDBCmd(id uint32, cmdType int16, entry *DBEntry) *EntryCommand { 122 impl := &EntryCommand{ 123 DB: entry, 124 cmdType: cmdType, 125 } 126 if entry != nil { 127 impl.entry = entry.DBBaseEntry 128 } 129 impl.BaseCustomizedCmd = txnbase.NewBaseCustomizedCmd(id, impl) 130 return impl 131 } 132 133 func (cmd *EntryCommand) Desc() string { 134 s := fmt.Sprintf("CmdName=%s;%s;TS=%s;CSN=%d", CmdName(cmd.cmdType), cmd.IDString(), cmd.GetTs().ToString(), cmd.ID) 135 return s 136 } 137 138 func (cmd *EntryCommand) GetLogIndex() *wal.Index { 139 if cmd.entry == nil { 140 return nil 141 } 142 return cmd.entry.GetLatestNodeLocked().GetLogIndex() 143 } 144 func (cmd *EntryCommand) SetReplayTxn(txn txnif.AsyncTxn) { 145 switch cmd.cmdType { 146 case CmdUpdateBlock, CmdUpdateSegment: 147 cmd.entry.GetLatestNodeLocked().(*MetadataMVCCNode).Txn = txn 148 case CmdUpdateTable: 149 cmd.entry.GetLatestNodeLocked().(*TableMVCCNode).Txn = txn 150 case CmdUpdateDatabase: 151 cmd.entry.GetLatestNodeLocked().(*DBMVCCNode).Txn = txn 152 default: 153 panic(fmt.Sprintf("invalid command type %d", cmd.cmdType)) 154 } 155 } 156 func (cmd *EntryCommand) ApplyCommit() { 157 switch cmd.cmdType { 158 case CmdUpdateBlock, CmdUpdateSegment, CmdUpdateTable, CmdUpdateDatabase: 159 node := cmd.entry.GetLatestNodeLocked() 160 if node.Is1PC() { 161 return 162 } 163 if err := node.ApplyCommit(nil); err != nil { 164 panic(err) 165 } 166 default: 167 panic(fmt.Sprintf("invalid command type %d", cmd.cmdType)) 168 } 169 } 170 func (cmd *EntryCommand) ApplyRollback() { 171 switch cmd.cmdType { 172 case CmdUpdateBlock, CmdUpdateSegment, CmdUpdateTable, CmdUpdateDatabase: 173 node := cmd.entry.GetLatestNodeLocked().(*MetadataMVCCNode) 174 if node.Is1PC() { 175 return 176 } 177 node.ApplyRollback(nil) 178 default: 179 panic(fmt.Sprintf("invalid command type %d", cmd.cmdType)) 180 } 181 } 182 func (cmd *EntryCommand) GetTs() types.TS { 183 ts := cmd.entry.GetLatestNodeLocked().GetPrepare() 184 return ts 185 } 186 func (cmd *EntryCommand) IDString() string { 187 s := "" 188 dbid, id := cmd.GetID() 189 switch cmd.cmdType { 190 case CmdUpdateDatabase: 191 s = fmt.Sprintf("%sDB=%d", s, dbid) 192 case CmdUpdateTable: 193 s = fmt.Sprintf("%sDB=%d;CommonID=%s", s, dbid, id.TableString()) 194 case CmdUpdateSegment: 195 s = fmt.Sprintf("%sDB=%d;CommonID=%s", s, dbid, id.SegmentString()) 196 case CmdUpdateBlock: 197 s = fmt.Sprintf("%sDB=%d;CommonID=%s", s, dbid, id.BlockString()) 198 } 199 return s 200 } 201 func (cmd *EntryCommand) GetID() (uint64, *common.ID) { 202 id := &common.ID{} 203 dbid := uint64(0) 204 switch cmd.cmdType { 205 case CmdUpdateDatabase: 206 dbid = cmd.entry.GetID() 207 case CmdUpdateTable: 208 if cmd.DBID != 0 { 209 dbid = cmd.DBID 210 id.TableID = cmd.Table.ID 211 } else { 212 dbid = cmd.Table.db.ID 213 id.TableID = cmd.entry.GetID() 214 } 215 case CmdUpdateSegment: 216 if cmd.DBID != 0 { 217 dbid = cmd.DBID 218 id.TableID = cmd.TableID 219 id.SegmentID = cmd.entry.GetID() 220 } else { 221 dbid = cmd.DB.ID 222 id.TableID = cmd.Table.ID 223 id.SegmentID = cmd.Segment.ID 224 } 225 case CmdUpdateBlock: 226 if cmd.DBID != 0 { 227 dbid = cmd.DBID 228 id.TableID = cmd.TableID 229 id.SegmentID = cmd.SegmentID 230 id.BlockID = cmd.entry.GetID() 231 } else { 232 dbid = cmd.DB.ID 233 id.TableID = cmd.Table.ID 234 id.SegmentID = cmd.Segment.ID 235 id.BlockID = cmd.entry.GetID() 236 } 237 } 238 return dbid, id 239 } 240 241 func (cmd *EntryCommand) String() string { 242 s := fmt.Sprintf("CmdName=%s;%s;TS=%s;CSN=%d;BaseEntry=%s", CmdName(cmd.cmdType), cmd.IDString(), cmd.GetTs().ToString(), cmd.ID, cmd.entry.String()) 243 return s 244 } 245 246 func (cmd *EntryCommand) VerboseString() string { 247 s := fmt.Sprintf("CmdName=%s;%s;TS=%s;CSN=%d;BaseEntry=%s", CmdName(cmd.cmdType), cmd.IDString(), cmd.GetTs().ToString(), cmd.ID, cmd.entry.String()) 248 switch cmd.cmdType { 249 case CmdUpdateTable: 250 s = fmt.Sprintf("%s;Schema=%v", s, cmd.Table.schema.String()) 251 } 252 return s 253 } 254 func (cmd *EntryCommand) GetType() int16 { return cmd.cmdType } 255 256 func (cmd *EntryCommand) WriteTo(w io.Writer) (n int64, err error) { 257 if err = binary.Write(w, binary.BigEndian, cmd.GetType()); err != nil { 258 return 259 } 260 if err = binary.Write(w, binary.BigEndian, cmd.ID); err != nil { 261 return 262 } 263 var sn int64 264 n = 4 + 2 265 266 if err = binary.Write(w, binary.BigEndian, cmd.entry.GetID()); err != nil { 267 return 268 } 269 n += 4 270 switch cmd.GetType() { 271 case CmdUpdateDatabase: 272 if sn, err = common.WriteString(cmd.DB.name, w); err != nil { 273 return 274 } 275 n += sn 276 if sn, err = cmd.DB.acInfo.WriteTo(w); err != nil { 277 return 278 } 279 n += sn 280 if sn, err = cmd.DB.WriteOneNodeTo(w); err != nil { 281 return 282 } 283 n += sn 284 case CmdUpdateTable: 285 if err = binary.Write(w, binary.BigEndian, cmd.Table.db.ID); err != nil { 286 return 287 } 288 n += 8 289 if sn, err = cmd.Table.WriteOneNodeTo(w); err != nil { 290 return 291 } 292 n += sn 293 var schemaBuf []byte 294 if schemaBuf, err = cmd.Table.schema.Marshal(); err != nil { 295 return 296 } 297 if _, err = w.Write(schemaBuf); err != nil { 298 return 299 } 300 n += int64(len(schemaBuf)) 301 case CmdUpdateSegment: 302 if err = binary.Write(w, binary.BigEndian, cmd.DB.ID); err != nil { 303 return 304 } 305 if err = binary.Write(w, binary.BigEndian, cmd.Table.ID); err != nil { 306 return 307 } 308 if err = binary.Write(w, binary.BigEndian, cmd.Segment.state); err != nil { 309 return 310 } 311 if err = binary.Write(w, binary.BigEndian, cmd.Segment.sorted); err != nil { 312 return 313 } 314 n += 8 + 8 + 1 + 1 315 var n2 int64 316 n2, err = cmd.entry.WriteOneNodeTo(w) 317 if err != nil { 318 return 319 } 320 n += n2 321 case CmdUpdateBlock: 322 if err = binary.Write(w, binary.BigEndian, cmd.DB.ID); err != nil { 323 return 324 } 325 if err = binary.Write(w, binary.BigEndian, cmd.Table.ID); err != nil { 326 return 327 } 328 if err = binary.Write(w, binary.BigEndian, cmd.Segment.ID); err != nil { 329 return 330 } 331 n += 8 + 8 + 8 332 if err = binary.Write(w, binary.BigEndian, cmd.Block.state); err != nil { 333 return 334 } 335 n += 1 336 var n2 int64 337 n2, err = cmd.entry.WriteOneNodeTo(w) 338 if err != nil { 339 return 340 } 341 n += n2 342 } 343 return 344 } 345 func (cmd *EntryCommand) Marshal() (buf []byte, err error) { 346 var bbuf bytes.Buffer 347 if _, err = cmd.WriteTo(&bbuf); err != nil { 348 return 349 } 350 buf = bbuf.Bytes() 351 return 352 } 353 func (cmd *EntryCommand) ReadFrom(r io.Reader) (n int64, err error) { 354 if err = binary.Read(r, binary.BigEndian, &cmd.ID); err != nil { 355 return 356 } 357 n += 4 358 var sn int64 359 switch cmd.GetType() { 360 case CmdUpdateDatabase: 361 entry := NewReplayDBBaseEntry() 362 if err = binary.Read(r, binary.BigEndian, &entry.ID); err != nil { 363 return 364 } 365 n += 8 366 cmd.entry = entry 367 cmd.DB = NewReplayDBEntry() 368 if cmd.DB.name, sn, err = common.ReadString(r); err != nil { 369 return 370 } 371 n += sn 372 if sn, err = cmd.DB.acInfo.ReadFrom(r); err != nil { 373 return 374 } 375 n += sn 376 if sn, err = cmd.entry.ReadOneNodeFrom(r); err != nil { 377 return 378 } 379 n += sn 380 cmd.DB.DBBaseEntry = cmd.entry.(*DBBaseEntry) 381 case CmdUpdateTable: 382 entry := NewReplayTableBaseEntry() 383 if err = binary.Read(r, binary.BigEndian, &entry.ID); err != nil { 384 return 385 } 386 n += 8 387 cmd.entry = entry 388 if err = binary.Read(r, binary.BigEndian, &cmd.DBID); err != nil { 389 return 390 } 391 392 n += 8 393 if sn, err = cmd.entry.ReadOneNodeFrom(r); err != nil { 394 return 395 } 396 n += sn 397 cmd.Table = NewReplayTableEntry() 398 cmd.Table.TableBaseEntry = cmd.entry.(*TableBaseEntry) 399 cmd.Table.schema = NewEmptySchema("") 400 if sn, err = cmd.Table.schema.ReadFrom(r); err != nil { 401 return 402 } 403 n += sn 404 case CmdUpdateSegment: 405 entry := NewReplayMetaBaseEntry() 406 if err = binary.Read(r, binary.BigEndian, &entry.ID); err != nil { 407 return 408 } 409 n += 8 410 cmd.entry = entry 411 if err = binary.Read(r, binary.BigEndian, &cmd.DBID); err != nil { 412 return 413 } 414 n += 8 415 if err = binary.Read(r, binary.BigEndian, &cmd.TableID); err != nil { 416 return 417 } 418 n += 8 419 var state EntryState 420 if err = binary.Read(r, binary.BigEndian, &state); err != nil { 421 return 422 } 423 n += 1 424 var sorted bool 425 if err = binary.Read(r, binary.BigEndian, &sorted); err != nil { 426 return 427 } 428 n += 1 429 if sn, err = cmd.entry.ReadOneNodeFrom(r); err != nil { 430 return 431 } 432 n += sn 433 cmd.Segment = NewReplaySegmentEntry() 434 cmd.Segment.MetaBaseEntry = cmd.entry.(*MetaBaseEntry) 435 cmd.Segment.state = state 436 cmd.Segment.sorted = sorted 437 case CmdUpdateBlock: 438 entry := NewReplayMetaBaseEntry() 439 if err = binary.Read(r, binary.BigEndian, &entry.ID); err != nil { 440 return 441 } 442 n += 8 443 cmd.entry = entry 444 if err = binary.Read(r, binary.BigEndian, &cmd.DBID); err != nil { 445 return 446 } 447 if err = binary.Read(r, binary.BigEndian, &cmd.TableID); err != nil { 448 return 449 } 450 if err = binary.Read(r, binary.BigEndian, &cmd.SegmentID); err != nil { 451 return 452 } 453 var state EntryState 454 if err = binary.Read(r, binary.BigEndian, &state); err != nil { 455 return 456 } 457 var n2 int64 458 n2, err = cmd.entry.ReadOneNodeFrom(r) 459 if err != nil { 460 return 461 } 462 n += n2 463 cmd.Block = NewReplayBlockEntry() 464 cmd.Block.MetaBaseEntry = cmd.entry.(*MetaBaseEntry) 465 cmd.Block.state = state 466 } 467 return 468 } 469 470 func (cmd *EntryCommand) Unmarshal(buf []byte) (err error) { 471 bbuf := bytes.NewBuffer(buf) 472 _, err = cmd.ReadFrom(bbuf) 473 return 474 }