github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/logtail/utils.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 logtail
    16  
    17  import (
    18  	"fmt"
    19  	"time"
    20  
    21  	pkgcatalog "github.com/matrixorigin/matrixone/pkg/catalog"
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    24  	"github.com/matrixorigin/matrixone/pkg/container/types"
    25  	"github.com/matrixorigin/matrixone/pkg/logutil"
    26  	"github.com/matrixorigin/matrixone/pkg/objectio"
    27  	"github.com/matrixorigin/matrixone/pkg/pb/api"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    29  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    30  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    31  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/dataio/blockio"
    32  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tasks"
    33  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnimpl"
    34  )
    35  
    36  const (
    37  	MetaIDX uint16 = iota
    38  
    39  	DBInsertIDX
    40  	DBInsertTxnIDX
    41  	DBDeleteIDX
    42  	DBDeleteTxnIDX
    43  
    44  	TBLInsertIDX
    45  	TBLInsertTxnIDX
    46  	TBLDeleteIDX
    47  	TBLDeleteTxnIDX
    48  	TBLColInsertIDX
    49  	TBLColDeleteIDX
    50  
    51  	SEGInsertIDX
    52  	SEGInsertTxnIDX
    53  	SEGDeleteIDX
    54  	SEGDeleteTxnIDX
    55  
    56  	BLKMetaInsertIDX
    57  	BLKMetaInsertTxnIDX
    58  	BLKMetaDeleteIDX
    59  	BLKMetaDeleteTxnIDX
    60  
    61  	BLKDNMetaInsertIDX
    62  	BLKDNMetaInsertTxnIDX
    63  	BLKDNMetaDeleteIDX
    64  	BLKDNMetaDeleteTxnIDX
    65  
    66  	BLKCNMetaInsertIDX
    67  
    68  	BLKInsertIDX
    69  	BLKInsertTxnIDX
    70  	BLKDeleteIDX
    71  	BLKDeleteTxnIDX
    72  )
    73  
    74  const MaxIDX = BLKCNMetaInsertIDX + 1
    75  
    76  type checkpointDataItem struct {
    77  	schema    *catalog.Schema
    78  	types     []types.Type
    79  	attrs     []string
    80  	nullables []bool
    81  }
    82  
    83  var checkpointDataSchemas [MaxIDX]*catalog.Schema
    84  
    85  var checkpointDataRefer [MaxIDX]*checkpointDataItem
    86  
    87  func init() {
    88  	checkpointDataSchemas = [MaxIDX]*catalog.Schema{
    89  		MetaSchema,
    90  		catalog.SystemDBSchema,
    91  		TxnNodeSchema,
    92  		DelSchema,
    93  		DBDNSchema,
    94  		catalog.SystemTableSchema,
    95  		TblDNSchema,
    96  		DelSchema,
    97  		TblDNSchema,
    98  		catalog.SystemColumnSchema,
    99  		DelSchema,
   100  		SegSchema,
   101  		SegDNSchema,
   102  		DelSchema,
   103  		SegDNSchema,
   104  		BlkMetaSchema,
   105  		BlkDNSchema,
   106  		DelSchema,
   107  		BlkDNSchema,
   108  		BlkMetaSchema,
   109  		BlkDNSchema,
   110  		DelSchema,
   111  		BlkDNSchema,
   112  		BlkMetaSchema,
   113  	}
   114  	for idx, schema := range checkpointDataSchemas {
   115  		checkpointDataRefer[idx] = &checkpointDataItem{
   116  			schema,
   117  			append(BaseTypes, schema.Types()...),
   118  			append(BaseAttr, schema.AllNames()...),
   119  			append([]bool{false, false}, schema.AllNullables()...),
   120  		}
   121  	}
   122  }
   123  
   124  func IncrementalCheckpointDataFactory(start, end types.TS) func(c *catalog.Catalog) (*CheckpointData, error) {
   125  	return func(c *catalog.Catalog) (data *CheckpointData, err error) {
   126  		collector := NewIncrementalCollector(start, end)
   127  		defer collector.Close()
   128  		err = c.RecurLoop(collector)
   129  		if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) {
   130  			err = nil
   131  		}
   132  		collector.data.prepareMeta()
   133  		if err != nil {
   134  			return
   135  		}
   136  		data = collector.OrphanData()
   137  		return
   138  	}
   139  }
   140  
   141  func GlobalCheckpointDataFactory(end types.TS, versionInterval time.Duration) func(c *catalog.Catalog) (*CheckpointData, error) {
   142  	return func(c *catalog.Catalog) (data *CheckpointData, err error) {
   143  		collector := NewGlobalCollector(end, versionInterval)
   144  		defer collector.Close()
   145  		err = c.RecurLoop(collector)
   146  		if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) {
   147  			err = nil
   148  		}
   149  		collector.data.prepareMeta()
   150  		if err != nil {
   151  			return
   152  		}
   153  		data = collector.OrphanData()
   154  		return
   155  	}
   156  }
   157  
   158  type CheckpointMeta struct {
   159  	blkInsertOffset *common.ClosedInterval
   160  	blkDeleteOffset *common.ClosedInterval
   161  }
   162  
   163  func NewCheckpointMeta() *CheckpointMeta {
   164  	return &CheckpointMeta{}
   165  }
   166  
   167  type CheckpointData struct {
   168  	meta map[uint64]*CheckpointMeta
   169  	bats [MaxIDX]*containers.Batch
   170  }
   171  
   172  func NewCheckpointData() *CheckpointData {
   173  	data := &CheckpointData{
   174  		meta: make(map[uint64]*CheckpointMeta),
   175  	}
   176  	for idx, schema := range checkpointDataSchemas {
   177  		data.bats[idx] = makeRespBatchFromSchema(schema)
   178  	}
   179  	return data
   180  }
   181  
   182  type BaseCollector struct {
   183  	*catalog.LoopProcessor
   184  	start, end types.TS
   185  
   186  	data *CheckpointData
   187  }
   188  
   189  type IncrementalCollector struct {
   190  	*BaseCollector
   191  }
   192  
   193  func NewIncrementalCollector(start, end types.TS) *IncrementalCollector {
   194  	collector := &IncrementalCollector{
   195  		BaseCollector: &BaseCollector{
   196  			LoopProcessor: new(catalog.LoopProcessor),
   197  			data:          NewCheckpointData(),
   198  			start:         start,
   199  			end:           end,
   200  		},
   201  	}
   202  	collector.DatabaseFn = collector.VisitDB
   203  	collector.TableFn = collector.VisitTable
   204  	collector.SegmentFn = collector.VisitSeg
   205  	collector.BlockFn = collector.VisitBlk
   206  	return collector
   207  }
   208  
   209  type GlobalCollector struct {
   210  	*BaseCollector
   211  	versionThershold types.TS
   212  }
   213  
   214  func NewGlobalCollector(end types.TS, versionInterval time.Duration) *GlobalCollector {
   215  	versionThresholdTS := types.BuildTS(end.Physical()-versionInterval.Nanoseconds(), end.Logical())
   216  	collector := &GlobalCollector{
   217  		BaseCollector: &BaseCollector{
   218  			LoopProcessor: new(catalog.LoopProcessor),
   219  			data:          NewCheckpointData(),
   220  			end:           end,
   221  		},
   222  		versionThershold: versionThresholdTS,
   223  	}
   224  	collector.DatabaseFn = collector.VisitDB
   225  	collector.TableFn = collector.VisitTable
   226  	collector.SegmentFn = collector.VisitSeg
   227  	collector.BlockFn = collector.VisitBlk
   228  	return collector
   229  }
   230  
   231  func (data *CheckpointData) ApplyReplayTo(
   232  	c *catalog.Catalog,
   233  	dataFactory catalog.DataFactory) (err error) {
   234  	c.OnReplayDatabaseBatch(data.GetDBBatchs())
   235  	ins, colins, dnins, del, dndel := data.GetTblBatchs()
   236  	c.OnReplayTableBatch(ins, colins, dnins, del, dndel, dataFactory)
   237  	ins, dnins, del, dndel = data.GetSegBatchs()
   238  	c.OnReplaySegmentBatch(ins, dnins, del, dndel, dataFactory)
   239  	ins, dnins, del, dndel = data.GetDNBlkBatchs()
   240  	c.OnReplayBlockBatch(ins, dnins, del, dndel, dataFactory)
   241  	ins, dnins, del, dndel = data.GetBlkBatchs()
   242  	c.OnReplayBlockBatch(ins, dnins, del, dndel, dataFactory)
   243  	return
   244  }
   245  func (data *CheckpointData) GetTableMeta(tableID uint64) (meta *CheckpointMeta) {
   246  	if len(data.meta) != 0 {
   247  		meta = data.meta[tableID]
   248  		return
   249  	}
   250  	for i := 0; i < data.bats[MetaIDX].GetVectorByName(SnapshotMetaAttr_Tid).Length(); i++ {
   251  		tid := data.bats[MetaIDX].GetVectorByName(SnapshotMetaAttr_Tid).Get(i).(uint64)
   252  		insStart := data.bats[MetaIDX].GetVectorByName(SnapshotMetaAttr_BlockInsertBatchStart).Get(i).(int32)
   253  		insEnd := data.bats[MetaIDX].GetVectorByName(SnapshotMetaAttr_BlockInsertBatchEnd).Get(i).(int32)
   254  		delStart := data.bats[MetaIDX].GetVectorByName(SnapshotMetaAttr_BlockDeleteBatchStart).Get(i).(int32)
   255  		delEnd := data.bats[MetaIDX].GetVectorByName(SnapshotMetaAttr_BlockDeleteBatchEnd).Get(i).(int32)
   256  		meta := new(CheckpointMeta)
   257  		if insStart != -1 {
   258  			meta.blkInsertOffset = &common.ClosedInterval{
   259  				Start: uint64(insStart),
   260  				End:   uint64(insEnd),
   261  			}
   262  		}
   263  		if delStart != -1 {
   264  			meta.blkDeleteOffset = &common.ClosedInterval{
   265  				Start: uint64(delStart),
   266  				End:   uint64(delEnd),
   267  			}
   268  		}
   269  		data.meta[tid] = meta
   270  		// logutil.Infof("GetTableMeta TID=%d, INTERVAL=%s", tid, meta.blkInsertOffset.String())
   271  	}
   272  	meta = data.meta[tableID]
   273  	return
   274  }
   275  func (data *CheckpointData) GetTableData(tid uint64) (ins, del, cnIns *api.Batch, err error) {
   276  	var insTaeBat, delTaeBat, cnInsTaeBat *containers.Batch
   277  	switch tid {
   278  	case pkgcatalog.MO_DATABASE_ID:
   279  		insTaeBat = data.bats[DBInsertIDX]
   280  		delTaeBat = data.bats[DBDeleteIDX]
   281  		if insTaeBat != nil {
   282  			ins, err = containersBatchToProtoBatch(insTaeBat)
   283  			if err != nil {
   284  				return
   285  			}
   286  		}
   287  		if delTaeBat != nil {
   288  			del, err = containersBatchToProtoBatch(delTaeBat)
   289  			if err != nil {
   290  				return
   291  			}
   292  		}
   293  		return
   294  	case pkgcatalog.MO_TABLES_ID:
   295  		insTaeBat = data.bats[TBLInsertIDX]
   296  		delTaeBat = data.bats[TBLDeleteIDX]
   297  		if insTaeBat != nil {
   298  			ins, err = containersBatchToProtoBatch(insTaeBat)
   299  			if err != nil {
   300  				return
   301  			}
   302  		}
   303  		if delTaeBat != nil {
   304  			del, err = containersBatchToProtoBatch(delTaeBat)
   305  			if err != nil {
   306  				return
   307  			}
   308  		}
   309  		return
   310  	case pkgcatalog.MO_COLUMNS_ID:
   311  		insTaeBat = data.bats[TBLColInsertIDX]
   312  		delTaeBat = data.bats[TBLColDeleteIDX]
   313  		if insTaeBat != nil {
   314  			ins, err = containersBatchToProtoBatch(insTaeBat)
   315  			if err != nil {
   316  				return
   317  			}
   318  		}
   319  		if delTaeBat != nil {
   320  			del, err = containersBatchToProtoBatch(delTaeBat)
   321  			if err != nil {
   322  				return
   323  			}
   324  		}
   325  		return
   326  	}
   327  
   328  	// For Debug
   329  	// if insTaeBat != nil {
   330  	// 	logutil.Infof("GetTableData: TID=%d %s", tid, BatchToString("INS-DATA", insTaeBat, true))
   331  	// }
   332  	// if delTaeBat != nil {
   333  	// 	logutil.Infof("GetTableData: TID=%d %s", tid, BatchToString("DEL-DATA", delTaeBat, true))
   334  	// }
   335  
   336  	meta := data.GetTableMeta(tid)
   337  	if meta == nil {
   338  		return nil, nil, nil, nil
   339  	}
   340  
   341  	insInterval := meta.blkInsertOffset
   342  	if insInterval != nil {
   343  		insOffset := insInterval.Start
   344  		insLength := insInterval.End - insInterval.Start
   345  		insTaeBat = data.bats[BLKMetaInsertIDX].Window(int(insOffset), int(insLength))
   346  	}
   347  
   348  	delInterval := meta.blkDeleteOffset
   349  	if delInterval != nil {
   350  		delOffset := delInterval.Start
   351  		delLength := delInterval.End - delInterval.Start
   352  		delTaeBat = data.bats[BLKMetaDeleteIDX].Window(int(delOffset), int(delLength))
   353  		cnInsTaeBat = data.bats[BLKCNMetaInsertIDX].Window(int(delOffset), int(delLength))
   354  	}
   355  
   356  	if insTaeBat != nil {
   357  		ins, err = containersBatchToProtoBatch(insTaeBat)
   358  		if err != nil {
   359  			return
   360  		}
   361  	}
   362  	if delTaeBat != nil {
   363  		del, err = containersBatchToProtoBatch(delTaeBat)
   364  		if err != nil {
   365  			return
   366  		}
   367  		cnIns, err = containersBatchToProtoBatch(cnInsTaeBat)
   368  		if err != nil {
   369  			return
   370  		}
   371  	}
   372  
   373  	// For debug
   374  	// if insTaeBat != nil {
   375  	// 	logutil.Infof("GetTableData: TID=%d %s", tid, BatchToString("INS-BLK-DATA", insTaeBat, true))
   376  	// }
   377  	// if delTaeBat != nil {
   378  	// 	logutil.Infof("GetTableData: TID=%d %s", tid, BatchToString("DEL-BLK-DATA", delTaeBat, true))
   379  	// }
   380  	// if cnInsTaeBat != nil {
   381  	// 	logutil.Infof("GetTableData: TID=%d %s", tid, BatchToString("CN-INS-DATA", cnInsTaeBat, true))
   382  	// }
   383  	return
   384  }
   385  
   386  func (data *CheckpointData) prepareMeta() {
   387  	bat := data.bats[MetaIDX]
   388  	for tid, meta := range data.meta {
   389  		bat.GetVectorByName(SnapshotMetaAttr_Tid).Append(tid)
   390  		if meta.blkInsertOffset == nil {
   391  			bat.GetVectorByName(SnapshotMetaAttr_BlockInsertBatchStart).Append(int32(-1))
   392  			bat.GetVectorByName(SnapshotMetaAttr_BlockInsertBatchEnd).Append(int32(-1))
   393  		} else {
   394  			bat.GetVectorByName(SnapshotMetaAttr_BlockInsertBatchStart).Append(int32(meta.blkInsertOffset.Start))
   395  			bat.GetVectorByName(SnapshotMetaAttr_BlockInsertBatchEnd).Append(int32(meta.blkInsertOffset.End))
   396  		}
   397  		if meta.blkDeleteOffset == nil {
   398  			bat.GetVectorByName(SnapshotMetaAttr_BlockDeleteBatchStart).Append(int32(-1))
   399  			bat.GetVectorByName(SnapshotMetaAttr_BlockDeleteBatchEnd).Append(int32(-1))
   400  		} else {
   401  			bat.GetVectorByName(SnapshotMetaAttr_BlockDeleteBatchStart).Append(int32(meta.blkDeleteOffset.Start))
   402  			bat.GetVectorByName(SnapshotMetaAttr_BlockDeleteBatchEnd).Append(int32(meta.blkDeleteOffset.End))
   403  		}
   404  	}
   405  }
   406  
   407  func (data *CheckpointData) UpdateBlkMeta(tid uint64, insStart, insEnd, delStart, delEnd int32) {
   408  	if delEnd < delStart && insEnd < insStart {
   409  		return
   410  	}
   411  	meta, ok := data.meta[tid]
   412  	if !ok {
   413  		meta = NewCheckpointMeta()
   414  		data.meta[tid] = meta
   415  	}
   416  	if delEnd >= delStart {
   417  		if meta.blkDeleteOffset == nil {
   418  			meta.blkDeleteOffset = &common.ClosedInterval{Start: uint64(delStart), End: uint64(delEnd)}
   419  		} else {
   420  			if !meta.blkDeleteOffset.TryMerge(common.ClosedInterval{Start: uint64(delStart), End: uint64(delEnd)}) {
   421  				panic(fmt.Sprintf("logic error interval %v, start %d, end %d", meta.blkDeleteOffset, delStart, delEnd))
   422  			}
   423  		}
   424  	}
   425  	if insEnd >= insStart {
   426  		if meta.blkInsertOffset == nil {
   427  			meta.blkInsertOffset = &common.ClosedInterval{Start: uint64(insStart), End: uint64(insEnd)}
   428  		} else {
   429  			if !meta.blkInsertOffset.TryMerge(common.ClosedInterval{Start: uint64(insStart), End: uint64(insEnd)}) {
   430  				panic(fmt.Sprintf("logic error interval %v, start %d, end %d", meta.blkInsertOffset, insStart, insEnd))
   431  			}
   432  		}
   433  	}
   434  }
   435  
   436  func (data *CheckpointData) PrintData() {
   437  	logutil.Info(BatchToString("BLK-META-DEL-BAT", data.bats[BLKMetaDeleteIDX], true))
   438  	logutil.Info(BatchToString("BLK-META-INS-BAT", data.bats[BLKMetaInsertIDX], true))
   439  }
   440  
   441  func (data *CheckpointData) WriteTo(
   442  	writer *blockio.Writer) (blks []objectio.BlockObject, err error) {
   443  	for _, bat := range data.bats {
   444  		if _, err = writer.WriteBlock(bat); err != nil {
   445  			return
   446  		}
   447  	}
   448  	blks, err = writer.Sync()
   449  	return
   450  }
   451  
   452  // TODO:
   453  // There need a global io pool
   454  func (data *CheckpointData) ReadFrom(
   455  	reader *blockio.Reader,
   456  	scheduler tasks.JobScheduler,
   457  	m *mpool.MPool) (err error) {
   458  	metas, err := reader.ReadMetas(m)
   459  	if err != nil {
   460  		return
   461  	}
   462  
   463  	if scheduler == nil {
   464  		scheduler = tasks.NewParallelJobScheduler(100)
   465  		defer scheduler.Stop()
   466  	}
   467  
   468  	jobs := make([]*tasks.Job, MaxIDX)
   469  
   470  	for idx, item := range checkpointDataRefer {
   471  		job := reader.BlkColumnByMetaLoadJob(
   472  			item.types,
   473  			item.attrs,
   474  			item.nullables,
   475  			metas[idx],
   476  		)
   477  		if err = scheduler.Schedule(job); err != nil {
   478  			break
   479  		}
   480  		jobs[idx] = job
   481  	}
   482  
   483  	cleanJobs := func() {
   484  		for _, job := range jobs {
   485  			if job == nil {
   486  				continue
   487  			}
   488  			result := job.WaitDone()
   489  			defer job.Close()
   490  			if result != nil && result.Res != nil {
   491  				result.Res.(*containers.Batch).Close()
   492  				result.Res = nil
   493  			}
   494  		}
   495  	}
   496  
   497  	if err != nil {
   498  		go cleanJobs()
   499  		return
   500  	}
   501  
   502  	for _, job := range jobs {
   503  		result := job.WaitDone()
   504  		if err = result.Err; err != nil {
   505  			break
   506  		}
   507  	}
   508  
   509  	if err != nil {
   510  		go cleanJobs()
   511  		return
   512  	}
   513  
   514  	for idx, job := range jobs {
   515  		result := job.GetResult()
   516  		data.bats[idx] = result.Res.(*containers.Batch)
   517  	}
   518  
   519  	return
   520  }
   521  
   522  func (data *CheckpointData) Close() {
   523  	for idx := range data.bats {
   524  		if data.bats[idx] != nil {
   525  			data.bats[idx].Close()
   526  			data.bats[idx] = nil
   527  		}
   528  	}
   529  }
   530  func (data *CheckpointData) GetDBBatchs() (
   531  	*containers.Batch,
   532  	*containers.Batch,
   533  	*containers.Batch,
   534  	*containers.Batch) {
   535  	return data.bats[DBInsertIDX],
   536  		data.bats[DBInsertTxnIDX],
   537  		data.bats[DBDeleteIDX],
   538  		data.bats[DBDeleteTxnIDX]
   539  }
   540  func (data *CheckpointData) GetTblBatchs() (
   541  	*containers.Batch,
   542  	*containers.Batch,
   543  	*containers.Batch,
   544  	*containers.Batch,
   545  	*containers.Batch) {
   546  	return data.bats[TBLInsertIDX],
   547  		data.bats[TBLInsertTxnIDX],
   548  		data.bats[TBLColInsertIDX],
   549  		data.bats[TBLDeleteIDX],
   550  		data.bats[TBLDeleteTxnIDX]
   551  }
   552  func (data *CheckpointData) GetSegBatchs() (
   553  	*containers.Batch,
   554  	*containers.Batch,
   555  	*containers.Batch,
   556  	*containers.Batch) {
   557  	return data.bats[SEGInsertIDX],
   558  		data.bats[SEGInsertTxnIDX],
   559  		data.bats[SEGDeleteIDX],
   560  		data.bats[SEGDeleteTxnIDX]
   561  }
   562  func (data *CheckpointData) GetBlkBatchs() (
   563  	*containers.Batch,
   564  	*containers.Batch,
   565  	*containers.Batch,
   566  	*containers.Batch) {
   567  	return data.bats[BLKMetaInsertIDX],
   568  		data.bats[BLKMetaInsertTxnIDX],
   569  		data.bats[BLKMetaDeleteIDX],
   570  		data.bats[BLKMetaDeleteTxnIDX]
   571  }
   572  func (data *CheckpointData) GetDNBlkBatchs() (
   573  	*containers.Batch,
   574  	*containers.Batch,
   575  	*containers.Batch,
   576  	*containers.Batch) {
   577  	return data.bats[BLKDNMetaInsertIDX],
   578  		data.bats[BLKDNMetaInsertTxnIDX],
   579  		data.bats[BLKDNMetaDeleteIDX],
   580  		data.bats[BLKDNMetaDeleteTxnIDX]
   581  }
   582  
   583  func (collector *BaseCollector) VisitDB(entry *catalog.DBEntry) error {
   584  	if shouldIgnoreDBInLogtail(entry.ID) {
   585  		return nil
   586  	}
   587  	entry.RLock()
   588  	mvccNodes := entry.ClonePreparedInRange(collector.start, collector.end)
   589  	entry.RUnlock()
   590  	for _, node := range mvccNodes {
   591  		if node.IsAborted() {
   592  			continue
   593  		}
   594  		dbNode := node.(*catalog.DBMVCCNode)
   595  		if dbNode.HasDropCommitted() {
   596  			// delScehma is empty, it will just fill rowid / commit ts
   597  			catalogEntry2Batch(
   598  				collector.data.bats[DBDeleteIDX],
   599  				entry, DelSchema,
   600  				txnimpl.FillDBRow,
   601  				u64ToRowID(entry.GetID()),
   602  				dbNode.GetEnd())
   603  			dbNode.TxnMVCCNode.AppendTuple(collector.data.bats[DBDeleteTxnIDX])
   604  			collector.data.bats[DBDeleteTxnIDX].GetVectorByName(SnapshotAttr_DBID).Append(entry.GetID())
   605  		} else {
   606  			catalogEntry2Batch(collector.data.bats[DBInsertIDX],
   607  				entry,
   608  				catalog.SystemDBSchema,
   609  				txnimpl.FillDBRow,
   610  				u64ToRowID(entry.GetID()),
   611  				dbNode.GetEnd())
   612  			dbNode.TxnMVCCNode.AppendTuple(collector.data.bats[DBInsertTxnIDX])
   613  		}
   614  	}
   615  	return nil
   616  }
   617  func (collector *GlobalCollector) isEntryDeletedBeforeThreshold(entry catalog.BaseEntry) bool {
   618  	entry.RLock()
   619  	defer entry.RUnlock()
   620  	return entry.DeleteBefore(collector.versionThershold)
   621  }
   622  func (collector *GlobalCollector) VisitDB(entry *catalog.DBEntry) error {
   623  	if collector.isEntryDeletedBeforeThreshold(entry.DBBaseEntry) {
   624  		return nil
   625  	}
   626  	return collector.BaseCollector.VisitDB(entry)
   627  }
   628  
   629  func (collector *BaseCollector) VisitTable(entry *catalog.TableEntry) (err error) {
   630  	if shouldIgnoreTblInLogtail(entry.ID) {
   631  		return nil
   632  	}
   633  	entry.RLock()
   634  	mvccNodes := entry.ClonePreparedInRange(collector.start, collector.end)
   635  	entry.RUnlock()
   636  	for _, node := range mvccNodes {
   637  		if node.IsAborted() {
   638  			continue
   639  		}
   640  		tblNode := node.(*catalog.TableMVCCNode)
   641  		if !tblNode.HasDropCommitted() {
   642  			for _, syscol := range catalog.SystemColumnSchema.ColDefs {
   643  				txnimpl.FillColumnRow(
   644  					entry,
   645  					syscol.Name,
   646  					collector.data.bats[TBLColInsertIDX].GetVectorByName(syscol.Name),
   647  				)
   648  			}
   649  			rowidVec := collector.data.bats[TBLColInsertIDX].GetVectorByName(catalog.AttrRowID)
   650  			commitVec := collector.data.bats[TBLColInsertIDX].GetVectorByName(catalog.AttrCommitTs)
   651  			for _, usercol := range entry.GetSchema().ColDefs {
   652  				rowidVec.Append(bytesToRowID([]byte(fmt.Sprintf("%d-%s", entry.GetID(), usercol.Name))))
   653  				commitVec.Append(tblNode.GetEnd())
   654  			}
   655  
   656  			collector.data.bats[TBLInsertTxnIDX].GetVectorByName(
   657  				SnapshotAttr_BlockMaxRow).Append(entry.GetSchema().BlockMaxRows)
   658  			collector.data.bats[TBLInsertTxnIDX].GetVectorByName(
   659  				SnapshotAttr_SegmentMaxBlock).Append(entry.GetSchema().SegmentMaxBlocks)
   660  
   661  			catalogEntry2Batch(
   662  				collector.data.bats[TBLInsertIDX],
   663  				entry,
   664  				catalog.SystemTableSchema,
   665  				txnimpl.FillTableRow,
   666  				u64ToRowID(entry.GetID()),
   667  				tblNode.GetEnd(),
   668  			)
   669  
   670  			tblNode.TxnMVCCNode.AppendTuple(collector.data.bats[TBLInsertTxnIDX])
   671  		} else {
   672  			collector.data.bats[TBLDeleteTxnIDX].GetVectorByName(
   673  				SnapshotAttr_DBID).Append(entry.GetDB().GetID())
   674  			collector.data.bats[TBLDeleteTxnIDX].GetVectorByName(
   675  				SnapshotAttr_TID).Append(entry.GetID())
   676  
   677  			rowidVec := collector.data.bats[TBLColDeleteIDX].GetVectorByName(catalog.AttrRowID)
   678  			commitVec := collector.data.bats[TBLColDeleteIDX].GetVectorByName(catalog.AttrCommitTs)
   679  			for _, usercol := range entry.GetSchema().ColDefs {
   680  				rowidVec.Append(
   681  					bytesToRowID([]byte(fmt.Sprintf("%d-%s", entry.GetID(), usercol.Name))),
   682  				)
   683  				commitVec.Append(tblNode.GetEnd())
   684  			}
   685  
   686  			catalogEntry2Batch(
   687  				collector.data.bats[TBLDeleteIDX],
   688  				entry, DelSchema,
   689  				txnimpl.FillTableRow,
   690  				u64ToRowID(entry.GetID()),
   691  				tblNode.GetEnd(),
   692  			)
   693  			tblNode.TxnMVCCNode.AppendTuple(collector.data.bats[TBLDeleteTxnIDX])
   694  		}
   695  	}
   696  	return nil
   697  }
   698  
   699  func (collector *GlobalCollector) VisitTable(entry *catalog.TableEntry) error {
   700  	if collector.isEntryDeletedBeforeThreshold(entry.TableBaseEntry) {
   701  		return nil
   702  	}
   703  	if collector.isEntryDeletedBeforeThreshold(entry.GetDB().DBBaseEntry) {
   704  		return nil
   705  	}
   706  	return collector.BaseCollector.VisitTable(entry)
   707  }
   708  
   709  func (collector *BaseCollector) VisitSeg(entry *catalog.SegmentEntry) (err error) {
   710  	entry.RLock()
   711  	mvccNodes := entry.ClonePreparedInRange(collector.start, collector.end)
   712  	entry.RUnlock()
   713  	if len(mvccNodes) == 0 {
   714  		return nil
   715  	}
   716  	for _, node := range mvccNodes {
   717  		if node.IsAborted() {
   718  			continue
   719  		}
   720  		segNode := node.(*catalog.MetadataMVCCNode)
   721  		if segNode.HasDropCommitted() {
   722  			collector.data.bats[SEGDeleteIDX].GetVectorByName(catalog.AttrRowID).Append(u64ToRowID(entry.ID))
   723  			collector.data.bats[SEGDeleteIDX].GetVectorByName(catalog.AttrCommitTs).Append(segNode.GetEnd())
   724  			collector.data.bats[SEGDeleteTxnIDX].GetVectorByName(SnapshotAttr_DBID).Append(entry.GetTable().GetDB().GetID())
   725  			collector.data.bats[SEGDeleteTxnIDX].GetVectorByName(SnapshotAttr_TID).Append(entry.GetTable().GetID())
   726  			segNode.TxnMVCCNode.AppendTuple(collector.data.bats[SEGDeleteTxnIDX])
   727  		} else {
   728  			collector.data.bats[SEGInsertIDX].GetVectorByName(SegmentAttr_ID).Append(entry.GetID())
   729  			collector.data.bats[SEGInsertIDX].GetVectorByName(SegmentAttr_CreateAt).Append(segNode.GetEnd())
   730  			collector.data.bats[SEGInsertIDX].GetVectorByName(SegmentAttr_State).Append(entry.IsAppendable())
   731  			collector.data.bats[SEGInsertIDX].GetVectorByName(SegmentAttr_Sorted).Append(entry.IsSorted())
   732  			collector.data.bats[SEGInsertTxnIDX].GetVectorByName(SnapshotAttr_DBID).Append(entry.GetTable().GetDB().GetID())
   733  			collector.data.bats[SEGInsertTxnIDX].GetVectorByName(SnapshotAttr_TID).Append(entry.GetTable().GetID())
   734  			segNode.TxnMVCCNode.AppendTuple(collector.data.bats[SEGInsertTxnIDX])
   735  		}
   736  	}
   737  	return nil
   738  }
   739  
   740  func (collector *GlobalCollector) VisitSeg(entry *catalog.SegmentEntry) error {
   741  	if collector.isEntryDeletedBeforeThreshold(entry.MetaBaseEntry) {
   742  		return nil
   743  	}
   744  	if collector.isEntryDeletedBeforeThreshold(entry.GetTable().TableBaseEntry) {
   745  		return nil
   746  	}
   747  	if collector.isEntryDeletedBeforeThreshold(entry.GetTable().GetDB().DBBaseEntry) {
   748  		return nil
   749  	}
   750  	return collector.BaseCollector.VisitSeg(entry)
   751  }
   752  
   753  func (collector *BaseCollector) VisitBlk(entry *catalog.BlockEntry) (err error) {
   754  	entry.RLock()
   755  	mvccNodes := entry.ClonePreparedInRange(collector.start, collector.end)
   756  	entry.RUnlock()
   757  	if len(mvccNodes) == 0 {
   758  		return nil
   759  	}
   760  	insStart := collector.data.bats[BLKMetaInsertIDX].GetVectorByName(catalog.AttrRowID).Length()
   761  	delStart := collector.data.bats[BLKMetaDeleteIDX].GetVectorByName(catalog.AttrRowID).Length()
   762  	for _, node := range mvccNodes {
   763  		if node.IsAborted() {
   764  			continue
   765  		}
   766  		metaNode := node.(*catalog.MetadataMVCCNode)
   767  		if metaNode.MetaLoc == "" || metaNode.Aborted {
   768  			if metaNode.HasDropCommitted() {
   769  				collector.data.bats[BLKDNMetaDeleteIDX].GetVectorByName(catalog.AttrRowID).Append(u64ToRowID(entry.ID))
   770  				collector.data.bats[BLKDNMetaDeleteIDX].GetVectorByName(catalog.AttrCommitTs).Append(metaNode.GetEnd())
   771  				collector.data.bats[BLKDNMetaDeleteTxnIDX].GetVectorByName(SnapshotAttr_DBID).Append(entry.GetSegment().GetTable().GetDB().GetID())
   772  				collector.data.bats[BLKDNMetaDeleteTxnIDX].GetVectorByName(SnapshotAttr_TID).Append(entry.GetSegment().GetTable().GetID())
   773  				collector.data.bats[BLKDNMetaDeleteTxnIDX].GetVectorByName(SnapshotAttr_SegID).Append(entry.GetSegment().GetID())
   774  				metaNode.TxnMVCCNode.AppendTuple(collector.data.bats[BLKDNMetaDeleteTxnIDX])
   775  				collector.data.bats[BLKDNMetaDeleteTxnIDX].GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Append([]byte(metaNode.MetaLoc))
   776  				collector.data.bats[BLKDNMetaDeleteTxnIDX].GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Append([]byte(metaNode.DeltaLoc))
   777  			} else {
   778  				collector.data.bats[BLKDNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_ID).Append(entry.ID)
   779  				collector.data.bats[BLKDNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_EntryState).Append(entry.IsAppendable())
   780  				collector.data.bats[BLKDNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Append([]byte(metaNode.MetaLoc))
   781  				collector.data.bats[BLKDNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Append([]byte(metaNode.DeltaLoc))
   782  				collector.data.bats[BLKDNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_CommitTs).Append(metaNode.GetEnd())
   783  				is_sorted := false
   784  				if !entry.IsAppendable() && entry.GetSchema().HasSortKey() {
   785  					is_sorted = true
   786  				}
   787  				collector.data.bats[BLKDNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_Sorted).Append(is_sorted)
   788  				collector.data.bats[BLKDNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_SegmentID).Append(entry.GetSegment().ID)
   789  				collector.data.bats[BLKDNMetaInsertIDX].GetVectorByName(catalog.AttrCommitTs).Append(metaNode.CreatedAt)
   790  				collector.data.bats[BLKDNMetaInsertIDX].GetVectorByName(catalog.AttrRowID).Append(u64ToRowID(entry.ID))
   791  				collector.data.bats[BLKDNMetaInsertTxnIDX].GetVectorByName(SnapshotAttr_DBID).Append(entry.GetSegment().GetTable().GetDB().GetID())
   792  				collector.data.bats[BLKDNMetaInsertTxnIDX].GetVectorByName(SnapshotAttr_TID).Append(entry.GetSegment().GetTable().GetID())
   793  				collector.data.bats[BLKDNMetaInsertTxnIDX].GetVectorByName(SnapshotAttr_SegID).Append(entry.GetSegment().GetID())
   794  				metaNode.TxnMVCCNode.AppendTuple(collector.data.bats[BLKDNMetaInsertTxnIDX])
   795  				collector.data.bats[BLKDNMetaInsertTxnIDX].GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Append([]byte(metaNode.MetaLoc))
   796  				collector.data.bats[BLKDNMetaInsertTxnIDX].GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Append([]byte(metaNode.DeltaLoc))
   797  			}
   798  		} else {
   799  			if metaNode.HasDropCommitted() {
   800  				collector.data.bats[BLKMetaDeleteIDX].GetVectorByName(catalog.AttrRowID).Append(u64ToRowID(entry.ID))
   801  				collector.data.bats[BLKMetaDeleteIDX].GetVectorByName(catalog.AttrCommitTs).Append(metaNode.GetEnd())
   802  				collector.data.bats[BLKMetaDeleteTxnIDX].GetVectorByName(SnapshotAttr_DBID).Append(entry.GetSegment().GetTable().GetDB().GetID())
   803  				collector.data.bats[BLKMetaDeleteTxnIDX].GetVectorByName(SnapshotAttr_TID).Append(entry.GetSegment().GetTable().GetID())
   804  				collector.data.bats[BLKMetaDeleteTxnIDX].GetVectorByName(SnapshotAttr_SegID).Append(entry.GetSegment().GetID())
   805  				metaNode.TxnMVCCNode.AppendTuple(collector.data.bats[BLKMetaDeleteTxnIDX])
   806  				collector.data.bats[BLKMetaDeleteTxnIDX].GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Append([]byte(metaNode.MetaLoc))
   807  				collector.data.bats[BLKMetaDeleteTxnIDX].GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Append([]byte(metaNode.DeltaLoc))
   808  
   809  				collector.data.bats[BLKCNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_ID).Append(entry.ID)
   810  				collector.data.bats[BLKCNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_EntryState).Append(entry.IsAppendable())
   811  				collector.data.bats[BLKCNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Append([]byte(metaNode.MetaLoc))
   812  				collector.data.bats[BLKCNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Append([]byte(metaNode.DeltaLoc))
   813  				collector.data.bats[BLKCNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_CommitTs).Append(metaNode.GetEnd())
   814  				is_sorted := false
   815  				if !entry.IsAppendable() && entry.GetSchema().HasSortKey() {
   816  					is_sorted = true
   817  				}
   818  				collector.data.bats[BLKCNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_Sorted).Append(is_sorted)
   819  				collector.data.bats[BLKCNMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_SegmentID).Append(entry.GetSegment().ID)
   820  				collector.data.bats[BLKCNMetaInsertIDX].GetVectorByName(catalog.AttrCommitTs).Append(metaNode.CreatedAt)
   821  				collector.data.bats[BLKCNMetaInsertIDX].GetVectorByName(catalog.AttrRowID).Append(u64ToRowID(entry.ID))
   822  			} else {
   823  				collector.data.bats[BLKMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_ID).Append(entry.ID)
   824  				collector.data.bats[BLKMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_EntryState).Append(entry.IsAppendable())
   825  				collector.data.bats[BLKMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Append([]byte(metaNode.MetaLoc))
   826  				collector.data.bats[BLKMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Append([]byte(metaNode.DeltaLoc))
   827  				collector.data.bats[BLKMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_CommitTs).Append(metaNode.GetEnd())
   828  				is_sorted := false
   829  				if !entry.IsAppendable() && entry.GetSchema().HasSortKey() {
   830  					is_sorted = true
   831  				}
   832  				collector.data.bats[BLKMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_Sorted).Append(is_sorted)
   833  				collector.data.bats[BLKMetaInsertIDX].GetVectorByName(pkgcatalog.BlockMeta_SegmentID).Append(entry.GetSegment().ID)
   834  				collector.data.bats[BLKMetaInsertIDX].GetVectorByName(catalog.AttrCommitTs).Append(metaNode.CreatedAt)
   835  				collector.data.bats[BLKMetaInsertIDX].GetVectorByName(catalog.AttrRowID).Append(u64ToRowID(entry.ID))
   836  				collector.data.bats[BLKMetaInsertTxnIDX].GetVectorByName(SnapshotAttr_DBID).Append(entry.GetSegment().GetTable().GetDB().GetID())
   837  				collector.data.bats[BLKMetaInsertTxnIDX].GetVectorByName(SnapshotAttr_TID).Append(entry.GetSegment().GetTable().GetID())
   838  				collector.data.bats[BLKMetaInsertTxnIDX].GetVectorByName(SnapshotAttr_SegID).Append(entry.GetSegment().GetID())
   839  				metaNode.TxnMVCCNode.AppendTuple(collector.data.bats[BLKMetaInsertTxnIDX])
   840  				collector.data.bats[BLKMetaInsertTxnIDX].GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Append([]byte(metaNode.MetaLoc))
   841  				collector.data.bats[BLKMetaInsertTxnIDX].GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Append([]byte(metaNode.DeltaLoc))
   842  			}
   843  		}
   844  	}
   845  	insEnd := collector.data.bats[BLKMetaInsertIDX].GetVectorByName(catalog.AttrRowID).Length()
   846  	delEnd := collector.data.bats[BLKMetaDeleteIDX].GetVectorByName(catalog.AttrRowID).Length()
   847  	collector.data.UpdateBlkMeta(entry.GetSegment().GetTable().ID, int32(insStart), int32(insEnd), int32(delStart), int32(delEnd))
   848  	return nil
   849  }
   850  
   851  func (collector *GlobalCollector) VisitBlk(entry *catalog.BlockEntry) error {
   852  	if collector.isEntryDeletedBeforeThreshold(entry.MetaBaseEntry) {
   853  		return nil
   854  	}
   855  	if collector.isEntryDeletedBeforeThreshold(entry.GetSegment().MetaBaseEntry) {
   856  		return nil
   857  	}
   858  	if collector.isEntryDeletedBeforeThreshold(entry.GetSegment().GetTable().TableBaseEntry) {
   859  		return nil
   860  	}
   861  	if collector.isEntryDeletedBeforeThreshold(entry.GetSegment().GetTable().GetDB().DBBaseEntry) {
   862  		return nil
   863  	}
   864  	return collector.BaseCollector.VisitBlk(entry)
   865  }
   866  
   867  func (collector *BaseCollector) OrphanData() *CheckpointData {
   868  	data := collector.data
   869  	collector.data = nil
   870  	return data
   871  }
   872  
   873  func (collector *BaseCollector) Close() {
   874  	if collector.data != nil {
   875  		collector.data.Close()
   876  	}
   877  }