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