github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/txndb.go (about)

     1  // Copyright 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 txnimpl
    16  
    17  import (
    18  	"sync"
    19  	"time"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    22  	"github.com/matrixorigin/matrixone/pkg/logutil"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    28  )
    29  
    30  type txnDB struct {
    31  	store       *txnStore
    32  	tables      map[uint64]*txnTable
    33  	mu          sync.RWMutex
    34  	entry       *catalog.DBEntry
    35  	createEntry txnif.TxnEntry
    36  	dropEntry   txnif.TxnEntry
    37  	ddlCSN      uint32
    38  	idx         int
    39  }
    40  
    41  func newTxnDB(store *txnStore, entry *catalog.DBEntry) *txnDB {
    42  	db := &txnDB{
    43  		store:  store,
    44  		tables: make(map[uint64]*txnTable),
    45  		entry:  entry,
    46  	}
    47  	return db
    48  }
    49  
    50  func (db *txnDB) SetCreateEntry(e txnif.TxnEntry) error {
    51  	if db.createEntry != nil {
    52  		panic("logic error")
    53  	}
    54  	db.store.IncreateWriteCnt()
    55  	db.store.txn.GetMemo().AddCatalogChange()
    56  	db.createEntry = e
    57  	return nil
    58  }
    59  
    60  func (db *txnDB) SetDropEntry(e txnif.TxnEntry) error {
    61  	if db.dropEntry != nil {
    62  		panic("logic error")
    63  	}
    64  	db.store.IncreateWriteCnt()
    65  	db.store.txn.GetMemo().AddCatalogChange()
    66  	db.dropEntry = e
    67  	return nil
    68  }
    69  
    70  func (db *txnDB) LogTxnEntry(tableId uint64, entry txnif.TxnEntry, readed []*common.ID) (err error) {
    71  	table, err := db.getOrSetTable(tableId)
    72  	if err != nil {
    73  		return
    74  	}
    75  	return table.LogTxnEntry(entry, readed)
    76  }
    77  
    78  func (db *txnDB) LogSegmentID(tid, sid uint64) {
    79  	table, _ := db.getOrSetTable(tid)
    80  	table.LogSegmentID(sid)
    81  }
    82  
    83  func (db *txnDB) LogBlockID(tid, bid uint64) {
    84  	table, _ := db.getOrSetTable(tid)
    85  	table.LogBlockID(bid)
    86  }
    87  
    88  func (db *txnDB) Close() error {
    89  	var err error
    90  	for _, table := range db.tables {
    91  		if err = table.Close(); err != nil {
    92  			break
    93  		}
    94  	}
    95  	db.tables = nil
    96  	db.createEntry = nil
    97  	db.dropEntry = nil
    98  	return err
    99  }
   100  
   101  func (db *txnDB) BatchDedup(id uint64, pk containers.Vector) (err error) {
   102  	table, err := db.getOrSetTable(id)
   103  	if err != nil {
   104  		return err
   105  	}
   106  	if table.IsDeleted() {
   107  		return moerr.NewNotFoundNoCtx()
   108  	}
   109  
   110  	return table.DoBatchDedup(pk)
   111  }
   112  
   113  func (db *txnDB) Append(id uint64, bat *containers.Batch) error {
   114  	table, err := db.getOrSetTable(id)
   115  	if err != nil {
   116  		return err
   117  	}
   118  	if table.IsDeleted() {
   119  		return moerr.NewNotFoundNoCtx()
   120  	}
   121  	return table.Append(bat)
   122  }
   123  
   124  func (db *txnDB) AddBlksWithMetaLoc(
   125  	tid uint64,
   126  	pkVecs []containers.Vector,
   127  	file string,
   128  	metaLocs []string,
   129  	flag int32) error {
   130  	table, err := db.getOrSetTable(tid)
   131  	if err != nil {
   132  		return err
   133  	}
   134  	if table.IsDeleted() {
   135  		return moerr.NewNotFoundNoCtx()
   136  	}
   137  	return table.AddBlksWithMetaLoc(pkVecs, file, metaLocs, flag)
   138  }
   139  
   140  func (db *txnDB) DeleteOne(table *txnTable, id *common.ID, row uint32, dt handle.DeleteType) (err error) {
   141  	changed, nid, nrow, err := table.TransferDeleteIntent(id, row)
   142  	if err != nil {
   143  		return err
   144  	}
   145  	if !changed {
   146  		return table.RangeDelete(id, row, row, dt)
   147  	}
   148  	return table.RangeDelete(nid, nrow, nrow, dt)
   149  }
   150  
   151  func (db *txnDB) RangeDelete(id *common.ID, start, end uint32, dt handle.DeleteType) (err error) {
   152  	table, err := db.getOrSetTable(id.TableID)
   153  	if err != nil {
   154  		return err
   155  	}
   156  	if table.IsDeleted() {
   157  		return moerr.NewNotFoundNoCtx()
   158  	}
   159  	return table.RangeDelete(id, start, end, dt)
   160  	// if start == end {
   161  	// 	return db.DeleteOne(table, id, start, dt)
   162  	// }
   163  	// for i := start; i <= end; i++ {
   164  	// 	if err = db.DeleteOne(table, id, i, dt); err != nil {
   165  	// 		return
   166  	// 	}
   167  	// }
   168  	// return
   169  }
   170  
   171  func (db *txnDB) GetByFilter(tid uint64, filter *handle.Filter) (id *common.ID, offset uint32, err error) {
   172  	table, err := db.getOrSetTable(tid)
   173  	if err != nil {
   174  		return
   175  	}
   176  	if table.IsDeleted() {
   177  		err = moerr.NewNotFoundNoCtx()
   178  		return
   179  	}
   180  	return table.GetByFilter(filter)
   181  }
   182  
   183  func (db *txnDB) GetValue(id *common.ID, row uint32, colIdx uint16) (v any, err error) {
   184  	table, err := db.getOrSetTable(id.TableID)
   185  	if err != nil {
   186  		return
   187  	}
   188  	if table.IsDeleted() {
   189  		err = moerr.NewNotFoundNoCtx()
   190  		return
   191  	}
   192  	return table.GetValue(id, row, colIdx)
   193  }
   194  
   195  func (db *txnDB) CreateRelation(def any) (relation handle.Relation, err error) {
   196  	schema := def.(*catalog.Schema)
   197  	var factory catalog.TableDataFactory
   198  	if db.store.dataFactory != nil {
   199  		factory = db.store.dataFactory.MakeTableFactory()
   200  	}
   201  	meta, err := db.entry.CreateTableEntry(schema, db.store.txn, factory)
   202  	if err != nil {
   203  		return
   204  	}
   205  	table, err := db.getOrSetTable(meta.GetID())
   206  	if err != nil {
   207  		return
   208  	}
   209  	relation = newRelation(table)
   210  	table.SetCreateEntry(meta)
   211  	return
   212  }
   213  
   214  func (db *txnDB) CreateRelationWithTableId(tableId uint64, def any) (relation handle.Relation, err error) {
   215  	schema := def.(*catalog.Schema)
   216  	var factory catalog.TableDataFactory
   217  	if db.store.dataFactory != nil {
   218  		factory = db.store.dataFactory.MakeTableFactory()
   219  	}
   220  	meta, err := db.entry.CreateTableEntryWithTableId(schema, db.store.txn, factory, tableId)
   221  	if err != nil {
   222  		return
   223  	}
   224  	table, err := db.getOrSetTable(meta.GetID())
   225  	if err != nil {
   226  		return
   227  	}
   228  	relation = newRelation(table)
   229  	table.SetCreateEntry(meta)
   230  	return
   231  }
   232  
   233  func (db *txnDB) DropRelationByName(name string) (relation handle.Relation, err error) {
   234  	hasNewTxnEntry, meta, err := db.entry.DropTableEntry(name, db.store.txn)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	table, err := db.getOrSetTable(meta.GetID())
   239  	if err != nil {
   240  		return nil, err
   241  	}
   242  	relation = newRelation(table)
   243  	if hasNewTxnEntry {
   244  		err = table.SetDropEntry(meta)
   245  	}
   246  	return
   247  }
   248  
   249  func (db *txnDB) DropRelationByID(id uint64) (relation handle.Relation, err error) {
   250  	hasNewTxnEntry, meta, err := db.entry.DropTableEntryByID(id, db.store.txn)
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  	table, err := db.getOrSetTable(meta.GetID())
   255  	if err != nil {
   256  		return nil, err
   257  	}
   258  	relation = newRelation(table)
   259  	if hasNewTxnEntry {
   260  		err = table.SetDropEntry(meta)
   261  	}
   262  	return
   263  }
   264  
   265  func (db *txnDB) UnsafeGetRelation(id uint64) (relation handle.Relation, err error) {
   266  	meta, err := db.entry.GetTableEntryByID(id)
   267  	if err != nil {
   268  		return
   269  	}
   270  	table, err := db.getOrSetTable(meta.GetID())
   271  	if err != nil {
   272  		return
   273  	}
   274  	relation = newRelation(table)
   275  	return
   276  }
   277  
   278  func (db *txnDB) GetRelationByName(name string) (relation handle.Relation, err error) {
   279  	meta, err := db.entry.TxnGetTableEntryByName(name, db.store.txn)
   280  	if err != nil {
   281  		return
   282  	}
   283  	table, err := db.getOrSetTable(meta.GetID())
   284  	if err != nil {
   285  		return
   286  	}
   287  	relation = newRelation(table)
   288  	return
   289  }
   290  
   291  func (db *txnDB) GetRelationByID(id uint64) (relation handle.Relation, err error) {
   292  	meta, err := db.entry.TxnGetTableEntryByID(id, db.store.txn)
   293  	if err != nil {
   294  		return
   295  	}
   296  	table, err := db.getOrSetTable(meta.GetID())
   297  	if err != nil {
   298  		return
   299  	}
   300  	relation = newRelation(table)
   301  	return
   302  }
   303  
   304  func (db *txnDB) GetSegment(id *common.ID) (seg handle.Segment, err error) {
   305  	var table *txnTable
   306  	if table, err = db.getOrSetTable(id.TableID); err != nil {
   307  		return
   308  	}
   309  	return table.GetSegment(id.SegmentID)
   310  }
   311  
   312  func (db *txnDB) CreateSegment(tid uint64, is1PC bool) (seg handle.Segment, err error) {
   313  	var table *txnTable
   314  	if table, err = db.getOrSetTable(tid); err != nil {
   315  		return
   316  	}
   317  	return table.CreateSegment(is1PC)
   318  }
   319  
   320  func (db *txnDB) CreateNonAppendableSegment(tid uint64, is1PC bool) (seg handle.Segment, err error) {
   321  	var table *txnTable
   322  	if table, err = db.getOrSetTable(tid); err != nil {
   323  		return
   324  	}
   325  	return table.CreateNonAppendableSegment(is1PC)
   326  }
   327  
   328  func (db *txnDB) getOrSetTable(id uint64) (table *txnTable, err error) {
   329  	db.mu.RLock()
   330  	table = db.tables[id]
   331  	db.mu.RUnlock()
   332  	if table != nil {
   333  		return
   334  	}
   335  	var entry *catalog.TableEntry
   336  	if entry, err = db.entry.GetTableEntryByID(id); err != nil {
   337  		return
   338  	}
   339  	db.mu.Lock()
   340  	defer db.mu.Unlock()
   341  	table = db.tables[id]
   342  	if table != nil {
   343  		return
   344  	}
   345  	if db.store.warChecker == nil {
   346  		db.store.warChecker = newWarChecker(db.store.txn, db.store.catalog)
   347  	}
   348  	table = newTxnTable(db.store, entry)
   349  	table.idx = len(db.tables)
   350  	db.tables[id] = table
   351  	return
   352  }
   353  
   354  func (db *txnDB) CreateNonAppendableBlock(id *common.ID) (blk handle.Block, err error) {
   355  	var table *txnTable
   356  	if table, err = db.getOrSetTable(id.TableID); err != nil {
   357  		return
   358  	}
   359  	return table.CreateNonAppendableBlock(id.SegmentID)
   360  }
   361  
   362  func (db *txnDB) CreateNonAppendableBlockWithMeta(
   363  	id *common.ID,
   364  	metaLoc string,
   365  	deltaLoc string) (blk handle.Block, err error) {
   366  	var table *txnTable
   367  	if table, err = db.getOrSetTable(id.TableID); err != nil {
   368  		return
   369  	}
   370  	return table.CreateNonAppendableBlockWithMeta(id.SegmentID, metaLoc, deltaLoc)
   371  }
   372  
   373  func (db *txnDB) GetBlock(id *common.ID) (blk handle.Block, err error) {
   374  	var table *txnTable
   375  	if table, err = db.getOrSetTable(id.TableID); err != nil {
   376  		return
   377  	}
   378  	return table.GetBlock(id)
   379  }
   380  
   381  func (db *txnDB) CreateBlock(tid, sid uint64, is1PC bool) (blk handle.Block, err error) {
   382  	var table *txnTable
   383  	if table, err = db.getOrSetTable(tid); err != nil {
   384  		return
   385  	}
   386  	return table.CreateBlock(sid, is1PC)
   387  }
   388  
   389  func (db *txnDB) SoftDeleteBlock(id *common.ID) (err error) {
   390  	var table *txnTable
   391  	if table, err = db.getOrSetTable(id.TableID); err != nil {
   392  		return
   393  	}
   394  	return table.SoftDeleteBlock(id)
   395  }
   396  func (db *txnDB) UpdateMetaLoc(id *common.ID, metaLoc string) (err error) {
   397  	var table *txnTable
   398  	if table, err = db.getOrSetTable(id.TableID); err != nil {
   399  		return
   400  	}
   401  	return table.UpdateMetaLoc(id, metaLoc)
   402  }
   403  func (db *txnDB) UpdateDeltaLoc(id *common.ID, deltaLoc string) (err error) {
   404  	var table *txnTable
   405  	if table, err = db.getOrSetTable(id.TableID); err != nil {
   406  		return
   407  	}
   408  	return table.UpdateDeltaLoc(id, deltaLoc)
   409  }
   410  func (db *txnDB) SoftDeleteSegment(id *common.ID) (err error) {
   411  	var table *txnTable
   412  	if table, err = db.getOrSetTable(id.TableID); err != nil {
   413  		return
   414  	}
   415  	return table.SoftDeleteSegment(id.SegmentID)
   416  }
   417  func (db *txnDB) NeedRollback() bool {
   418  	return db.createEntry != nil && db.dropEntry != nil
   419  }
   420  func (db *txnDB) ApplyRollback() (err error) {
   421  	if db.createEntry != nil {
   422  		if err = db.createEntry.ApplyRollback(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil {
   423  			return
   424  		}
   425  	}
   426  	for _, table := range db.tables {
   427  		if err = table.ApplyRollback(); err != nil {
   428  			break
   429  		}
   430  	}
   431  	if db.dropEntry != nil {
   432  		if err = db.dropEntry.ApplyRollback(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil {
   433  			return
   434  		}
   435  	}
   436  	return
   437  }
   438  
   439  func (db *txnDB) WaitPrepared() (err error) {
   440  	for _, table := range db.tables {
   441  		table.WaitSynced()
   442  	}
   443  	return
   444  }
   445  func (db *txnDB) Apply1PCCommit() (err error) {
   446  	if db.createEntry != nil && db.createEntry.Is1PC() {
   447  		if err = db.createEntry.ApplyCommit(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil {
   448  			return
   449  		}
   450  	}
   451  	for _, table := range db.tables {
   452  		if err = table.Apply1PCCommit(); err != nil {
   453  			break
   454  		}
   455  	}
   456  	if db.dropEntry != nil && db.dropEntry.Is1PC() {
   457  		if err = db.dropEntry.ApplyCommit(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil {
   458  			return
   459  		}
   460  	}
   461  	return
   462  }
   463  func (db *txnDB) ApplyCommit() (err error) {
   464  	now := time.Now()
   465  	if db.createEntry != nil && !db.createEntry.Is1PC() {
   466  		if err = db.createEntry.ApplyCommit(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil {
   467  			return
   468  		}
   469  	}
   470  	for _, table := range db.tables {
   471  		if err = table.ApplyCommit(); err != nil {
   472  			break
   473  		}
   474  	}
   475  	if db.dropEntry != nil && !db.dropEntry.Is1PC() {
   476  		if err = db.dropEntry.ApplyCommit(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil {
   477  			return
   478  		}
   479  	}
   480  	logutil.Debugf("Txn-%X ApplyCommit Takes %s", db.store.txn.GetID(), time.Since(now))
   481  	return
   482  }
   483  
   484  func (db *txnDB) PrePrepare() (err error) {
   485  	for _, table := range db.tables {
   486  		if table.NeedRollback() {
   487  			if err = table.PrepareRollback(); err != nil {
   488  				return
   489  			}
   490  			delete(db.tables, table.GetID())
   491  		}
   492  	}
   493  	for _, table := range db.tables {
   494  		if err = table.PrePreareTransfer(); err != nil {
   495  			return
   496  		}
   497  	}
   498  	for _, table := range db.tables {
   499  		if err = table.PrePrepareDedup(); err != nil {
   500  			return
   501  		}
   502  	}
   503  	for _, table := range db.tables {
   504  		if err = table.PrePrepare(); err != nil {
   505  			panic(err)
   506  		}
   507  	}
   508  	return
   509  }
   510  
   511  func (db *txnDB) PrepareCommit() (err error) {
   512  	now := time.Now()
   513  	if db.createEntry != nil {
   514  		if err = db.createEntry.PrepareCommit(); err != nil {
   515  			return
   516  		}
   517  	}
   518  	for _, table := range db.tables {
   519  		if err = table.PrepareCommit(); err != nil {
   520  			break
   521  		}
   522  	}
   523  	if db.dropEntry != nil {
   524  		if err = db.dropEntry.PrepareCommit(); err != nil {
   525  			return
   526  		}
   527  	}
   528  
   529  	logutil.Debugf("Txn-%X PrepareCommit Takes %s", db.store.txn.GetID(), time.Since(now))
   530  
   531  	return
   532  }
   533  
   534  func (db *txnDB) PreApplyCommit() (err error) {
   535  	for _, table := range db.tables {
   536  		// table.ApplyAppend()
   537  		if err = table.PreApplyCommit(); err != nil {
   538  			return
   539  		}
   540  	}
   541  	return
   542  }
   543  
   544  func (db *txnDB) CollectCmd(cmdMgr *commandManager) (err error) {
   545  	if db.createEntry != nil {
   546  		csn := cmdMgr.GetCSN()
   547  		entry := db.createEntry
   548  		cmd, err := entry.MakeCommand(csn)
   549  		if err != nil {
   550  			panic(err)
   551  		}
   552  		cmdMgr.AddCmd(cmd)
   553  		db.ddlCSN = csn
   554  	}
   555  	tables := make([]*txnTable, len(db.tables))
   556  	for _, table := range db.tables {
   557  		tables[table.idx] = table
   558  	}
   559  	for _, table := range tables {
   560  		if err = table.CollectCmd(cmdMgr); err != nil {
   561  			return
   562  		}
   563  	}
   564  	if db.dropEntry != nil {
   565  		csn := cmdMgr.GetCSN()
   566  		cmd, err := db.dropEntry.MakeCommand(csn)
   567  		if err != nil {
   568  			panic(err)
   569  		}
   570  		cmdMgr.AddCmd(cmd)
   571  		db.ddlCSN = csn
   572  	}
   573  	return
   574  }
   575  
   576  func (db *txnDB) AddTxnEntry(t txnif.TxnEntryType, entry txnif.TxnEntry) {
   577  	// TODO
   578  }
   579  
   580  func (db *txnDB) PrepareRollback() error {
   581  	var err error
   582  	if db.createEntry != nil {
   583  		if err := db.createEntry.PrepareRollback(); err != nil {
   584  			return err
   585  		}
   586  	}
   587  	for _, table := range db.tables {
   588  		if err = table.PrepareRollback(); err != nil {
   589  			break
   590  		}
   591  	}
   592  	if db.dropEntry != nil {
   593  		if err := db.dropEntry.PrepareRollback(); err != nil {
   594  			return err
   595  		}
   596  	}
   597  
   598  	return err
   599  }