github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/table.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 txnimpl 16 17 import ( 18 "fmt" 19 "time" 20 21 "github.com/RoaringBitmap/roaring" 22 "github.com/matrixorigin/matrixone/pkg/common/moerr" 23 "github.com/matrixorigin/matrixone/pkg/container/types" 24 "github.com/matrixorigin/matrixone/pkg/logutil" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" 28 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle" 29 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 30 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model" 31 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables/updates" 32 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal" 33 ) 34 35 var ( 36 ErrDuplicateNode = moerr.NewInternalErrorNoCtx("tae: duplicate node") 37 ) 38 39 type txnEntries struct { 40 entries []txnif.TxnEntry 41 mask *roaring.Bitmap 42 } 43 44 func newTxnEntries() *txnEntries { 45 return &txnEntries{ 46 entries: make([]txnif.TxnEntry, 0), 47 mask: roaring.New(), 48 } 49 } 50 51 func (entries *txnEntries) Len() int { 52 return len(entries.entries) 53 } 54 55 func (entries *txnEntries) Append(entry txnif.TxnEntry) { 56 entries.entries = append(entries.entries, entry) 57 } 58 59 func (entries *txnEntries) Delete(idx int) { 60 entries.mask.Add(uint32(idx)) 61 } 62 63 func (entries *txnEntries) IsDeleted(idx int) bool { 64 return entries.mask.ContainsInt(idx) 65 } 66 67 func (entries *txnEntries) AnyDelete() bool { 68 return !entries.mask.IsEmpty() 69 } 70 71 func (entries *txnEntries) Close() { 72 entries.mask = nil 73 entries.entries = nil 74 } 75 76 type deleteNode struct { 77 txnif.DeleteNode 78 idx int 79 } 80 81 func newDeleteNode(node txnif.DeleteNode, idx int) *deleteNode { 82 return &deleteNode{ 83 DeleteNode: node, 84 idx: idx, 85 } 86 } 87 88 type txnTable struct { 89 store *txnStore 90 createEntry txnif.TxnEntry 91 dropEntry txnif.TxnEntry 92 localSegment *localSegment 93 deleteNodes map[common.ID]*deleteNode 94 entry *catalog.TableEntry 95 schema *catalog.Schema 96 logs []wal.LogEntry 97 maxSegId uint64 98 maxBlkId uint64 99 100 txnEntries *txnEntries 101 csnStart uint32 102 103 idx int 104 } 105 106 func newTxnTable(store *txnStore, entry *catalog.TableEntry) *txnTable { 107 tbl := &txnTable{ 108 store: store, 109 entry: entry, 110 schema: entry.GetSchema(), 111 deleteNodes: make(map[common.ID]*deleteNode), 112 logs: make([]wal.LogEntry, 0), 113 txnEntries: newTxnEntries(), 114 } 115 return tbl 116 } 117 118 func (tbl *txnTable) PrePreareTransfer() (err error) { 119 ts := types.BuildTS(time.Now().UTC().UnixNano(), 0) 120 return tbl.TransferDeletes(ts) 121 } 122 123 func (tbl *txnTable) TransferDeleteIntent( 124 id *common.ID, 125 row uint32) (changed bool, nid *common.ID, nrow uint32, err error) { 126 pinned, err := tbl.store.transferTable.Pin(*id) 127 if err != nil { 128 err = nil 129 return 130 } 131 defer pinned.Close() 132 entry, err := tbl.store.warChecker.CacheGet( 133 tbl.entry.GetDB().ID, 134 id.TableID, 135 id.SegmentID, 136 id.BlockID) 137 if err != nil { 138 panic(err) 139 } 140 ts := types.BuildTS(time.Now().UTC().UnixNano(), 0) 141 if err = readWriteConfilictCheck(entry.MetaBaseEntry, ts); err == nil { 142 return 143 } 144 err = nil 145 nid = &common.ID{ 146 TableID: id.TableID, 147 } 148 rowID, ok := pinned.Item().Transfer(row) 149 if !ok { 150 err = moerr.NewTxnWWConflictNoCtx() 151 return 152 } 153 changed = true 154 nid.SegmentID, nid.BlockID, nrow = model.DecodePhyAddrKey(rowID) 155 return 156 } 157 158 func (tbl *txnTable) TransferDeletes(ts types.TS) (err error) { 159 if tbl.store.transferTable == nil { 160 return 161 } 162 if len(tbl.deleteNodes) == 0 { 163 return 164 } 165 for id, node := range tbl.deleteNodes { 166 // search the read set to check wether the delete node relevant 167 // block was deleted. 168 // if not deleted, go to next 169 // if deleted, try to transfer the delete node 170 if err = tbl.store.warChecker.checkOne( 171 &id, 172 ts, 173 ); err == nil { 174 continue 175 } 176 177 // if the error is not a r-w conflict. something wrong really happened 178 if !moerr.IsMoErrCode(err, moerr.ErrTxnRWConflict) { 179 return 180 } 181 182 // try to transfer the delete node 183 // here are some possible returns 184 // nil: transferred successfully 185 // ErrTxnRWConflict: the target block was also be compacted 186 // ErrTxnWWConflict: w-w error 187 if _, err = tbl.TransferDelete(&id, node); err != nil { 188 return 189 } 190 } 191 return 192 } 193 194 func (tbl *txnTable) recurTransferDelete( 195 memo map[uint64]*common.PinnedItem[*model.TransferHashPage], 196 page *model.TransferHashPage, 197 id *common.ID, 198 row uint32, 199 depth int) (err error) { 200 201 var page2 *common.PinnedItem[*model.TransferHashPage] 202 203 rowID, ok := page.Transfer(row) 204 if !ok { 205 err = moerr.NewTxnWWConflictNoCtx() 206 msg := fmt.Sprintf("table-%d blk-%d delete row-%d depth-%d", 207 id.TableID, 208 id.BlockID, 209 row, 210 depth) 211 logutil.Warnf("[ts=%s]TransferDelete: %v", 212 tbl.store.txn.GetStartTS().ToString(), 213 msg) 214 return 215 } 216 segmentID, blockID, offset := model.DecodePhyAddrKey(rowID) 217 newID := &common.ID{ 218 TableID: id.TableID, 219 SegmentID: segmentID, 220 BlockID: blockID, 221 } 222 if page2, ok = memo[blockID]; !ok { 223 if page2, err = tbl.store.transferTable.Pin(*newID); err != nil { 224 err = nil 225 } else { 226 memo[blockID] = page2 227 } 228 } 229 if page2 != nil { 230 return tbl.recurTransferDelete( 231 memo, 232 page2.Item(), 233 newID, 234 offset, 235 depth+1) 236 } 237 if err = tbl.RangeDelete(newID, offset, offset, handle.DT_Normal); err != nil { 238 return 239 } 240 logutil.Infof("depth-%d transfer delete from blk-%d row-%d to blk-%d row-%d", 241 depth, 242 id.BlockID, 243 row, 244 blockID, 245 offset) 246 return 247 } 248 249 func (tbl *txnTable) TransferDelete(id *common.ID, node *deleteNode) (transferred bool, err error) { 250 memo := make(map[uint64]*common.PinnedItem[*model.TransferHashPage]) 251 logutil.Info("[Start]", 252 common.AnyField("txn-start-ts", tbl.store.txn.GetStartTS().ToString()), 253 common.OperationField("transfer-deletes"), 254 common.OperandField(id.BlockString())) 255 defer func() { 256 logutil.Info("[End]", 257 common.AnyField("txn-start-ts", tbl.store.txn.GetStartTS().ToString()), 258 common.OperationField("transfer-deletes"), 259 common.OperandField(id.BlockString()), 260 common.ErrorField(err)) 261 for _, m := range memo { 262 m.Close() 263 } 264 }() 265 266 pinned, err := tbl.store.transferTable.Pin(*id) 267 // cannot find a transferred record. maybe the transferred record was TTL'ed 268 // here we can convert the error back to r-w conflict 269 if err != nil { 270 err = moerr.NewTxnRWConflictNoCtx() 271 return 272 } 273 memo[id.BlockID] = pinned 274 275 rows := node.DeletedRows() 276 // logutil.Infof("TransferDelete deletenode %s", node.DeleteNode.(*updates.DeleteNode).GeneralVerboseString()) 277 page := pinned.Item() 278 depth := 0 279 for _, row := range rows { 280 if err = tbl.recurTransferDelete(memo, page, id, row, depth); err != nil { 281 return 282 } 283 } 284 285 // rollback transferred delete node. should not fail 286 if err = node.PrepareRollback(); err != nil { 287 panic(err) 288 } 289 if err = node.ApplyRollback(nil); err != nil { 290 panic(err) 291 } 292 293 tbl.commitTransferDeleteNode(id, node) 294 transferred = true 295 return 296 } 297 298 func (tbl *txnTable) commitTransferDeleteNode(id *common.ID, node *deleteNode) { 299 tbl.store.warChecker.Delete(id) 300 tbl.txnEntries.Delete(node.idx) 301 delete(tbl.deleteNodes, *id) 302 } 303 304 func (tbl *txnTable) LogSegmentID(sid uint64) { 305 if tbl.maxSegId < sid { 306 tbl.maxSegId = sid 307 } 308 } 309 310 func (tbl *txnTable) LogBlockID(bid uint64) { 311 if tbl.maxBlkId < bid { 312 tbl.maxBlkId = bid 313 } 314 } 315 316 func (tbl *txnTable) WaitSynced() { 317 for _, e := range tbl.logs { 318 if err := e.WaitDone(); err != nil { 319 panic(err) 320 } 321 e.Free() 322 } 323 } 324 325 func (tbl *txnTable) CollectCmd(cmdMgr *commandManager) (err error) { 326 tbl.csnStart = uint32(cmdMgr.GetCSN()) 327 for idx, txnEntry := range tbl.txnEntries.entries { 328 if tbl.txnEntries.IsDeleted(idx) { 329 continue 330 } 331 csn := cmdMgr.GetCSN() 332 cmd, err := txnEntry.MakeCommand(csn) 333 // logutil.Infof("%d-%d",csn,cmd.GetType()) 334 if err != nil { 335 return err 336 } 337 if cmd == nil { 338 panic(txnEntry) 339 } 340 cmdMgr.AddCmd(cmd) 341 } 342 if tbl.localSegment != nil { 343 if err = tbl.localSegment.CollectCmd(cmdMgr); err != nil { 344 return 345 } 346 } 347 return 348 } 349 350 func (tbl *txnTable) GetSegment(id uint64) (seg handle.Segment, err error) { 351 var meta *catalog.SegmentEntry 352 if meta, err = tbl.entry.GetSegmentByID(id); err != nil { 353 return 354 } 355 var ok bool 356 meta.RLock() 357 ok, err = meta.IsVisible(tbl.store.txn.GetStartTS(), meta.RWMutex) 358 meta.RUnlock() 359 if err != nil { 360 return 361 } 362 if !ok { 363 err = moerr.NewNotFoundNoCtx() 364 return 365 } 366 seg = newSegment(tbl, meta) 367 return 368 } 369 370 func (tbl *txnTable) SoftDeleteSegment(id uint64) (err error) { 371 txnEntry, err := tbl.entry.DropSegmentEntry(id, tbl.store.txn) 372 if err != nil { 373 return 374 } 375 tbl.store.IncreateWriteCnt() 376 if txnEntry != nil { 377 tbl.txnEntries.Append(txnEntry) 378 } 379 tbl.store.txn.GetMemo().AddSegment(tbl.entry.GetDB().GetID(), tbl.entry.ID, id) 380 return 381 } 382 383 func (tbl *txnTable) CreateSegment(is1PC bool) (seg handle.Segment, err error) { 384 return tbl.createSegment(catalog.ES_Appendable, is1PC) 385 } 386 387 func (tbl *txnTable) CreateNonAppendableSegment(is1PC bool) (seg handle.Segment, err error) { 388 return tbl.createSegment(catalog.ES_NotAppendable, is1PC) 389 } 390 391 func (tbl *txnTable) createSegment(state catalog.EntryState, is1PC bool) (seg handle.Segment, err error) { 392 var meta *catalog.SegmentEntry 393 var factory catalog.SegmentDataFactory 394 if tbl.store.dataFactory != nil { 395 factory = tbl.store.dataFactory.MakeSegmentFactory() 396 } 397 if meta, err = tbl.entry.CreateSegment(tbl.store.txn, state, factory); err != nil { 398 return 399 } 400 seg = newSegment(tbl, meta) 401 tbl.store.IncreateWriteCnt() 402 tbl.store.txn.GetMemo().AddSegment(tbl.entry.GetDB().ID, tbl.entry.ID, meta.ID) 403 if is1PC { 404 meta.Set1PC() 405 } 406 tbl.txnEntries.Append(meta) 407 return 408 } 409 410 func (tbl *txnTable) SoftDeleteBlock(id *common.ID) (err error) { 411 var seg *catalog.SegmentEntry 412 if seg, err = tbl.entry.GetSegmentByID(id.SegmentID); err != nil { 413 return 414 } 415 meta, err := seg.DropBlockEntry(id.BlockID, tbl.store.txn) 416 if err != nil { 417 return 418 } 419 tbl.store.IncreateWriteCnt() 420 tbl.store.txn.GetMemo().AddBlock(tbl.entry.GetDB().ID, id.TableID, id.SegmentID, id.BlockID) 421 if meta != nil { 422 tbl.txnEntries.Append(meta) 423 } 424 return 425 } 426 427 func (tbl *txnTable) LogTxnEntry(entry txnif.TxnEntry, readed []*common.ID) (err error) { 428 tbl.store.IncreateWriteCnt() 429 tbl.txnEntries.Append(entry) 430 for _, id := range readed { 431 // warChecker skip non-block read 432 if id.BlockID == 0 { 433 continue 434 } 435 436 // record block into read set 437 tbl.store.warChecker.InsertByID( 438 tbl.entry.GetDB().ID, 439 id.TableID, 440 id.SegmentID, 441 id.BlockID) 442 } 443 return 444 } 445 446 func (tbl *txnTable) GetBlock(id *common.ID) (blk handle.Block, err error) { 447 meta, err := tbl.store.warChecker.CacheGet( 448 tbl.entry.GetDB().ID, 449 id.TableID, 450 id.SegmentID, 451 id.BlockID) 452 if err != nil { 453 return 454 } 455 blk = buildBlock(tbl, meta) 456 return 457 } 458 459 func (tbl *txnTable) CreateNonAppendableBlock(sid uint64) (blk handle.Block, err error) { 460 return tbl.createBlock(sid, catalog.ES_NotAppendable, false) 461 } 462 463 func (tbl *txnTable) CreateNonAppendableBlockWithMeta( 464 sid uint64, 465 metaLoc string, 466 deltaLoc string) (blk handle.Block, err error) { 467 return tbl.createBlockWithMeta(sid, catalog.ES_NotAppendable, 468 false, metaLoc, deltaLoc) 469 } 470 471 func (tbl *txnTable) CreateBlock(sid uint64, is1PC bool) (blk handle.Block, err error) { 472 return tbl.createBlock(sid, catalog.ES_Appendable, is1PC) 473 } 474 475 func (tbl *txnTable) createBlock( 476 sid uint64, 477 state catalog.EntryState, 478 is1PC bool) (blk handle.Block, err error) { 479 var seg *catalog.SegmentEntry 480 if seg, err = tbl.entry.GetSegmentByID(sid); err != nil { 481 return 482 } 483 if !seg.IsAppendable() && state == catalog.ES_Appendable { 484 err = moerr.NewInternalErrorNoCtx("not appendable") 485 return 486 } 487 var factory catalog.BlockDataFactory 488 if tbl.store.dataFactory != nil { 489 factory = tbl.store.dataFactory.MakeBlockFactory() 490 } 491 meta, err := seg.CreateBlock(tbl.store.txn, state, factory) 492 if err != nil { 493 return 494 } 495 if is1PC { 496 meta.Set1PC() 497 } 498 tbl.store.IncreateWriteCnt() 499 id := meta.AsCommonID() 500 tbl.store.txn.GetMemo().AddBlock(tbl.entry.GetDB().ID, id.TableID, id.SegmentID, id.BlockID) 501 tbl.txnEntries.Append(meta) 502 return buildBlock(tbl, meta), err 503 } 504 505 func (tbl *txnTable) createBlockWithMeta( 506 sid uint64, 507 state catalog.EntryState, 508 is1PC bool, 509 metaLoc string, 510 deltaLoc string) (blk handle.Block, err error) { 511 var seg *catalog.SegmentEntry 512 if seg, err = tbl.entry.GetSegmentByID(sid); err != nil { 513 return 514 } 515 if !seg.IsAppendable() && state == catalog.ES_Appendable { 516 err = moerr.NewInternalErrorNoCtx("not appendable") 517 return 518 } 519 var factory catalog.BlockDataFactory 520 if tbl.store.dataFactory != nil { 521 factory = tbl.store.dataFactory.MakeBlockFactory() 522 } 523 meta, err := seg.CreateBlockWithMeta(tbl.store.txn, state, factory, metaLoc, deltaLoc) 524 if err != nil { 525 return 526 } 527 if is1PC { 528 meta.Set1PC() 529 } 530 tbl.store.IncreateWriteCnt() 531 id := meta.AsCommonID() 532 tbl.store.txn.GetMemo().AddBlock(tbl.entry.GetDB().ID, id.TableID, id.SegmentID, id.BlockID) 533 tbl.txnEntries.Append(meta) 534 return buildBlock(tbl, meta), err 535 } 536 537 func (tbl *txnTable) SetCreateEntry(e txnif.TxnEntry) { 538 if tbl.createEntry != nil { 539 panic("logic error") 540 } 541 tbl.store.IncreateWriteCnt() 542 tbl.store.txn.GetMemo().AddCatalogChange() 543 tbl.createEntry = e 544 tbl.txnEntries.Append(e) 545 } 546 547 func (tbl *txnTable) SetDropEntry(e txnif.TxnEntry) error { 548 if tbl.dropEntry != nil { 549 panic("logic error") 550 } 551 tbl.store.IncreateWriteCnt() 552 tbl.store.txn.GetMemo().AddCatalogChange() 553 tbl.dropEntry = e 554 tbl.txnEntries.Append(e) 555 return nil 556 } 557 558 func (tbl *txnTable) IsDeleted() bool { 559 return tbl.dropEntry != nil 560 } 561 562 func (tbl *txnTable) GetSchema() *catalog.Schema { 563 return tbl.schema 564 } 565 566 func (tbl *txnTable) GetMeta() *catalog.TableEntry { 567 return tbl.entry 568 } 569 570 func (tbl *txnTable) GetID() uint64 { 571 return tbl.entry.GetID() 572 } 573 574 func (tbl *txnTable) Close() error { 575 var err error 576 if tbl.localSegment != nil { 577 if err = tbl.localSegment.Close(); err != nil { 578 return err 579 } 580 tbl.localSegment = nil 581 } 582 tbl.deleteNodes = nil 583 tbl.logs = nil 584 tbl.txnEntries = nil 585 return nil 586 } 587 588 func (tbl *txnTable) AddDeleteNode(id *common.ID, node txnif.DeleteNode) error { 589 nid := *id 590 u := tbl.deleteNodes[nid] 591 if u != nil { 592 return ErrDuplicateNode 593 } 594 tbl.store.IncreateWriteCnt() 595 tbl.store.txn.GetMemo().AddBlock(tbl.entry.GetDB().ID, id.TableID, id.SegmentID, id.BlockID) 596 tbl.deleteNodes[nid] = newDeleteNode(node, tbl.txnEntries.Len()) 597 tbl.txnEntries.Append(node) 598 return nil 599 } 600 601 func (tbl *txnTable) Append(data *containers.Batch) (err error) { 602 if tbl.schema.HasPK() { 603 if err = tbl.DoBatchDedup(data.Vecs[tbl.schema.GetSingleSortKeyIdx()]); err != nil { 604 return 605 } 606 } 607 if tbl.localSegment == nil { 608 tbl.localSegment = newLocalSegment(tbl) 609 } 610 return tbl.localSegment.Append(data) 611 } 612 613 func (tbl *txnTable) AddBlksWithMetaLoc( 614 pkVecs []containers.Vector, 615 file string, 616 metaLocs []string, 617 flag int32) (err error) { 618 //TODO::If txn at CN had checked duplication against its snapshot and workspace, 619 // we should skip here. 620 if tbl.schema.HasPK() { 621 for _, v := range pkVecs { 622 if err = tbl.DoBatchDedup(v); err != nil { 623 return 624 } 625 } 626 } 627 if tbl.localSegment == nil { 628 //tbl.localSegment = newLocalSegmentWithID(tbl, sid) 629 tbl.localSegment = newLocalSegment(tbl) 630 } 631 return tbl.localSegment.AddBlksWithMetaLoc(pkVecs, file, metaLocs) 632 } 633 634 func (tbl *txnTable) RangeDeleteLocalRows(start, end uint32) (err error) { 635 if tbl.localSegment != nil { 636 err = tbl.localSegment.RangeDelete(start, end) 637 } 638 return 639 } 640 641 func (tbl *txnTable) LocalDeletesToString() string { 642 s := fmt.Sprintf("<txnTable-%d>[LocalDeletes]:\n", tbl.GetID()) 643 if tbl.localSegment != nil { 644 s = fmt.Sprintf("%s%s", s, tbl.localSegment.DeletesToString()) 645 } 646 return s 647 } 648 649 func (tbl *txnTable) IsLocalDeleted(row uint32) bool { 650 if tbl.localSegment == nil { 651 return false 652 } 653 return tbl.localSegment.IsDeleted(row) 654 } 655 656 func (tbl *txnTable) RangeDelete(id *common.ID, start, end uint32, dt handle.DeleteType) (err error) { 657 defer func() { 658 if err == nil { 659 return 660 } 661 // if moerr.IsMoErrCode(err, moerr.ErrTxnWWConflict) { 662 // moerr.NewTxnWriteConflictNoCtx("table-%d blk-%d delete rows from %d to %d", 663 // id.TableID, 664 // id.BlockID, 665 // start, 666 // end) 667 // } 668 if err != nil { 669 logutil.Infof("[ts=%s]: table-%d blk-%d delete rows from %d to %d %v", 670 tbl.store.txn.GetStartTS().ToString(), 671 id.TableID, 672 id.BlockID, 673 start, 674 end, 675 err) 676 } 677 }() 678 if isLocalSegment(id) { 679 err = tbl.RangeDeleteLocalRows(start, end) 680 return 681 } 682 node := tbl.deleteNodes[*id] 683 if node != nil { 684 // TODO: refactor 685 chain := node.GetChain().(*updates.DeleteChain) 686 mvcc := chain.GetController() 687 mvcc.Lock() 688 if err = mvcc.CheckNotDeleted(start, end, tbl.store.txn.GetStartTS()); err == nil { 689 node.RangeDeleteLocked(start, end) 690 } 691 mvcc.Unlock() 692 if err != nil { 693 tbl.store.warChecker.Insert(mvcc.GetEntry()) 694 } 695 return 696 } 697 blk, err := tbl.store.warChecker.CacheGet( 698 tbl.entry.GetDB().ID, 699 id.TableID, id.SegmentID, 700 id.BlockID) 701 if err != nil { 702 return 703 } 704 blkData := blk.GetBlockData() 705 node2, err := blkData.RangeDelete(tbl.store.txn, start, end, dt) 706 if err == nil { 707 if err = tbl.AddDeleteNode(id, node2); err != nil { 708 return 709 } 710 tbl.store.warChecker.Insert(blk) 711 } 712 return 713 } 714 715 func (tbl *txnTable) GetByFilter(filter *handle.Filter) (id *common.ID, offset uint32, err error) { 716 if tbl.localSegment != nil { 717 id, offset, err = tbl.localSegment.GetByFilter(filter) 718 if err == nil { 719 return 720 } 721 err = nil 722 } 723 h := newRelation(tbl) 724 blockIt := h.MakeBlockIt() 725 for blockIt.Valid() { 726 h := blockIt.GetBlock() 727 if h.IsUncommitted() { 728 blockIt.Next() 729 continue 730 } 731 offset, err = h.GetByFilter(filter) 732 // block := h.GetMeta().(*catalog.BlockEntry).GetBlockData() 733 // offset, err = block.GetByFilter(tbl.store.txn, filter) 734 if err == nil { 735 id = h.Fingerprint() 736 break 737 } 738 blockIt.Next() 739 } 740 if err == nil && id == nil { 741 err = moerr.NewNotFoundNoCtx() 742 } 743 return 744 } 745 746 func (tbl *txnTable) GetLocalValue(row uint32, col uint16) (v any, err error) { 747 if tbl.localSegment == nil { 748 return 749 } 750 return tbl.localSegment.GetValue(row, col) 751 } 752 753 func (tbl *txnTable) GetValue(id *common.ID, row uint32, col uint16) (v any, err error) { 754 if isLocalSegment(id) { 755 return tbl.localSegment.GetValue(row, col) 756 } 757 meta, err := tbl.store.warChecker.CacheGet( 758 tbl.entry.GetDB().ID, 759 id.TableID, 760 id.SegmentID, 761 id.BlockID) 762 if err != nil { 763 panic(err) 764 } 765 block := meta.GetBlockData() 766 return block.GetValue(tbl.store.txn, int(row), int(col)) 767 } 768 769 func (tbl *txnTable) UpdateMetaLoc(id *common.ID, metaloc string) (err error) { 770 meta, err := tbl.store.warChecker.CacheGet( 771 tbl.entry.GetDB().ID, 772 id.TableID, 773 id.SegmentID, 774 id.BlockID) 775 if err != nil { 776 panic(err) 777 } 778 isNewNode, err := meta.UpdateMetaLoc(tbl.store.txn, metaloc) 779 if err != nil { 780 return 781 } 782 if isNewNode { 783 tbl.txnEntries.Append(meta) 784 } 785 return 786 } 787 788 func (tbl *txnTable) UpdateDeltaLoc(id *common.ID, deltaloc string) (err error) { 789 meta, err := tbl.store.warChecker.CacheGet( 790 tbl.entry.GetDB().ID, 791 id.TableID, 792 id.SegmentID, 793 id.BlockID) 794 if err != nil { 795 panic(err) 796 } 797 isNewNode, err := meta.UpdateDeltaLoc(tbl.store.txn, deltaloc) 798 if err != nil { 799 return 800 } 801 if isNewNode { 802 tbl.txnEntries.Append(meta) 803 } 804 return 805 } 806 807 func (tbl *txnTable) UpdateConstraint(cstr []byte) (err error) { 808 tbl.store.IncreateWriteCnt() 809 tbl.store.txn.GetMemo().AddCatalogChange() 810 isNewNode, err := tbl.entry.UpdateConstraint(tbl.store.txn, cstr) 811 if isNewNode { 812 tbl.txnEntries.Append(tbl.entry) 813 } 814 return 815 } 816 817 func (tbl *txnTable) UncommittedRows() uint32 { 818 if tbl.localSegment == nil { 819 return 0 820 } 821 return tbl.localSegment.Rows() 822 } 823 func (tbl *txnTable) NeedRollback() bool { 824 return tbl.createEntry != nil && tbl.dropEntry != nil 825 } 826 827 // PrePrepareDedup do deduplication check for 1PC Commit or 2PC Prepare 828 func (tbl *txnTable) PrePrepareDedup() (err error) { 829 if tbl.localSegment == nil || !tbl.schema.HasPK() { 830 return 831 } 832 pkVecs := tbl.localSegment.GetPKVecs() 833 for _, pkVec := range pkVecs { 834 defer pkVec.Close() 835 err = tbl.DoPrecommitDedup(pkVec) 836 if err != nil { 837 return 838 } 839 } 840 return 841 } 842 843 // Dedup 1. checks whether these primary keys are duplicated in all the blocks 844 // which are visible and not dropped at txn's snapshot timestamp. 845 // 2. It is called when appending data into this table. 846 func (tbl *txnTable) Dedup(keys containers.Vector) (err error) { 847 h := newRelation(tbl) 848 it := newRelationBlockIt(h) 849 for it.Valid() { 850 blk := it.GetBlock().GetMeta().(*catalog.BlockEntry) 851 blkData := blk.GetBlockData() 852 if blkData == nil { 853 it.Next() 854 continue 855 } 856 var rowmask *roaring.Bitmap 857 if len(tbl.deleteNodes) > 0 { 858 fp := blk.AsCommonID() 859 deleteNode := tbl.deleteNodes[*fp] 860 if deleteNode != nil { 861 rowmask = deleteNode.GetRowMaskRefLocked() 862 } 863 } 864 if err = blkData.BatchDedup(tbl.store.txn, keys, rowmask, false); err != nil { 865 // logutil.Infof("%s, %s, %v", blk.String(), rowmask, err) 866 return 867 } 868 it.Next() 869 } 870 return 871 } 872 873 // DoPrecommitDedup 1. it do deduplication by traversing all the segments/blocks, and 874 // skipping over some blocks/segments which being active or drop-committed or aborted; 875 // 2. it is called when txn dequeues from preparing queue. 876 // 3. we should make this function run quickly as soon as possible. 877 // TODO::it would be used to do deduplication with the logtail. 878 func (tbl *txnTable) DoPrecommitDedup(pks containers.Vector) (err error) { 879 segIt := tbl.entry.MakeSegmentIt(false) 880 for segIt.Valid() { 881 seg := segIt.Get().GetPayload() 882 //FIXME::Where is this tbl.maxSegId assigned, it always be zero? 883 if seg.GetID() < tbl.maxSegId { 884 return 885 } 886 { 887 seg.RLock() 888 //FIXME:: Why need to wait committing here? waiting had happened at Dedup. 889 //needwait, txnToWait := seg.NeedWaitCommitting(tbl.store.txn.GetStartTS()) 890 //if needwait { 891 // seg.RUnlock() 892 // txnToWait.GetTxnState(true) 893 // seg.RLock() 894 //} 895 shouldSkip := seg.HasDropCommittedLocked() || seg.IsCreatingOrAborted() 896 seg.RUnlock() 897 if shouldSkip { 898 segIt.Next() 899 continue 900 } 901 } 902 segData := seg.GetSegmentData() 903 // TODO: Add a new batch dedup method later 904 if err = segData.BatchDedup(tbl.store.txn, pks); moerr.IsMoErrCode(err, moerr.ErrDuplicateEntry) { 905 return 906 } 907 if err == nil { 908 segIt.Next() 909 continue 910 } 911 var shouldSkip bool 912 err = nil 913 blkIt := seg.MakeBlockIt(false) 914 for blkIt.Valid() { 915 blk := blkIt.Get().GetPayload() 916 if blk.GetID() < tbl.maxBlkId { 917 return 918 } 919 { 920 blk.RLock() 921 shouldSkip = blk.HasDropCommittedLocked() || blk.IsCreatingOrAborted() 922 blk.RUnlock() 923 if shouldSkip { 924 blkIt.Next() 925 continue 926 } 927 } 928 blkData := blk.GetBlockData() 929 var rowmask *roaring.Bitmap 930 if len(tbl.deleteNodes) > 0 { 931 if tbl.store.warChecker.HasConflict(blk.ID) { 932 continue 933 } 934 fp := blk.AsCommonID() 935 deleteNode := tbl.deleteNodes[*fp] 936 if deleteNode != nil { 937 rowmask = deleteNode.GetRowMaskRefLocked() 938 } 939 } 940 if err = blkData.BatchDedup(tbl.store.txn, pks, rowmask, true); err != nil { 941 return 942 } 943 blkIt.Next() 944 } 945 segIt.Next() 946 } 947 return 948 } 949 950 func (tbl *txnTable) DoBatchDedup(key containers.Vector) (err error) { 951 index := NewSimpleTableIndex() 952 //Check whether primary key is duplicated. 953 if err = index.BatchInsert( 954 tbl.schema.GetSingleSortKey().Name, 955 key, 956 0, 957 key.Length(), 958 0, 959 true); err != nil { 960 return 961 } 962 963 if tbl.localSegment != nil { 964 //Check whether primary key is duplicated with localSegment. 965 if err = tbl.localSegment.BatchDedup(key); err != nil { 966 return 967 } 968 } 969 //Check whether primary key is duplicated with all the blocks which are visible to txn. 970 err = tbl.Dedup(key) 971 return 972 } 973 974 func (tbl *txnTable) BatchDedupLocal(bat *containers.Batch) (err error) { 975 if tbl.localSegment == nil || !tbl.schema.HasPK() { 976 return 977 } 978 err = tbl.localSegment.BatchDedup(bat.Vecs[tbl.schema.GetSingleSortKeyIdx()]) 979 return 980 } 981 982 func (tbl *txnTable) PrepareRollback() (err error) { 983 for idx, txnEntry := range tbl.txnEntries.entries { 984 if tbl.txnEntries.IsDeleted(idx) { 985 continue 986 } 987 if err = txnEntry.PrepareRollback(); err != nil { 988 break 989 } 990 } 991 return 992 } 993 994 func (tbl *txnTable) ApplyAppend() (err error) { 995 if tbl.localSegment != nil { 996 err = tbl.localSegment.ApplyAppend() 997 } 998 return 999 } 1000 1001 func (tbl *txnTable) PrePrepare() (err error) { 1002 if tbl.localSegment != nil { 1003 err = tbl.localSegment.PrepareApply() 1004 } 1005 return 1006 } 1007 1008 func (tbl *txnTable) PrepareCommit() (err error) { 1009 for idx, node := range tbl.txnEntries.entries { 1010 if tbl.txnEntries.IsDeleted(idx) { 1011 continue 1012 } 1013 if err = node.PrepareCommit(); err != nil { 1014 break 1015 } 1016 } 1017 return 1018 } 1019 1020 func (tbl *txnTable) PreApplyCommit() (err error) { 1021 return tbl.ApplyAppend() 1022 } 1023 1024 func (tbl *txnTable) ApplyCommit() (err error) { 1025 csn := tbl.csnStart 1026 for idx, node := range tbl.txnEntries.entries { 1027 if tbl.txnEntries.IsDeleted(idx) { 1028 continue 1029 } 1030 if node.Is1PC() { 1031 continue 1032 } 1033 if err = node.ApplyCommit(tbl.store.cmdMgr.MakeLogIndex(csn)); err != nil { 1034 break 1035 } 1036 csn++ 1037 } 1038 return 1039 } 1040 1041 func (tbl *txnTable) Apply1PCCommit() (err error) { 1042 for idx, node := range tbl.txnEntries.entries { 1043 if tbl.txnEntries.IsDeleted(idx) { 1044 continue 1045 } 1046 if !node.Is1PC() { 1047 continue 1048 } 1049 if err = node.ApplyCommit(tbl.store.cmdMgr.MakeLogIndex(tbl.csnStart)); err != nil { 1050 break 1051 } 1052 tbl.csnStart++ 1053 } 1054 return 1055 } 1056 func (tbl *txnTable) ApplyRollback() (err error) { 1057 csn := tbl.csnStart 1058 for idx, node := range tbl.txnEntries.entries { 1059 if tbl.txnEntries.IsDeleted(idx) { 1060 continue 1061 } 1062 if node.Is1PC() { 1063 continue 1064 } 1065 if err = node.ApplyRollback(tbl.store.cmdMgr.MakeLogIndex(csn)); err != nil { 1066 break 1067 } 1068 csn++ 1069 } 1070 return 1071 }