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  }