github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/catalog/catalogreplay.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  package catalog
    15  
    16  import (
    17  	pkgcatalog "github.com/matrixorigin/matrixone/pkg/catalog"
    18  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    19  	"github.com/matrixorigin/matrixone/pkg/container/types"
    20  	"github.com/matrixorigin/matrixone/pkg/logutil"
    21  	"github.com/matrixorigin/matrixone/pkg/objectio"
    22  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/data"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal"
    28  
    29  	"go.uber.org/zap"
    30  )
    31  
    32  //#region Replay related
    33  
    34  func (catalog *Catalog) ReplayCmd(
    35  	txncmd txnif.TxnCmd,
    36  	dataFactory DataFactory,
    37  	observer wal.ReplayObserver) {
    38  	switch txncmd.GetType() {
    39  	case txnbase.IOET_WALTxnCommand_Composed:
    40  		cmds := txncmd.(*txnbase.ComposedCmd)
    41  		for _, cmds := range cmds.Cmds {
    42  			catalog.ReplayCmd(cmds, dataFactory, observer)
    43  		}
    44  	case IOET_WALTxnCommand_Database:
    45  		cmd := txncmd.(*EntryCommand[*EmptyMVCCNode, *DBNode])
    46  		catalog.onReplayUpdateDatabase(cmd, observer)
    47  	case IOET_WALTxnCommand_Table:
    48  		cmd := txncmd.(*EntryCommand[*TableMVCCNode, *TableNode])
    49  		catalog.onReplayUpdateTable(cmd, dataFactory, observer)
    50  	case IOET_WALTxnCommand_Object:
    51  		cmd := txncmd.(*EntryCommand[*ObjectMVCCNode, *ObjectNode])
    52  		catalog.onReplayUpdateObject(cmd, dataFactory, observer)
    53  	case IOET_WALTxnCommand_Block:
    54  		cmd := txncmd.(*EntryCommand[*MetadataMVCCNode, *BlockNode])
    55  		catalog.onReplayUpdateBlock(cmd, dataFactory, observer)
    56  	case IOET_WALTxnCommand_Segment:
    57  		// segment is deprecated
    58  		return
    59  	default:
    60  		panic("unsupport")
    61  	}
    62  }
    63  
    64  func (catalog *Catalog) onReplayUpdateDatabase(cmd *EntryCommand[*EmptyMVCCNode, *DBNode], observer wal.ReplayObserver) {
    65  	catalog.OnReplayDBID(cmd.ID.DbID)
    66  	var err error
    67  	un := cmd.mvccNode
    68  	if un.Is1PC() {
    69  		if err := un.ApplyCommit(); err != nil {
    70  			panic(err)
    71  		}
    72  	}
    73  
    74  	db, err := catalog.GetDatabaseByID(cmd.ID.DbID)
    75  	if err != nil {
    76  		db = NewReplayDBEntry()
    77  		db.ID = cmd.ID.DbID
    78  		db.catalog = catalog
    79  		db.DBNode = cmd.node
    80  		db.Insert(un)
    81  		err = catalog.AddEntryLocked(db, un.GetTxn(), false)
    82  		if err != nil {
    83  			panic(err)
    84  		}
    85  		return
    86  	}
    87  
    88  	dbun := db.SearchNodeLocked(un)
    89  	if dbun == nil {
    90  		db.Insert(un)
    91  	} else {
    92  		return
    93  		// panic(fmt.Sprintf("logic err: duplicate node %v and %v", dbun.String(), un.String()))
    94  	}
    95  }
    96  
    97  func (catalog *Catalog) OnReplayDatabaseBatch(ins, insTxn, del, delTxn *containers.Batch) {
    98  	for i := 0; i < ins.Length(); i++ {
    99  		dbid := ins.GetVectorByName(pkgcatalog.SystemDBAttr_ID).Get(i).(uint64)
   100  		name := string(ins.GetVectorByName(pkgcatalog.SystemDBAttr_Name).Get(i).([]byte))
   101  		txnNode := txnbase.ReadTuple(insTxn, i)
   102  		tenantID := ins.GetVectorByName(pkgcatalog.SystemDBAttr_AccID).Get(i).(uint32)
   103  		userID := ins.GetVectorByName(pkgcatalog.SystemDBAttr_Creator).Get(i).(uint32)
   104  		roleID := ins.GetVectorByName(pkgcatalog.SystemDBAttr_Owner).Get(i).(uint32)
   105  		createAt := ins.GetVectorByName(pkgcatalog.SystemDBAttr_CreateAt).Get(i).(types.Timestamp)
   106  		createSql := string(ins.GetVectorByName(pkgcatalog.SystemDBAttr_CreateSQL).Get(i).([]byte))
   107  		datType := string(ins.GetVectorByName(pkgcatalog.SystemDBAttr_Type).Get(i).([]byte))
   108  		catalog.onReplayCreateDB(dbid, name, txnNode, tenantID, userID, roleID, createAt, createSql, datType)
   109  	}
   110  	for i := 0; i < del.Length(); i++ {
   111  		dbid := delTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64)
   112  		txnNode := txnbase.ReadTuple(delTxn, i)
   113  		catalog.onReplayDeleteDB(dbid, txnNode)
   114  	}
   115  }
   116  
   117  func (catalog *Catalog) onReplayCreateDB(
   118  	dbid uint64, name string, txnNode *txnbase.TxnMVCCNode,
   119  	tenantID, userID, roleID uint32, createAt types.Timestamp, createSql, datType string) {
   120  	catalog.OnReplayDBID(dbid)
   121  	db, _ := catalog.GetDatabaseByID(dbid)
   122  	if db != nil {
   123  		dbCreatedAt := db.GetCreatedAtLocked()
   124  		if !dbCreatedAt.Equal(&txnNode.End) {
   125  			panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s",
   126  				txnNode.End.ToString(), dbCreatedAt.ToString()))
   127  		}
   128  		return
   129  	}
   130  	db = NewReplayDBEntry()
   131  	db.catalog = catalog
   132  	db.ID = dbid
   133  	db.DBNode = &DBNode{
   134  		acInfo: accessInfo{
   135  			TenantID: tenantID,
   136  			UserID:   userID,
   137  			RoleID:   roleID,
   138  			CreateAt: createAt,
   139  		},
   140  		createSql: createSql,
   141  		datType:   datType,
   142  		name:      name,
   143  	}
   144  	_ = catalog.AddEntryLocked(db, nil, true)
   145  	un := &MVCCNode[*EmptyMVCCNode]{
   146  		EntryMVCCNode: &EntryMVCCNode{
   147  			CreatedAt: txnNode.End,
   148  		},
   149  		TxnMVCCNode: txnNode,
   150  	}
   151  	db.Insert(un)
   152  }
   153  func (catalog *Catalog) onReplayDeleteDB(dbid uint64, txnNode *txnbase.TxnMVCCNode) {
   154  	catalog.OnReplayDBID(dbid)
   155  	db, err := catalog.GetDatabaseByID(dbid)
   156  	if err != nil {
   157  		logutil.Info("delete %d", zap.Uint64("dbid", dbid), zap.String("catalog pp", catalog.SimplePPString(common.PPL3)))
   158  		panic(err)
   159  	}
   160  	dbDeleteAt := db.GetDeleteAtLocked()
   161  	if !dbDeleteAt.IsEmpty() {
   162  		if !dbDeleteAt.Equal(&txnNode.End) {
   163  			panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), dbDeleteAt.ToString()))
   164  		}
   165  		return
   166  	}
   167  	prev := db.MVCCChain.GetLatestNodeLocked()
   168  	un := &MVCCNode[*EmptyMVCCNode]{
   169  		EntryMVCCNode: &EntryMVCCNode{
   170  			CreatedAt: db.GetCreatedAtLocked(),
   171  			DeletedAt: txnNode.End,
   172  		},
   173  		TxnMVCCNode: txnNode,
   174  		BaseNode:    prev.BaseNode.CloneAll(),
   175  	}
   176  	db.Insert(un)
   177  }
   178  func (catalog *Catalog) onReplayUpdateTable(cmd *EntryCommand[*TableMVCCNode, *TableNode], dataFactory DataFactory, observer wal.ReplayObserver) {
   179  	catalog.OnReplayTableID(cmd.ID.TableID)
   180  	// prepareTS := cmd.GetTs()
   181  	// if prepareTS.LessEq(catalog.GetCheckpointed().MaxTS) {
   182  	// 	if observer != nil {
   183  	// 		observer.OnStaleIndex(idx)
   184  	// 	}
   185  	// 	return
   186  	// }
   187  	db, err := catalog.GetDatabaseByID(cmd.ID.DbID)
   188  	if err != nil {
   189  		panic(err)
   190  	}
   191  	tbl, err := db.GetTableEntryByID(cmd.ID.TableID)
   192  
   193  	un := cmd.mvccNode
   194  	if un.Is1PC() {
   195  		if err := un.ApplyCommit(); err != nil {
   196  			panic(err)
   197  		}
   198  	}
   199  
   200  	if err != nil {
   201  		tbl = NewReplayTableEntry()
   202  		tbl.ID = cmd.ID.TableID
   203  		tbl.db = db
   204  		tbl.tableData = dataFactory.MakeTableFactory()(tbl)
   205  		tbl.TableNode = cmd.node
   206  		tbl.TableNode.schema.Store(un.BaseNode.Schema)
   207  		tbl.Insert(un)
   208  		err = db.AddEntryLocked(tbl, un.GetTxn(), true)
   209  		if err != nil {
   210  			logutil.Warn(catalog.SimplePPString(common.PPL3))
   211  			panic(err)
   212  		}
   213  		return
   214  	}
   215  	tblun := tbl.SearchNodeLocked(un)
   216  	if tblun == nil {
   217  		tbl.Insert(un) //TODO isvalid
   218  		if tbl.isColumnChangedInSchema() {
   219  			tbl.FreezeAppend()
   220  		}
   221  		schema := un.BaseNode.Schema
   222  		tbl.TableNode.schema.Store(schema)
   223  		// alter table rename
   224  		if schema.Extra.OldName != "" && un.DeletedAt.IsEmpty() {
   225  			err := tbl.db.RenameTableInTxn(schema.Extra.OldName, schema.Name, tbl.ID, schema.AcInfo.TenantID, un.GetTxn(), true)
   226  			if err != nil {
   227  				logutil.Warn(schema.String())
   228  				panic(err)
   229  			}
   230  		}
   231  	}
   232  
   233  }
   234  
   235  func (catalog *Catalog) OnReplayTableBatch(ins, insTxn, insCol, del, delTxn *containers.Batch, dataFactory DataFactory) {
   236  	schemaOffset := 0
   237  	for i := 0; i < ins.Length(); i++ {
   238  		tid := ins.GetVectorByName(pkgcatalog.SystemRelAttr_ID).Get(i).(uint64)
   239  		dbid := ins.GetVectorByName(pkgcatalog.SystemRelAttr_DBID).Get(i).(uint64)
   240  		name := string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_Name).Get(i).([]byte))
   241  		schema := NewEmptySchema(name)
   242  		schemaOffset = schema.ReadFromBatch(insCol, schemaOffset, tid)
   243  		schema.Comment = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_Comment).Get(i).([]byte))
   244  		schema.Version = ins.GetVectorByName(pkgcatalog.SystemRelAttr_Version).Get(i).(uint32)
   245  		schema.CatalogVersion = ins.GetVectorByName(pkgcatalog.SystemRelAttr_CatalogVersion).Get(i).(uint32)
   246  		schema.Partitioned = ins.GetVectorByName(pkgcatalog.SystemRelAttr_Partitioned).Get(i).(int8)
   247  		schema.Partition = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_Partition).Get(i).([]byte))
   248  		schema.Relkind = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_Kind).Get(i).([]byte))
   249  		schema.Createsql = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_CreateSQL).Get(i).([]byte))
   250  		schema.View = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_ViewDef).Get(i).([]byte))
   251  		schema.Constraint = ins.GetVectorByName(pkgcatalog.SystemRelAttr_Constraint).Get(i).([]byte)
   252  		schema.AcInfo = accessInfo{}
   253  		schema.AcInfo.RoleID = ins.GetVectorByName(pkgcatalog.SystemRelAttr_Owner).Get(i).(uint32)
   254  		schema.AcInfo.UserID = ins.GetVectorByName(pkgcatalog.SystemRelAttr_Creator).Get(i).(uint32)
   255  		schema.AcInfo.CreateAt = ins.GetVectorByName(pkgcatalog.SystemRelAttr_CreateAt).Get(i).(types.Timestamp)
   256  		schema.AcInfo.TenantID = ins.GetVectorByName(pkgcatalog.SystemRelAttr_AccID).Get(i).(uint32)
   257  		schema.BlockMaxRows = insTxn.GetVectorByName(SnapshotAttr_BlockMaxRow).Get(i).(uint32)
   258  		schema.ObjectMaxBlocks = insTxn.GetVectorByName(SnapshotAttr_ObjectMaxBlock).Get(i).(uint16)
   259  		extra := insTxn.GetVectorByName(SnapshotAttr_SchemaExtra).Get(i).([]byte)
   260  		schema.MustRestoreExtra(extra)
   261  		schema.Finalize(true)
   262  		txnNode := txnbase.ReadTuple(insTxn, i)
   263  		catalog.onReplayCreateTable(dbid, tid, schema, txnNode, dataFactory)
   264  	}
   265  	for i := 0; i < del.Length(); i++ {
   266  		dbid := delTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64)
   267  		tid := delTxn.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64)
   268  		txnNode := txnbase.ReadTuple(delTxn, i)
   269  		catalog.onReplayDeleteTable(dbid, tid, txnNode)
   270  	}
   271  }
   272  
   273  func (catalog *Catalog) onReplayCreateTable(dbid, tid uint64, schema *Schema, txnNode *txnbase.TxnMVCCNode, dataFactory DataFactory) {
   274  	catalog.OnReplayTableID(tid)
   275  	db, err := catalog.GetDatabaseByID(dbid)
   276  	if err != nil {
   277  		logutil.Info(catalog.SimplePPString(common.PPL3))
   278  		panic(err)
   279  	}
   280  	tbl, _ := db.GetTableEntryByID(tid)
   281  	if tbl != nil {
   282  		tblCreatedAt := tbl.GetCreatedAtLocked()
   283  		if tblCreatedAt.Greater(&txnNode.End) {
   284  			panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), tblCreatedAt.ToString()))
   285  		}
   286  		// alter table
   287  		un := &MVCCNode[*TableMVCCNode]{
   288  			EntryMVCCNode: &EntryMVCCNode{
   289  				CreatedAt: tblCreatedAt,
   290  			},
   291  			TxnMVCCNode: txnNode,
   292  			BaseNode: &TableMVCCNode{
   293  				Schema: schema,
   294  			},
   295  		}
   296  		tbl.Insert(un)
   297  		if tbl.isColumnChangedInSchema() {
   298  			tbl.FreezeAppend()
   299  		}
   300  		tbl.TableNode.schema.Store(schema)
   301  		if schema.Extra.OldName != "" {
   302  			logutil.Infof("replay rename %v from %v -> %v", tid, schema.Extra.OldName, schema.Name)
   303  			err := tbl.db.RenameTableInTxn(schema.Extra.OldName, schema.Name, tbl.ID, schema.AcInfo.TenantID, un.GetTxn(), true)
   304  			if err != nil {
   305  				logutil.Warn(schema.String())
   306  				panic(err)
   307  			}
   308  		}
   309  
   310  		return
   311  	}
   312  	tbl = NewReplayTableEntry()
   313  	tbl.TableNode = &TableNode{}
   314  	tbl.TableNode.schema.Store(schema)
   315  	tbl.db = db
   316  	tbl.ID = tid
   317  	tbl.tableData = dataFactory.MakeTableFactory()(tbl)
   318  	_ = db.AddEntryLocked(tbl, nil, true)
   319  	un := &MVCCNode[*TableMVCCNode]{
   320  		EntryMVCCNode: &EntryMVCCNode{
   321  			CreatedAt: txnNode.End,
   322  		},
   323  		TxnMVCCNode: txnNode,
   324  		BaseNode: &TableMVCCNode{
   325  			Schema: schema,
   326  		},
   327  	}
   328  	tbl.Insert(un)
   329  }
   330  func (catalog *Catalog) onReplayDeleteTable(dbid, tid uint64, txnNode *txnbase.TxnMVCCNode) {
   331  	catalog.OnReplayTableID(tid)
   332  	db, err := catalog.GetDatabaseByID(dbid)
   333  	if err != nil {
   334  		logutil.Info(catalog.SimplePPString(common.PPL3))
   335  		panic(err)
   336  	}
   337  	tbl, err := db.GetTableEntryByID(tid)
   338  	if err != nil {
   339  		logutil.Info(catalog.SimplePPString(common.PPL3))
   340  		panic(err)
   341  	}
   342  	tableDeleteAt := tbl.GetDeleteAtLocked()
   343  	if !tableDeleteAt.IsEmpty() {
   344  		if !tableDeleteAt.Equal(&txnNode.End) {
   345  			panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), tableDeleteAt.ToString()))
   346  		}
   347  		return
   348  	}
   349  	prev := tbl.MVCCChain.GetLatestCommittedNodeLocked()
   350  	un := &MVCCNode[*TableMVCCNode]{
   351  		EntryMVCCNode: &EntryMVCCNode{
   352  			CreatedAt: prev.CreatedAt,
   353  			DeletedAt: txnNode.End,
   354  		},
   355  		TxnMVCCNode: txnNode,
   356  		BaseNode:    prev.BaseNode.CloneAll(),
   357  	}
   358  	tbl.Insert(un)
   359  
   360  }
   361  func (catalog *Catalog) onReplayUpdateObject(
   362  	cmd *EntryCommand[*ObjectMVCCNode, *ObjectNode],
   363  	dataFactory DataFactory,
   364  	observer wal.ReplayObserver) {
   365  	catalog.OnReplayObjectID(cmd.node.SortHint)
   366  
   367  	db, err := catalog.GetDatabaseByID(cmd.ID.DbID)
   368  	if err != nil {
   369  		panic(err)
   370  	}
   371  	tbl, err := db.GetTableEntryByID(cmd.ID.TableID)
   372  	if err != nil {
   373  		logutil.Debugf("tbl %d-%d", cmd.ID.DbID, cmd.ID.TableID)
   374  		logutil.Info(catalog.SimplePPString(3))
   375  		panic(err)
   376  	}
   377  	obj, err := tbl.GetObjectByID(cmd.ID.ObjectID())
   378  	un := cmd.mvccNode
   379  	if un.Is1PC() {
   380  		if err := un.ApplyCommit(); err != nil {
   381  			panic(err)
   382  		}
   383  	}
   384  	if err != nil {
   385  		obj = NewReplayObjectEntry()
   386  		obj.ID = *cmd.ID.ObjectID()
   387  		obj.table = tbl
   388  		obj.Insert(un)
   389  		obj.ObjectNode = cmd.node
   390  		tbl.AddEntryLocked(obj)
   391  	} else {
   392  		node := obj.SearchNodeLocked(un)
   393  		if node == nil {
   394  			obj.Insert(un)
   395  		} else {
   396  			node.BaseNode.Update(un.BaseNode)
   397  		}
   398  	}
   399  	if obj.objData == nil {
   400  		obj.objData = dataFactory.MakeObjectFactory()(obj)
   401  	} else {
   402  		deleteAt := obj.GetDeleteAtLocked()
   403  		if !obj.IsAppendable() || (obj.IsAppendable() && !deleteAt.IsEmpty()) {
   404  			obj.objData.TryUpgrade()
   405  			obj.objData.UpgradeAllDeleteChain()
   406  		}
   407  	}
   408  }
   409  
   410  func (catalog *Catalog) OnReplayObjectBatch(objectInfo *containers.Batch, dataFactory DataFactory) {
   411  	dbidVec := objectInfo.GetVectorByName(SnapshotAttr_DBID)
   412  	for i := 0; i < dbidVec.Length(); i++ {
   413  		dbid := objectInfo.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64)
   414  		tid := objectInfo.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64)
   415  		objectNode := ReadObjectInfoTuple(objectInfo, i)
   416  		sid := objectNode.ObjectName().ObjectId()
   417  		txnNode := txnbase.ReadTuple(objectInfo, i)
   418  		entryNode := ReadEntryNodeTuple(objectInfo, i)
   419  		state := objectInfo.GetVectorByName(ObjectAttr_State).Get(i).(bool)
   420  		entryState := ES_Appendable
   421  		if !state {
   422  			entryState = ES_NotAppendable
   423  		}
   424  		catalog.onReplayCheckpointObject(dbid, tid, sid, objectNode, entryNode, txnNode, entryState, dataFactory)
   425  	}
   426  }
   427  
   428  func (catalog *Catalog) onReplayCheckpointObject(
   429  	dbid, tbid uint64,
   430  	objid *types.Objectid,
   431  	objNode *ObjectMVCCNode,
   432  	entryNode *EntryMVCCNode,
   433  	txnNode *txnbase.TxnMVCCNode,
   434  	state EntryState,
   435  	dataFactory DataFactory,
   436  ) {
   437  	db, err := catalog.GetDatabaseByID(dbid)
   438  	if err != nil {
   439  		logutil.Info(catalog.SimplePPString(common.PPL3))
   440  		panic(err)
   441  	}
   442  	rel, err := db.GetTableEntryByID(tbid)
   443  	if err != nil {
   444  		logutil.Info(catalog.SimplePPString(common.PPL3))
   445  		panic(err)
   446  	}
   447  	obj, _ := rel.GetObjectByID(objid)
   448  	if obj == nil {
   449  		obj = NewReplayObjectEntry()
   450  		obj.ID = *objid
   451  		obj.table = rel
   452  		obj.ObjectNode = &ObjectNode{
   453  			state:    state,
   454  			sorted:   state == ES_NotAppendable,
   455  			SortHint: catalog.NextObject(),
   456  		}
   457  		rel.AddEntryLocked(obj)
   458  	}
   459  	un := &MVCCNode[*ObjectMVCCNode]{
   460  		EntryMVCCNode: entryNode,
   461  		BaseNode:      objNode,
   462  		TxnMVCCNode:   txnNode,
   463  	}
   464  	node := obj.SearchNodeLocked(un)
   465  	if node == nil {
   466  		obj.Insert(un)
   467  	} else {
   468  		node.BaseNode.Update(un.BaseNode)
   469  	}
   470  	if obj.objData == nil {
   471  		obj.objData = dataFactory.MakeObjectFactory()(obj)
   472  	} else {
   473  		deleteAt := obj.GetDeleteAtLocked()
   474  		if !obj.IsAppendable() || (obj.IsAppendable() && !deleteAt.IsEmpty()) {
   475  			obj.objData.TryUpgrade()
   476  			obj.objData.UpgradeAllDeleteChain()
   477  		}
   478  	}
   479  }
   480  
   481  // Before ckp version 10 and IOET_WALTxnCommand_Object, object info doesn't exist.
   482  // Replay Object by block.
   483  // Original Size, Compressed Size and Block Number is skipped.
   484  func (catalog *Catalog) replayObjectByBlock(
   485  	tbl *TableEntry,
   486  	blkID types.Blockid,
   487  	state EntryState,
   488  	start, end types.TS,
   489  	metaLocation objectio.Location,
   490  	needApplyCommit bool,
   491  	create, delete bool,
   492  	txn txnif.TxnReader,
   493  	dataFactory DataFactory) {
   494  	ObjectID := blkID.Object()
   495  	obj, _ := tbl.GetObjectByID(ObjectID)
   496  	// create
   497  	if create {
   498  		if obj == nil {
   499  			obj = NewObjectEntryByMetaLocation(
   500  				tbl,
   501  				ObjectID,
   502  				start, end, state, metaLocation, dataFactory.MakeObjectFactory())
   503  			tbl.AddEntryLocked(obj)
   504  		}
   505  	}
   506  	// delete
   507  	if delete {
   508  		node := obj.SearchNodeLocked(
   509  			&MVCCNode[*ObjectMVCCNode]{
   510  				TxnMVCCNode: &txnbase.TxnMVCCNode{
   511  					Start: start,
   512  				},
   513  			},
   514  		)
   515  		if node == nil {
   516  			node = obj.GetLatestNodeLocked().CloneData()
   517  			node.Start = start
   518  			node.Prepare = end
   519  			node.End = end
   520  			if node.BaseNode.IsEmpty() {
   521  				node.BaseNode = NewObjectInfoWithMetaLocation(metaLocation, ObjectID)
   522  			}
   523  			obj.Insert(node)
   524  			node.DeletedAt = end
   525  		}
   526  	}
   527  	_, blkOffset := blkID.Offsets()
   528  	obj.tryUpdateBlockCnt(int(blkOffset) + 1)
   529  	if obj.objData == nil {
   530  		obj.objData = dataFactory.MakeObjectFactory()(obj)
   531  	} else {
   532  		deleteAt := obj.GetDeleteAtLocked()
   533  		if !obj.IsAppendable() || (obj.IsAppendable() && !deleteAt.IsEmpty()) {
   534  			obj.objData.TryUpgrade()
   535  			obj.objData.UpgradeAllDeleteChain()
   536  		}
   537  	}
   538  }
   539  func (catalog *Catalog) onReplayUpdateBlock(
   540  	cmd *EntryCommand[*MetadataMVCCNode, *BlockNode],
   541  	dataFactory DataFactory,
   542  	observer wal.ReplayObserver) {
   543  	// catalog.OnReplayBlockID(cmd.ID.BlockID)
   544  	db, err := catalog.GetDatabaseByID(cmd.ID.DbID)
   545  	if err != nil {
   546  		panic(err)
   547  	}
   548  	tbl, err := db.GetTableEntryByID(cmd.ID.TableID)
   549  	if err != nil {
   550  		panic(err)
   551  	}
   552  	catalog.replayObjectByBlock(
   553  		tbl,
   554  		cmd.ID.BlockID,
   555  		cmd.node.state,
   556  		cmd.mvccNode.Start,
   557  		cmd.mvccNode.Prepare,
   558  		cmd.mvccNode.BaseNode.MetaLoc,
   559  		true,
   560  		cmd.mvccNode.CreatedAt.Equal(&txnif.UncommitTS),
   561  		cmd.mvccNode.DeletedAt.Equal(&txnif.UncommitTS),
   562  		cmd.mvccNode.Txn,
   563  		dataFactory)
   564  	if !cmd.mvccNode.BaseNode.DeltaLoc.IsEmpty() {
   565  		obj, err := tbl.GetObjectByID(cmd.ID.ObjectID())
   566  		if err != nil {
   567  			panic(err)
   568  		}
   569  		tombstone := tbl.GetOrCreateTombstone(obj, dataFactory.MakeTombstoneFactory())
   570  		_, blkOffset := cmd.ID.BlockID.Offsets()
   571  		tombstone.ReplayDeltaLoc(cmd.mvccNode, blkOffset)
   572  	}
   573  }
   574  
   575  func (catalog *Catalog) OnReplayBlockBatch(ins, insTxn, del, delTxn *containers.Batch, dataFactory DataFactory) {
   576  	for i := 0; i < ins.Length(); i++ {
   577  		dbid := insTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64)
   578  		tid := insTxn.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64)
   579  		appendable := ins.GetVectorByName(pkgcatalog.BlockMeta_EntryState).Get(i).(bool)
   580  		state := ES_NotAppendable
   581  		if appendable {
   582  			state = ES_Appendable
   583  		}
   584  		blkID := ins.GetVectorByName(pkgcatalog.BlockMeta_ID).Get(i).(types.Blockid)
   585  		sid := blkID.Object()
   586  		metaLoc := ins.GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Get(i).([]byte)
   587  		deltaLoc := ins.GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Get(i).([]byte)
   588  		txnNode := txnbase.ReadTuple(insTxn, i)
   589  		catalog.onReplayCreateBlock(dbid, tid, sid, &blkID, state, metaLoc, deltaLoc, txnNode, dataFactory)
   590  	}
   591  	for i := 0; i < del.Length(); i++ {
   592  		dbid := delTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64)
   593  		tid := delTxn.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64)
   594  		rid := del.GetVectorByName(AttrRowID).Get(i).(types.Rowid)
   595  		blkID := rid.BorrowBlockID()
   596  		sid := rid.BorrowObjectID()
   597  		un := txnbase.ReadTuple(delTxn, i)
   598  		metaLoc := delTxn.GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Get(i).([]byte)
   599  		deltaLoc := delTxn.GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Get(i).([]byte)
   600  		catalog.onReplayDeleteBlock(dbid, tid, sid, blkID, metaLoc, deltaLoc, un)
   601  	}
   602  }
   603  func (catalog *Catalog) onReplayCreateBlock(
   604  	dbid, tid uint64,
   605  	objid *types.Objectid,
   606  	blkid *types.Blockid,
   607  	state EntryState,
   608  	metaloc, deltaloc objectio.Location,
   609  	txnNode *txnbase.TxnMVCCNode,
   610  	dataFactory DataFactory) {
   611  	// catalog.OnReplayBlockID(blkid)
   612  	db, err := catalog.GetDatabaseByID(dbid)
   613  	if err != nil {
   614  		logutil.Info(catalog.SimplePPString(common.PPL3))
   615  		panic(err)
   616  	}
   617  	rel, err := db.GetTableEntryByID(tid)
   618  	if err != nil {
   619  		logutil.Info(catalog.SimplePPString(common.PPL3))
   620  		panic(err)
   621  	}
   622  	catalog.replayObjectByBlock(
   623  		rel,
   624  		*blkid,
   625  		state,
   626  		txnNode.Start,
   627  		txnNode.End,
   628  		metaloc,
   629  		false,
   630  		true,
   631  		false,
   632  		nil,
   633  		dataFactory)
   634  	if !deltaloc.IsEmpty() {
   635  		obj, err := rel.GetObjectByID(objid)
   636  		if err != nil {
   637  			panic(err)
   638  		}
   639  		tombstone := rel.GetOrCreateTombstone(obj, dataFactory.MakeTombstoneFactory())
   640  		_, blkOffset := blkid.Offsets()
   641  		mvccNode := &MVCCNode[*MetadataMVCCNode]{
   642  			EntryMVCCNode: &EntryMVCCNode{},
   643  			TxnMVCCNode:   txnNode,
   644  			BaseNode: &MetadataMVCCNode{
   645  				DeltaLoc: deltaloc,
   646  			},
   647  		}
   648  		tombstone.ReplayDeltaLoc(mvccNode, blkOffset)
   649  	}
   650  }
   651  
   652  func (catalog *Catalog) onReplayDeleteBlock(
   653  	dbid, tid uint64,
   654  	objid *types.Objectid,
   655  	blkid *types.Blockid,
   656  	metaloc,
   657  	deltaloc objectio.Location,
   658  	txnNode *txnbase.TxnMVCCNode,
   659  ) {
   660  	// catalog.OnReplayBlockID(blkid)
   661  	db, err := catalog.GetDatabaseByID(dbid)
   662  	if err != nil {
   663  		logutil.Info(catalog.SimplePPString(common.PPL3))
   664  		panic(err)
   665  	}
   666  	rel, err := db.GetTableEntryByID(tid)
   667  	if err != nil {
   668  		logutil.Info(catalog.SimplePPString(common.PPL3))
   669  		panic(err)
   670  	}
   671  	catalog.replayObjectByBlock(
   672  		rel,
   673  		*blkid,
   674  		ES_Appendable, // state is not used when delete
   675  		txnNode.Start,
   676  		txnNode.End,
   677  		metaloc,
   678  		false,
   679  		false,
   680  		true,
   681  		nil,
   682  		nil)
   683  }
   684  func (catalog *Catalog) ReplayTableRows() {
   685  	rows := uint64(0)
   686  	tableProcessor := new(LoopProcessor)
   687  	tableProcessor.ObjectFn = func(be *ObjectEntry) error {
   688  		if !be.IsActive() {
   689  			return nil
   690  		}
   691  		rows += be.GetObjectData().GetRowsOnReplay()
   692  		return nil
   693  	}
   694  	tableProcessor.TombstoneFn = func(t data.Tombstone) error {
   695  		rows -= uint64(t.GetDeleteCnt())
   696  		return nil
   697  	}
   698  	processor := new(LoopProcessor)
   699  	processor.TableFn = func(tbl *TableEntry) error {
   700  		if tbl.db.name == pkgcatalog.MO_CATALOG {
   701  			return nil
   702  		}
   703  		rows = 0
   704  		err := tbl.RecurLoop(tableProcessor)
   705  		if err != nil {
   706  			panic(err)
   707  		}
   708  		tbl.rows.Store(rows)
   709  		return nil
   710  	}
   711  	err := catalog.RecurLoop(processor)
   712  	if err != nil {
   713  		panic(err)
   714  	}
   715  }
   716  
   717  //#endregion