github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/store.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  	"sync"
    19  	"sync/atomic"
    20  	"time"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  	"github.com/matrixorigin/matrixone/pkg/logutil"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/buffer/base"
    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/logstore/entry"
    31  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model"
    32  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables"
    33  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase"
    34  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal"
    35  )
    36  
    37  type txnStore struct {
    38  	txnbase.NoopTxnStore
    39  	mu            sync.RWMutex
    40  	transferTable *model.HashPageTable
    41  	dbs           map[uint64]*txnDB
    42  	driver        wal.Driver
    43  	nodesMgr      base.INodeManager
    44  	txn           txnif.AsyncTxn
    45  	catalog       *catalog.Catalog
    46  	cmdMgr        *commandManager
    47  	logs          []entry.Entry
    48  	warChecker    *warChecker
    49  	dataFactory   *tables.DataFactory
    50  	writeOps      atomic.Uint32
    51  }
    52  
    53  var TxnStoreFactory = func(
    54  	catalog *catalog.Catalog,
    55  	driver wal.Driver,
    56  	transferTable *model.HashPageTable,
    57  	txnBufMgr base.INodeManager,
    58  	dataFactory *tables.DataFactory) txnbase.TxnStoreFactory {
    59  	return func() txnif.TxnStore {
    60  		return newStore(catalog, driver, transferTable, txnBufMgr, dataFactory)
    61  	}
    62  }
    63  
    64  func newStore(
    65  	catalog *catalog.Catalog,
    66  	driver wal.Driver,
    67  	transferTable *model.HashPageTable,
    68  	txnBufMgr base.INodeManager,
    69  	dataFactory *tables.DataFactory) *txnStore {
    70  	return &txnStore{
    71  		transferTable: transferTable,
    72  		dbs:           make(map[uint64]*txnDB),
    73  		catalog:       catalog,
    74  		cmdMgr:        newCommandManager(driver),
    75  		driver:        driver,
    76  		logs:          make([]entry.Entry, 0),
    77  		dataFactory:   dataFactory,
    78  		nodesMgr:      txnBufMgr,
    79  	}
    80  }
    81  
    82  func (store *txnStore) IsReadonly() bool {
    83  	return store.writeOps.Load() == 0
    84  }
    85  
    86  func (store *txnStore) IncreateWriteCnt() int {
    87  	return int(store.writeOps.Add(1))
    88  }
    89  
    90  func (store *txnStore) LogTxnEntry(dbId uint64, tableId uint64, entry txnif.TxnEntry, readed []*common.ID) (err error) {
    91  	db, err := store.getOrSetDB(dbId)
    92  	if err != nil {
    93  		return
    94  	}
    95  	return db.LogTxnEntry(tableId, entry, readed)
    96  }
    97  
    98  func (store *txnStore) LogTxnState(sync bool) (logEntry entry.Entry, err error) {
    99  	cmd := txnbase.NewTxnStateCmd(
   100  		store.txn.GetID(),
   101  		store.txn.GetTxnState(false),
   102  		store.txn.GetCommitTS(),
   103  	)
   104  	var buf []byte
   105  	if buf, err = cmd.Marshal(); err != nil {
   106  		return
   107  	}
   108  	logEntry = entry.GetBase()
   109  	logEntry.SetType(ETTxnState)
   110  	if err = logEntry.SetPayload(buf); err != nil {
   111  		return
   112  	}
   113  	info := &entry.Info{
   114  		Group: wal.GroupC,
   115  		TxnId: store.txn.GetID(),
   116  	}
   117  	logEntry.SetInfo(info)
   118  	var lsn uint64
   119  	lsn, err = store.driver.AppendEntry(wal.GroupC, logEntry)
   120  	if err != nil {
   121  		return
   122  	}
   123  	if sync {
   124  		err = logEntry.WaitDone()
   125  	}
   126  	logutil.Debugf("LogTxnState LSN=%d, Size=%d", lsn, len(buf))
   127  	return
   128  }
   129  
   130  func (store *txnStore) LogSegmentID(dbId, tid, sid uint64) {
   131  	db, _ := store.getOrSetDB(dbId)
   132  	db.LogSegmentID(tid, sid)
   133  }
   134  
   135  func (store *txnStore) LogBlockID(dbId, tid, bid uint64) {
   136  	db, _ := store.getOrSetDB(dbId)
   137  	db.LogBlockID(tid, bid)
   138  }
   139  
   140  func (store *txnStore) Close() error {
   141  	var err error
   142  	for _, db := range store.dbs {
   143  		if err = db.Close(); err != nil {
   144  			break
   145  		}
   146  	}
   147  	store.dbs = nil
   148  	store.cmdMgr = nil
   149  	store.logs = nil
   150  	store.warChecker = nil
   151  	return err
   152  }
   153  
   154  func (store *txnStore) BindTxn(txn txnif.AsyncTxn) {
   155  	store.txn = txn
   156  }
   157  
   158  func (store *txnStore) BatchDedup(dbId, id uint64, pk containers.Vector) (err error) {
   159  	db, err := store.getOrSetDB(dbId)
   160  	if err != nil {
   161  		return err
   162  	}
   163  	// if table.IsDeleted() {
   164  	// 	return txnbase.ErrNotFound
   165  	// }
   166  
   167  	return db.BatchDedup(id, pk)
   168  }
   169  
   170  func (store *txnStore) Append(dbId, id uint64, data *containers.Batch) error {
   171  	store.IncreateWriteCnt()
   172  	db, err := store.getOrSetDB(dbId)
   173  	if err != nil {
   174  		return err
   175  	}
   176  	// if db.IsDeleted() {
   177  	// 	return txnbase.ErrNotFound
   178  	// }
   179  	return db.Append(id, data)
   180  }
   181  
   182  func (store *txnStore) AddBlksWithMetaLoc(
   183  	dbId, tid uint64,
   184  	pkVecs []containers.Vector,
   185  	file string,
   186  	metaLoc []string,
   187  	flag int32,
   188  ) error {
   189  	store.IncreateWriteCnt()
   190  	db, err := store.getOrSetDB(dbId)
   191  	if err != nil {
   192  		return err
   193  	}
   194  	return db.AddBlksWithMetaLoc(tid, pkVecs, file, metaLoc, flag)
   195  }
   196  
   197  func (store *txnStore) RangeDelete(dbId uint64, id *common.ID, start, end uint32, dt handle.DeleteType) (err error) {
   198  	db, err := store.getOrSetDB(dbId)
   199  	if err != nil {
   200  		return err
   201  	}
   202  	return db.RangeDelete(id, start, end, dt)
   203  }
   204  
   205  func (store *txnStore) UpdateMetaLoc(dbId uint64, id *common.ID, metaLoc string) (err error) {
   206  	db, err := store.getOrSetDB(dbId)
   207  	if err != nil {
   208  		return err
   209  	}
   210  	// if table.IsDeleted() {
   211  	// 	return txnbase.ErrNotFound
   212  	// }
   213  	return db.UpdateMetaLoc(id, metaLoc)
   214  }
   215  
   216  func (store *txnStore) UpdateDeltaLoc(dbId uint64, id *common.ID, deltaLoc string) (err error) {
   217  	db, err := store.getOrSetDB(dbId)
   218  	if err != nil {
   219  		return err
   220  	}
   221  	// if table.IsDeleted() {
   222  	// 	return txnbase.ErrNotFound
   223  	// }
   224  	return db.UpdateDeltaLoc(id, deltaLoc)
   225  }
   226  
   227  func (store *txnStore) GetByFilter(dbId, tid uint64, filter *handle.Filter) (id *common.ID, offset uint32, err error) {
   228  	db, err := store.getOrSetDB(dbId)
   229  	if err != nil {
   230  		return
   231  	}
   232  	// if table.IsDeleted() {
   233  	// 	err = txnbase.ErrNotFound
   234  	// 	return
   235  	// }
   236  	return db.GetByFilter(tid, filter)
   237  }
   238  
   239  func (store *txnStore) GetValue(dbId uint64, id *common.ID, row uint32, colIdx uint16) (v any, err error) {
   240  	db, err := store.getOrSetDB(dbId)
   241  	if err != nil {
   242  		return
   243  	}
   244  	// if table.IsDeleted() {
   245  	// 	err = txnbase.ErrNotFound
   246  	// 	return
   247  	// }
   248  	return db.GetValue(id, row, colIdx)
   249  }
   250  
   251  func (store *txnStore) DatabaseNames() (names []string) {
   252  	it := newDBIt(store.txn, store.catalog)
   253  	for it.Valid() {
   254  		names = append(names, it.GetCurr().GetName())
   255  		it.Next()
   256  	}
   257  	return
   258  }
   259  
   260  func (store *txnStore) UseDatabase(name string) (err error) {
   261  	return err
   262  }
   263  
   264  func (store *txnStore) UnsafeGetDatabase(id uint64) (h handle.Database, err error) {
   265  	meta, err := store.catalog.GetDatabaseByID(id)
   266  	if err != nil {
   267  		return
   268  	}
   269  	var db *txnDB
   270  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   271  		return
   272  	}
   273  	h = buildDB(db)
   274  	return
   275  }
   276  
   277  func (store *txnStore) GetDatabase(name string) (h handle.Database, err error) {
   278  	defer func() {
   279  		if err == moerr.GetOkExpectedEOB() {
   280  			err = moerr.NewBadDBNoCtx(name)
   281  		}
   282  	}()
   283  	meta, err := store.catalog.TxnGetDBEntryByName(name, store.txn)
   284  	if err != nil {
   285  		return
   286  	}
   287  	var db *txnDB
   288  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   289  		return
   290  	}
   291  	h = buildDB(db)
   292  	return
   293  }
   294  
   295  func (store *txnStore) GetDatabaseByID(id uint64) (h handle.Database, err error) {
   296  	meta, err := store.catalog.TxnGetDBEntryByID(id, store.txn)
   297  	if err != nil {
   298  		return
   299  	}
   300  	var db *txnDB
   301  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   302  		return
   303  	}
   304  	h = buildDB(db)
   305  	return
   306  }
   307  
   308  func (store *txnStore) CreateDatabase(name, createSql string) (h handle.Database, err error) {
   309  	meta, err := store.catalog.CreateDBEntry(name, createSql, store.txn)
   310  	if err != nil {
   311  		return nil, err
   312  	}
   313  	var db *txnDB
   314  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   315  		return
   316  	}
   317  	if err = db.SetCreateEntry(meta); err != nil {
   318  		return
   319  	}
   320  	h = buildDB(db)
   321  	return
   322  }
   323  
   324  func (store *txnStore) CreateDatabaseWithID(name, createSql string, id uint64) (h handle.Database, err error) {
   325  	meta, err := store.catalog.CreateDBEntryWithID(name, createSql, id, store.txn)
   326  	if err != nil {
   327  		return nil, err
   328  	}
   329  	var db *txnDB
   330  	if db, err = store.getOrSetDB(meta.GetID()); err != nil {
   331  		return
   332  	}
   333  	if err = db.SetCreateEntry(meta); err != nil {
   334  		return
   335  	}
   336  	h = buildDB(db)
   337  	return
   338  }
   339  
   340  func (store *txnStore) DropDatabase(name string) (h handle.Database, err error) {
   341  	hasNewEntry, meta, err := store.catalog.DropDBEntry(name, store.txn)
   342  	if err != nil {
   343  		return
   344  	}
   345  	db, err := store.getOrSetDB(meta.GetID())
   346  	if err != nil {
   347  		return
   348  	}
   349  	if hasNewEntry {
   350  		if err = db.SetDropEntry(meta); err != nil {
   351  			return
   352  		}
   353  	}
   354  	h = buildDB(db)
   355  	return
   356  }
   357  
   358  func (store *txnStore) DropDatabaseByID(id uint64) (h handle.Database, err error) {
   359  	hasNewEntry, meta, err := store.catalog.DropDBEntryByID(id, store.txn)
   360  	if err != nil {
   361  		return
   362  	}
   363  	db, err := store.getOrSetDB(meta.GetID())
   364  	if err != nil {
   365  		return
   366  	}
   367  	if hasNewEntry {
   368  		if err = db.SetDropEntry(meta); err != nil {
   369  			return
   370  		}
   371  	}
   372  	h = buildDB(db)
   373  	return
   374  }
   375  
   376  func (store *txnStore) CreateRelation(dbId uint64, def any) (relation handle.Relation, err error) {
   377  	db, err := store.getOrSetDB(dbId)
   378  	if err != nil {
   379  		return
   380  	}
   381  	return db.CreateRelation(def)
   382  }
   383  
   384  func (store *txnStore) CreateRelationWithTableId(dbId uint64, tableId uint64, def any) (relation handle.Relation, err error) {
   385  	db, err := store.getOrSetDB(dbId)
   386  	if err != nil {
   387  		return
   388  	}
   389  	return db.CreateRelationWithTableId(tableId, def)
   390  }
   391  
   392  func (store *txnStore) DropRelationByName(dbId uint64, name string) (relation handle.Relation, err error) {
   393  	db, err := store.getOrSetDB(dbId)
   394  	if err != nil {
   395  		return nil, err
   396  	}
   397  	return db.DropRelationByName(name)
   398  }
   399  
   400  func (store *txnStore) DropRelationByID(dbId uint64, id uint64) (relation handle.Relation, err error) {
   401  	db, err := store.getOrSetDB(dbId)
   402  	if err != nil {
   403  		return nil, err
   404  	}
   405  	return db.DropRelationByID(id)
   406  }
   407  
   408  func (store *txnStore) UnsafeGetRelation(dbId, id uint64) (relation handle.Relation, err error) {
   409  	db, err := store.getOrSetDB(dbId)
   410  	if err != nil {
   411  		return nil, err
   412  	}
   413  	return db.UnsafeGetRelation(id)
   414  }
   415  
   416  func (store *txnStore) GetRelationByName(dbId uint64, name string) (relation handle.Relation, err error) {
   417  	db, err := store.getOrSetDB(dbId)
   418  	if err != nil {
   419  		return nil, err
   420  	}
   421  	return db.GetRelationByName(name)
   422  }
   423  
   424  func (store *txnStore) GetRelationByID(dbId uint64, id uint64) (relation handle.Relation, err error) {
   425  	db, err := store.getOrSetDB(dbId)
   426  	if err != nil {
   427  		return nil, err
   428  	}
   429  	return db.GetRelationByID(id)
   430  }
   431  
   432  func (store *txnStore) GetSegment(dbId uint64, id *common.ID) (seg handle.Segment, err error) {
   433  	var db *txnDB
   434  	if db, err = store.getOrSetDB(dbId); err != nil {
   435  		return
   436  	}
   437  	return db.GetSegment(id)
   438  }
   439  
   440  func (store *txnStore) CreateSegment(dbId, tid uint64, is1PC bool) (seg handle.Segment, err error) {
   441  	var db *txnDB
   442  	if db, err = store.getOrSetDB(dbId); err != nil {
   443  		return
   444  	}
   445  	return db.CreateSegment(tid, is1PC)
   446  }
   447  
   448  func (store *txnStore) CreateNonAppendableSegment(dbId, tid uint64, is1PC bool) (seg handle.Segment, err error) {
   449  	var db *txnDB
   450  	if db, err = store.getOrSetDB(dbId); err != nil {
   451  		return
   452  	}
   453  	return db.CreateNonAppendableSegment(tid, is1PC)
   454  }
   455  
   456  func (store *txnStore) getOrSetDB(id uint64) (db *txnDB, err error) {
   457  	store.mu.RLock()
   458  	db = store.dbs[id]
   459  	store.mu.RUnlock()
   460  	if db != nil {
   461  		return
   462  	}
   463  	var entry *catalog.DBEntry
   464  	if entry, err = store.catalog.GetDatabaseByID(id); err != nil {
   465  		return
   466  	}
   467  	store.mu.Lock()
   468  	defer store.mu.Unlock()
   469  	db = store.dbs[id]
   470  	if db != nil {
   471  		return
   472  	}
   473  	db = newTxnDB(store, entry)
   474  	db.idx = len(store.dbs)
   475  	store.dbs[id] = db
   476  	return
   477  }
   478  
   479  func (store *txnStore) CreateNonAppendableBlock(dbId uint64, id *common.ID) (blk handle.Block, err error) {
   480  	var db *txnDB
   481  	if db, err = store.getOrSetDB(dbId); err != nil {
   482  		return
   483  	}
   484  	return db.CreateNonAppendableBlock(id)
   485  }
   486  
   487  func (store *txnStore) CreateNonAppendableBlockWithMeta(
   488  	dbId uint64,
   489  	id *common.ID,
   490  	metaLoc string,
   491  	deltaLoc string) (blk handle.Block, err error) {
   492  	var db *txnDB
   493  	if db, err = store.getOrSetDB(dbId); err != nil {
   494  		return
   495  	}
   496  	return db.CreateNonAppendableBlockWithMeta(id, metaLoc, deltaLoc)
   497  }
   498  
   499  func (store *txnStore) GetBlock(dbId uint64, id *common.ID) (blk handle.Block, err error) {
   500  	var db *txnDB
   501  	if db, err = store.getOrSetDB(dbId); err != nil {
   502  		return
   503  	}
   504  	return db.GetBlock(id)
   505  }
   506  
   507  func (store *txnStore) CreateBlock(dbId, tid, sid uint64, is1PC bool) (blk handle.Block, err error) {
   508  	var db *txnDB
   509  	if db, err = store.getOrSetDB(dbId); err != nil {
   510  		return
   511  	}
   512  	return db.CreateBlock(tid, sid, is1PC)
   513  }
   514  
   515  func (store *txnStore) SoftDeleteBlock(dbId uint64, id *common.ID) (err error) {
   516  	var db *txnDB
   517  	if db, err = store.getOrSetDB(dbId); err != nil {
   518  		return
   519  	}
   520  	return db.SoftDeleteBlock(id)
   521  }
   522  
   523  func (store *txnStore) SoftDeleteSegment(dbId uint64, id *common.ID) (err error) {
   524  	var db *txnDB
   525  	if db, err = store.getOrSetDB(dbId); err != nil {
   526  		return
   527  	}
   528  	return db.SoftDeleteSegment(id)
   529  }
   530  
   531  func (store *txnStore) ApplyRollback() (err error) {
   532  	if store.cmdMgr.GetCSN() == 0 {
   533  		return
   534  	}
   535  	for _, db := range store.dbs {
   536  		if err = db.ApplyRollback(); err != nil {
   537  			break
   538  		}
   539  	}
   540  	return
   541  }
   542  
   543  func (store *txnStore) WaitPrepared() (err error) {
   544  	for _, db := range store.dbs {
   545  		if err = db.WaitPrepared(); err != nil {
   546  			return
   547  		}
   548  	}
   549  	for _, e := range store.logs {
   550  		if err = e.WaitDone(); err != nil {
   551  			break
   552  		}
   553  		e.Free()
   554  	}
   555  	return
   556  }
   557  
   558  func (store *txnStore) ApplyCommit() (err error) {
   559  	for _, db := range store.dbs {
   560  		if err = db.ApplyCommit(); err != nil {
   561  			break
   562  		}
   563  	}
   564  	return
   565  }
   566  
   567  func (store *txnStore) PrePrepare() (err error) {
   568  	for _, db := range store.dbs {
   569  		if db.NeedRollback() {
   570  			if err = db.PrepareRollback(); err != nil {
   571  				return
   572  			}
   573  			delete(store.dbs, db.entry.GetID())
   574  		}
   575  		if err = db.PrePrepare(); err != nil {
   576  			return
   577  		}
   578  	}
   579  	return
   580  }
   581  
   582  func (store *txnStore) PrepareCommit() (err error) {
   583  	if store.warChecker != nil {
   584  		if err = store.warChecker.checkAll(
   585  			store.txn.GetPrepareTS()); err != nil {
   586  			return err
   587  		}
   588  	}
   589  	for _, db := range store.dbs {
   590  		if err = db.PrepareCommit(); err != nil {
   591  			break
   592  		}
   593  	}
   594  
   595  	return
   596  }
   597  
   598  func (store *txnStore) PreApplyCommit() (err error) {
   599  	now := time.Now()
   600  	for _, db := range store.dbs {
   601  		if err = db.PreApplyCommit(); err != nil {
   602  			return
   603  		}
   604  	}
   605  	if err = store.CollectCmd(); err != nil {
   606  		return
   607  	}
   608  
   609  	if store.cmdMgr.GetCSN() == 0 {
   610  		return
   611  	}
   612  
   613  	logEntry, err := store.cmdMgr.ApplyTxnRecord(store.txn.GetID(), store.txn)
   614  	if err != nil {
   615  		return
   616  	}
   617  	if logEntry != nil {
   618  		store.logs = append(store.logs, logEntry)
   619  	}
   620  	for _, db := range store.dbs {
   621  		if err = db.Apply1PCCommit(); err != nil {
   622  			return
   623  		}
   624  	}
   625  	logutil.Debugf("Txn-%X PrepareCommit Takes %s", store.txn.GetID(), time.Since(now))
   626  	return
   627  }
   628  
   629  func (store *txnStore) CollectCmd() (err error) {
   630  	dbs := make([]*txnDB, len(store.dbs))
   631  	for _, db := range store.dbs {
   632  		dbs[db.idx] = db
   633  	}
   634  	for _, db := range dbs {
   635  		if err = db.CollectCmd(store.cmdMgr); err != nil {
   636  			return
   637  		}
   638  	}
   639  	return
   640  }
   641  
   642  func (store *txnStore) AddTxnEntry(t txnif.TxnEntryType, entry txnif.TxnEntry) {
   643  	// TODO
   644  }
   645  
   646  func (store *txnStore) PrepareRollback() error {
   647  	var err error
   648  	for _, db := range store.dbs {
   649  		if err = db.PrepareRollback(); err != nil {
   650  			break
   651  		}
   652  	}
   653  
   654  	return err
   655  }
   656  
   657  func (store *txnStore) GetLSN() uint64 { return store.cmdMgr.lsn }