github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/logtail/snapshot.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  	"bytes"
    19  	"context"
    20  	"fmt"
    21  	catalog2 "github.com/matrixorigin/matrixone/pkg/catalog"
    22  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    25  	"github.com/matrixorigin/matrixone/pkg/fileservice"
    26  	"github.com/matrixorigin/matrixone/pkg/logutil"
    27  	"github.com/matrixorigin/matrixone/pkg/objectio"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/blockio"
    29  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    30  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    31  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    32  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase"
    33  	"sync"
    34  	"time"
    35  )
    36  
    37  const (
    38  	SnapshotTypeIdx types.Enum = iota
    39  	SnapshotTypeCluster
    40  	SnapshotTypeAccount
    41  )
    42  
    43  // mo_snapshot's schema
    44  const (
    45  	ColSnapshotId uint16 = iota
    46  	ColSName
    47  	ColTS
    48  	ColLevel
    49  	ColAccountName
    50  	ColDatabaseName
    51  	ColTableName
    52  	ColObjId
    53  )
    54  
    55  var (
    56  	objectInfoSchemaAttr = []string{
    57  		catalog.ObjectAttr_ObjectStats,
    58  		catalog.EntryNode_CreateAt,
    59  		catalog.EntryNode_DeleteAt,
    60  		catalog2.BlockMeta_DeltaLoc,
    61  		SnapshotAttr_TID,
    62  	}
    63  	objectInfoSchemaTypes = []types.Type{
    64  		types.New(types.T_varchar, types.MaxVarcharLen, 0),
    65  		types.New(types.T_TS, types.MaxVarcharLen, 0),
    66  		types.New(types.T_TS, types.MaxVarcharLen, 0),
    67  		types.New(types.T_varchar, 5000, 0),
    68  		types.New(types.T_uint64, 0, 0),
    69  	}
    70  
    71  	objectDeltaSchemaAttr = []string{
    72  		catalog2.BlockMeta_ID,
    73  		catalog2.BlockMeta_DeltaLoc,
    74  	}
    75  
    76  	objectDeltaSchemaTypes = []types.Type{
    77  		types.New(types.T_Blockid, 0, 0),
    78  		types.New(types.T_varchar, types.MaxVarcharLen, 0),
    79  	}
    80  
    81  	tableInfoSchemaAttr = []string{
    82  		catalog2.SystemColAttr_AccID,
    83  		catalog2.SystemRelAttr_DBID,
    84  		SnapshotAttr_TID,
    85  		catalog2.SystemRelAttr_CreateAt,
    86  		catalog.EntryNode_DeleteAt,
    87  	}
    88  
    89  	tableInfoSchemaTypes = []types.Type{
    90  		types.New(types.T_uint32, 0, 0),
    91  		types.New(types.T_uint64, 0, 0),
    92  		types.New(types.T_uint64, 0, 0),
    93  		types.New(types.T_TS, types.MaxVarcharLen, 0),
    94  		types.New(types.T_TS, types.MaxVarcharLen, 0),
    95  	}
    96  
    97  	snapshotSchemaTypes = []types.Type{
    98  		types.New(types.T_uint64, 0, 0),
    99  		types.New(types.T_varchar, types.MaxVarcharLen, 0),
   100  		types.New(types.T_int64, 0, 0),
   101  		types.New(types.T_enum, 0, 0),
   102  		types.New(types.T_varchar, types.MaxVarcharLen, 0),
   103  		types.New(types.T_varchar, types.MaxVarcharLen, 0),
   104  		types.New(types.T_varchar, types.MaxVarcharLen, 0),
   105  		types.New(types.T_uint64, 0, 0),
   106  	}
   107  )
   108  
   109  type objectInfo struct {
   110  	stats         objectio.ObjectStats
   111  	deltaLocation map[uint32]*objectio.Location
   112  	createAt      types.TS
   113  	deleteAt      types.TS
   114  }
   115  
   116  type SnapshotMeta struct {
   117  	sync.RWMutex
   118  	objects     map[objectio.Segmentid]*objectInfo
   119  	tid         uint64
   120  	tables      map[uint32]map[uint64]*TableInfo
   121  	acctIndexes map[uint64]*TableInfo
   122  }
   123  
   124  type TableInfo struct {
   125  	accID    uint32
   126  	dbID     uint64
   127  	tid      uint64
   128  	createAt types.TS
   129  	deleteAt types.TS
   130  }
   131  
   132  func NewSnapshotMeta() *SnapshotMeta {
   133  	return &SnapshotMeta{
   134  		objects:     make(map[objectio.Segmentid]*objectInfo),
   135  		tables:      make(map[uint32]map[uint64]*TableInfo),
   136  		acctIndexes: make(map[uint64]*TableInfo),
   137  	}
   138  }
   139  
   140  func (sm *SnapshotMeta) updateTableInfo(data *CheckpointData) {
   141  	insTable, _, _, _, delTableTxn := data.GetTblBatchs()
   142  	insAccIDs := vector.MustFixedCol[uint32](insTable.GetVectorByName(catalog2.SystemColAttr_AccID).GetDownstreamVector())
   143  	insTIDs := vector.MustFixedCol[uint64](insTable.GetVectorByName(catalog2.SystemRelAttr_ID).GetDownstreamVector())
   144  	insDBIDs := vector.MustFixedCol[uint64](insTable.GetVectorByName(catalog2.SystemRelAttr_DBID).GetDownstreamVector())
   145  	insCreateAts := vector.MustFixedCol[types.Timestamp](insTable.GetVectorByName(catalog2.SystemRelAttr_CreateAt).GetDownstreamVector())
   146  	for i := 0; i < insTable.Length(); i++ {
   147  		tid := insTIDs[i]
   148  		if sm.tid == 0 {
   149  			tableName := string(insTable.GetVectorByName(catalog2.SystemRelAttr_Name).Get(i).([]byte))
   150  			if tableName == "mo_snapshots" {
   151  				logutil.Infof("mo_snapshots: %d", tid)
   152  				sm.SetTid(tid)
   153  			}
   154  		}
   155  		accID := insAccIDs[i]
   156  		if sm.tables[accID] == nil {
   157  			sm.tables[accID] = make(map[uint64]*TableInfo)
   158  		}
   159  		dbid := insDBIDs[i]
   160  		create := insCreateAts[i]
   161  		createAt := types.BuildTS(create.Unix(), 0)
   162  		if sm.tables[accID][tid] != nil {
   163  			continue
   164  		}
   165  		table := &TableInfo{
   166  			accID:    accID,
   167  			dbID:     dbid,
   168  			tid:      tid,
   169  			createAt: createAt,
   170  		}
   171  		sm.tables[accID][tid] = table
   172  
   173  		if sm.acctIndexes[tid] == nil {
   174  			sm.acctIndexes[tid] = table
   175  		}
   176  	}
   177  
   178  	delTableIDs := vector.MustFixedCol[uint64](delTableTxn.GetVectorByName(SnapshotAttr_TID).GetDownstreamVector())
   179  	delDropAts := vector.MustFixedCol[types.TS](delTableTxn.GetVectorByName(txnbase.SnapshotAttr_CommitTS).GetDownstreamVector())
   180  	for i := 0; i < delTableTxn.Length(); i++ {
   181  		tid := delTableIDs[i]
   182  		dropAt := delDropAts[i]
   183  		if sm.acctIndexes[tid] == nil {
   184  			//In the upgraded cluster, because the inc checkpoint is consumed halfway,
   185  			// there may be no record of the create table entry, only the delete entry
   186  			continue
   187  		}
   188  		table := sm.acctIndexes[tid]
   189  		table.deleteAt = dropAt
   190  		sm.acctIndexes[tid] = table
   191  		sm.tables[table.accID][tid] = table
   192  	}
   193  }
   194  
   195  func (sm *SnapshotMeta) Update(data *CheckpointData) *SnapshotMeta {
   196  	sm.Lock()
   197  	defer sm.Unlock()
   198  
   199  	sm.updateTableInfo(data)
   200  	if sm.tid == 0 {
   201  		return sm
   202  	}
   203  	ins := data.GetObjectBatchs()
   204  	insDeleteTSs := vector.MustFixedCol[types.TS](ins.GetVectorByName(catalog.EntryNode_DeleteAt).GetDownstreamVector())
   205  	insCreateTSs := vector.MustFixedCol[types.TS](ins.GetVectorByName(catalog.EntryNode_CreateAt).GetDownstreamVector())
   206  	insTableIDs := vector.MustFixedCol[uint64](ins.GetVectorByName(SnapshotAttr_TID).GetDownstreamVector())
   207  	for i := 0; i < ins.Length(); i++ {
   208  		table := insTableIDs[i]
   209  		if table != sm.tid {
   210  			continue
   211  		}
   212  		var objectStats objectio.ObjectStats
   213  		buf := ins.GetVectorByName(catalog.ObjectAttr_ObjectStats).Get(i).([]byte)
   214  		objectStats.UnMarshal(buf)
   215  		deleteTS := insDeleteTSs[i]
   216  		createTS := insCreateTSs[i]
   217  		if sm.objects[objectStats.ObjectName().SegmentId()] == nil {
   218  			if !deleteTS.IsEmpty() {
   219  				continue
   220  			}
   221  			sm.objects[objectStats.ObjectName().SegmentId()] = &objectInfo{
   222  				stats:    objectStats,
   223  				createAt: createTS,
   224  			}
   225  			continue
   226  		}
   227  		if deleteTS.IsEmpty() {
   228  			panic(any("deleteTS is empty"))
   229  		}
   230  		delete(sm.objects, objectStats.ObjectName().SegmentId())
   231  	}
   232  	del, _, _, _ := data.GetBlkBatchs()
   233  	delBlockIDs := vector.MustFixedCol[types.Blockid](del.GetVectorByName(catalog2.BlockMeta_ID).GetDownstreamVector())
   234  	for i := 0; i < del.Length(); i++ {
   235  		blockID := delBlockIDs[i]
   236  		deltaLoc := objectio.Location(del.GetVectorByName(catalog2.BlockMeta_DeltaLoc).Get(i).([]byte))
   237  		if sm.objects[*blockID.Segment()] != nil {
   238  			if sm.objects[*blockID.Segment()].deltaLocation == nil {
   239  				sm.objects[*blockID.Segment()].deltaLocation = make(map[uint32]*objectio.Location)
   240  			}
   241  			sm.objects[*blockID.Segment()].deltaLocation[uint32(blockID.Sequence())] = &deltaLoc
   242  		}
   243  	}
   244  	return nil
   245  }
   246  
   247  func (sm *SnapshotMeta) GetSnapshot(ctx context.Context, fs fileservice.FileService, mp *mpool.MPool) (map[uint32]containers.Vector, error) {
   248  	sm.RLock()
   249  	objects := sm.objects
   250  	sm.RUnlock()
   251  	snapshotList := make(map[uint32]containers.Vector)
   252  	idxes := []uint16{ColTS, ColLevel, ColObjId}
   253  	colTypes := []types.Type{
   254  		snapshotSchemaTypes[ColTS],
   255  		snapshotSchemaTypes[ColLevel],
   256  		snapshotSchemaTypes[ColObjId],
   257  	}
   258  	for _, object := range objects {
   259  		location := object.stats.ObjectLocation()
   260  		name := object.stats.ObjectName()
   261  		for i := uint32(0); i < object.stats.BlkCnt(); i++ {
   262  			loc := objectio.BuildLocation(name, location.Extent(), 0, uint16(i))
   263  			blk := objectio.BlockInfo{
   264  				BlockID:   *objectio.BuildObjectBlockid(name, uint16(i)),
   265  				SegmentID: name.SegmentId(),
   266  				MetaLoc:   objectio.ObjectLocation(loc),
   267  			}
   268  			if object.deltaLocation[i] != nil {
   269  				logutil.Infof("deltaLoc: %v, id is %d", object.deltaLocation[i].String(), i)
   270  				blk.DeltaLoc = objectio.ObjectLocation(*object.deltaLocation[i])
   271  			}
   272  			checkpointTS := types.BuildTS(time.Now().UTC().UnixNano(), 0)
   273  			bat, err := blockio.BlockRead(ctx, &blk, nil, idxes, colTypes, checkpointTS.ToTimestamp(),
   274  				nil, nil, nil, fs, mp, nil, fileservice.Policy(0))
   275  			if err != nil {
   276  				return nil, err
   277  			}
   278  			defer bat.Clean(mp)
   279  			tsList := vector.MustFixedCol[int64](bat.Vecs[0])
   280  			typeList := vector.MustFixedCol[types.Enum](bat.Vecs[1])
   281  			acctList := vector.MustFixedCol[uint64](bat.Vecs[2])
   282  			for r := 0; r < bat.Vecs[0].Length(); r++ {
   283  				ts := tsList[r]
   284  				snapTs := types.BuildTS(ts, 0)
   285  				acct := acctList[r]
   286  				snapshotType := typeList[r]
   287  				if snapshotType == SnapshotTypeCluster {
   288  					for account := range sm.tables {
   289  						if snapshotList[account] == nil {
   290  							snapshotList[account] = containers.MakeVector(types.T_TS.ToType(), mp)
   291  						}
   292  						err = vector.AppendFixed[types.TS](snapshotList[account].GetDownstreamVector(), snapTs, false, mp)
   293  						if err != nil {
   294  							return nil, err
   295  						}
   296  					}
   297  					continue
   298  				}
   299  				id := uint32(acct)
   300  				if snapshotList[id] == nil {
   301  					snapshotList[id] = containers.MakeVector(types.T_TS.ToType(), mp)
   302  				}
   303  				logutil.Infof("GetSnapshot: id %d, ts %v", id, snapTs.ToString())
   304  				err = vector.AppendFixed[types.TS](snapshotList[id].GetDownstreamVector(), snapTs, false, mp)
   305  				if err != nil {
   306  					return nil, err
   307  				}
   308  			}
   309  		}
   310  	}
   311  	for i := range snapshotList {
   312  		snapshotList[i].GetDownstreamVector().InplaceSort()
   313  	}
   314  	return snapshotList, nil
   315  }
   316  
   317  func (sm *SnapshotMeta) SetTid(tid uint64) {
   318  	sm.tid = tid
   319  }
   320  
   321  func (sm *SnapshotMeta) SaveMeta(name string, fs fileservice.FileService) (uint32, error) {
   322  	if len(sm.objects) == 0 {
   323  		return 0, nil
   324  	}
   325  	bat := containers.NewBatch()
   326  	for i, attr := range objectInfoSchemaAttr {
   327  		bat.AddVector(attr, containers.MakeVector(objectInfoSchemaTypes[i], common.DebugAllocator))
   328  	}
   329  	deltaBat := containers.NewBatch()
   330  	for i, attr := range objectDeltaSchemaAttr {
   331  		deltaBat.AddVector(attr, containers.MakeVector(objectDeltaSchemaTypes[i], common.DebugAllocator))
   332  	}
   333  	for _, entry := range sm.objects {
   334  		vector.AppendBytes(
   335  			bat.GetVectorByName(catalog.ObjectAttr_ObjectStats).GetDownstreamVector(),
   336  			entry.stats[:], false, common.DebugAllocator)
   337  		vector.AppendFixed[types.TS](
   338  			bat.GetVectorByName(catalog.EntryNode_CreateAt).GetDownstreamVector(),
   339  			entry.createAt, false, common.DebugAllocator)
   340  		vector.AppendFixed[types.TS](
   341  			bat.GetVectorByName(catalog.EntryNode_DeleteAt).GetDownstreamVector(),
   342  			entry.deleteAt, false, common.DebugAllocator)
   343  		for id, delta := range entry.deltaLocation {
   344  			blockID := objectio.BuildObjectBlockid(entry.stats.ObjectName(), uint16(id))
   345  			vector.AppendFixed[types.Blockid](deltaBat.GetVectorByName(catalog2.BlockMeta_ID).GetDownstreamVector(),
   346  				*blockID, false, common.DebugAllocator)
   347  			vector.AppendBytes(deltaBat.GetVectorByName(catalog2.BlockMeta_DeltaLoc).GetDownstreamVector(),
   348  				[]byte(*delta), false, common.DebugAllocator)
   349  		}
   350  		vector.AppendFixed[uint64](
   351  			bat.GetVectorByName(SnapshotAttr_TID).GetDownstreamVector(),
   352  			sm.tid, false, common.DebugAllocator)
   353  	}
   354  	defer bat.Close()
   355  	defer deltaBat.Close()
   356  	writer, err := objectio.NewObjectWriterSpecial(objectio.WriterGC, name, fs)
   357  	if err != nil {
   358  		return 0, err
   359  	}
   360  	if _, err = writer.WriteWithoutSeqnum(containers.ToCNBatch(bat)); err != nil {
   361  		return 0, err
   362  	}
   363  	if deltaBat.Length() > 0 {
   364  		logutil.Infof("deltaBat length is %d", deltaBat.Length())
   365  		if _, err = writer.WriteWithoutSeqnum(containers.ToCNBatch(deltaBat)); err != nil {
   366  			return 0, err
   367  		}
   368  	}
   369  
   370  	_, err = writer.WriteEnd(context.Background())
   371  	if err != nil {
   372  		return 0, err
   373  	}
   374  	size := writer.GetObjectStats()[0].OriginSize()
   375  	return size, err
   376  }
   377  
   378  func (sm *SnapshotMeta) SaveTableInfo(name string, fs fileservice.FileService) (uint32, error) {
   379  	if len(sm.tables) == 0 {
   380  		return 0, nil
   381  	}
   382  	bat := containers.NewBatch()
   383  	for i, attr := range tableInfoSchemaAttr {
   384  		bat.AddVector(attr, containers.MakeVector(tableInfoSchemaTypes[i], common.DebugAllocator))
   385  	}
   386  	for _, entry := range sm.tables {
   387  		for _, table := range entry {
   388  			vector.AppendFixed[uint32](
   389  				bat.GetVectorByName(catalog2.SystemColAttr_AccID).GetDownstreamVector(),
   390  				table.accID, false, common.DebugAllocator)
   391  			vector.AppendFixed[uint64](
   392  				bat.GetVectorByName(catalog2.SystemRelAttr_DBID).GetDownstreamVector(),
   393  				table.dbID, false, common.DebugAllocator)
   394  			vector.AppendFixed[uint64](
   395  				bat.GetVectorByName(SnapshotAttr_TID).GetDownstreamVector(),
   396  				table.tid, false, common.DebugAllocator)
   397  			vector.AppendFixed[types.TS](
   398  				bat.GetVectorByName(catalog2.SystemRelAttr_CreateAt).GetDownstreamVector(),
   399  				table.createAt, false, common.DebugAllocator)
   400  			vector.AppendFixed[types.TS](
   401  				bat.GetVectorByName(catalog.EntryNode_DeleteAt).GetDownstreamVector(),
   402  				table.deleteAt, false, common.DebugAllocator)
   403  		}
   404  	}
   405  	defer bat.Close()
   406  	writer, err := objectio.NewObjectWriterSpecial(objectio.WriterGC, name, fs)
   407  	if err != nil {
   408  		return 0, err
   409  	}
   410  	if _, err = writer.WriteWithoutSeqnum(containers.ToCNBatch(bat)); err != nil {
   411  		return 0, err
   412  	}
   413  
   414  	_, err = writer.WriteEnd(context.Background())
   415  	if err != nil {
   416  		return 0, err
   417  	}
   418  	size := writer.GetObjectStats()[0].OriginSize()
   419  	return size, err
   420  }
   421  
   422  func (sm *SnapshotMeta) RebuildTableInfo(ins *containers.Batch) {
   423  	insTIDs := vector.MustFixedCol[uint64](ins.GetVectorByName(catalog.SnapshotAttr_TID).GetDownstreamVector())
   424  	insAccIDs := vector.MustFixedCol[uint32](ins.GetVectorByName(catalog2.SystemColAttr_AccID).GetDownstreamVector())
   425  	insDBIDs := vector.MustFixedCol[uint64](ins.GetVectorByName(catalog2.SystemRelAttr_DBID).GetDownstreamVector())
   426  	insCreateTSs := vector.MustFixedCol[types.TS](ins.GetVectorByName(catalog2.SystemRelAttr_CreateAt).GetDownstreamVector())
   427  	insDeleteTSs := vector.MustFixedCol[types.TS](ins.GetVectorByName(catalog.EntryNode_DeleteAt).GetDownstreamVector())
   428  	for i := 0; i < ins.Length(); i++ {
   429  		tid := insTIDs[i]
   430  		dbid := insDBIDs[i]
   431  		accid := insAccIDs[i]
   432  		createTS := insCreateTSs[i]
   433  		deleteTS := insDeleteTSs[i]
   434  		if sm.tables[accid] == nil {
   435  			sm.tables[accid] = make(map[uint64]*TableInfo)
   436  		}
   437  		table := &TableInfo{
   438  			tid:      tid,
   439  			dbID:     dbid,
   440  			accID:    accid,
   441  			createAt: createTS,
   442  			deleteAt: deleteTS,
   443  		}
   444  		sm.tables[accid][tid] = table
   445  		sm.acctIndexes[tid] = table
   446  	}
   447  }
   448  
   449  func (sm *SnapshotMeta) Rebuild(ins *containers.Batch) {
   450  	sm.Lock()
   451  	defer sm.Unlock()
   452  	insCreateTSs := vector.MustFixedCol[types.TS](ins.GetVectorByName(catalog.EntryNode_CreateAt).GetDownstreamVector())
   453  	for i := 0; i < ins.Length(); i++ {
   454  		var objectStats objectio.ObjectStats
   455  		buf := ins.GetVectorByName(catalog.ObjectAttr_ObjectStats).Get(i).([]byte)
   456  		objectStats.UnMarshal(buf)
   457  		createTS := insCreateTSs[i]
   458  		if sm.tid == 0 {
   459  			tid := ins.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64)
   460  			if tid == 0 {
   461  				panic("tid is 0")
   462  			}
   463  			sm.SetTid(tid)
   464  		}
   465  		if sm.objects[objectStats.ObjectName().SegmentId()] == nil {
   466  			sm.objects[objectStats.ObjectName().SegmentId()] = &objectInfo{
   467  				stats:    objectStats,
   468  				createAt: createTS,
   469  			}
   470  			continue
   471  		}
   472  	}
   473  }
   474  
   475  func (sm *SnapshotMeta) RebuildDelta(ins *containers.Batch) {
   476  	sm.Lock()
   477  	defer sm.Unlock()
   478  	insBlockIDs := vector.MustFixedCol[types.Blockid](ins.GetVectorByName(catalog2.BlockMeta_ID).GetDownstreamVector())
   479  	for i := 0; i < ins.Length(); i++ {
   480  		blockID := insBlockIDs[i]
   481  		deltaLoc := objectio.Location(ins.GetVectorByName(catalog2.BlockMeta_DeltaLoc).Get(i).([]byte))
   482  		if sm.objects[*blockID.Segment()] != nil {
   483  			if sm.objects[*blockID.Segment()].deltaLocation == nil {
   484  				sm.objects[*blockID.Segment()].deltaLocation = make(map[uint32]*objectio.Location)
   485  			}
   486  			logutil.Infof("RebuildDelta: %v, loc is %v", blockID.String(), deltaLoc.String())
   487  			sm.objects[*blockID.Segment()].deltaLocation[uint32(blockID.Sequence())] = &deltaLoc
   488  		} else {
   489  			panic("blockID not found")
   490  		}
   491  	}
   492  }
   493  
   494  func (sm *SnapshotMeta) ReadMeta(ctx context.Context, name string, fs fileservice.FileService) error {
   495  	reader, err := blockio.NewFileReaderNoCache(fs, name)
   496  	if err != nil {
   497  		return err
   498  	}
   499  	bs, err := reader.LoadAllBlocks(ctx, common.DebugAllocator)
   500  	if err != nil {
   501  		return err
   502  	}
   503  	idxes := make([]uint16, len(objectInfoSchemaAttr))
   504  	for i := range objectInfoSchemaAttr {
   505  		idxes[i] = uint16(i)
   506  	}
   507  	mobat, release, err := reader.LoadColumns(ctx, idxes, nil, bs[0].GetID(), common.DebugAllocator)
   508  	if err != nil {
   509  		return err
   510  	}
   511  	defer release()
   512  	bat := containers.NewBatch()
   513  	defer bat.Close()
   514  	for i := range objectInfoSchemaAttr {
   515  		pkgVec := mobat.Vecs[i]
   516  		var vec containers.Vector
   517  		if pkgVec.Length() == 0 {
   518  			vec = containers.MakeVector(objectInfoSchemaTypes[i], common.DebugAllocator)
   519  		} else {
   520  			vec = containers.ToTNVector(pkgVec, common.DebugAllocator)
   521  		}
   522  		bat.AddVector(objectInfoSchemaAttr[i], vec)
   523  	}
   524  	sm.Rebuild(bat)
   525  
   526  	if len(bs) == 1 {
   527  		return nil
   528  	}
   529  
   530  	idxes = make([]uint16, len(objectDeltaSchemaAttr))
   531  	for i := range objectDeltaSchemaAttr {
   532  		idxes[i] = uint16(i)
   533  	}
   534  	moDeltaBat, releaseDelta, err := reader.LoadColumns(ctx, idxes, nil, bs[1].GetID(), common.DebugAllocator)
   535  	if err != nil {
   536  		return err
   537  	}
   538  	defer releaseDelta()
   539  	deltaBat := containers.NewBatch()
   540  	defer deltaBat.Close()
   541  	for i := range objectDeltaSchemaAttr {
   542  		pkgVec := moDeltaBat.Vecs[i]
   543  		var vec containers.Vector
   544  		if pkgVec.Length() == 0 {
   545  			vec = containers.MakeVector(objectDeltaSchemaTypes[i], common.DebugAllocator)
   546  		} else {
   547  			vec = containers.ToTNVector(pkgVec, common.DebugAllocator)
   548  		}
   549  		deltaBat.AddVector(objectDeltaSchemaAttr[i], vec)
   550  	}
   551  	sm.RebuildDelta(deltaBat)
   552  	return nil
   553  }
   554  
   555  func (sm *SnapshotMeta) ReadTableInfo(ctx context.Context, name string, fs fileservice.FileService) error {
   556  	reader, err := blockio.NewFileReaderNoCache(fs, name)
   557  	if err != nil {
   558  		return err
   559  	}
   560  	bs, err := reader.LoadAllBlocks(ctx, common.DebugAllocator)
   561  	if err != nil {
   562  		return err
   563  	}
   564  	idxes := make([]uint16, len(tableInfoSchemaAttr))
   565  	for i := range tableInfoSchemaAttr {
   566  		idxes[i] = uint16(i)
   567  	}
   568  	mobat, release, err := reader.LoadColumns(ctx, idxes, nil, bs[0].GetID(), common.DebugAllocator)
   569  	if err != nil {
   570  		return err
   571  	}
   572  	defer release()
   573  	bat := containers.NewBatch()
   574  	defer bat.Close()
   575  	for i := range tableInfoSchemaAttr {
   576  		pkgVec := mobat.Vecs[i]
   577  		var vec containers.Vector
   578  		if pkgVec.Length() == 0 {
   579  			vec = containers.MakeVector(objectInfoSchemaTypes[i], common.DebugAllocator)
   580  		} else {
   581  			vec = containers.ToTNVector(pkgVec, common.DebugAllocator)
   582  		}
   583  		bat.AddVector(tableInfoSchemaAttr[i], vec)
   584  	}
   585  	sm.RebuildTableInfo(bat)
   586  	return nil
   587  }
   588  
   589  func (sm *SnapshotMeta) InitTableInfo(data *CheckpointData) {
   590  	sm.Lock()
   591  	defer sm.Unlock()
   592  	sm.updateTableInfo(data)
   593  }
   594  
   595  func (sm *SnapshotMeta) TableInfoString() string {
   596  	sm.RLock()
   597  	defer sm.RUnlock()
   598  	var buf bytes.Buffer
   599  	for accID, tables := range sm.tables {
   600  		buf.WriteString(fmt.Sprintf("accountID: %d\n", accID))
   601  		for tid, table := range tables {
   602  			buf.WriteString(fmt.Sprintf("tableID: %d, create: %s, deleteAt: %s\n",
   603  				tid, table.createAt.ToString(), table.deleteAt.ToString()))
   604  		}
   605  	}
   606  	return buf.String()
   607  }
   608  
   609  func (sm *SnapshotMeta) GetSnapshotList(SnapshotList map[uint32][]types.TS, tid uint64) []types.TS {
   610  	sm.RLock()
   611  	defer sm.RUnlock()
   612  	if sm.acctIndexes[tid] == nil {
   613  		return nil
   614  	}
   615  	accID := sm.acctIndexes[tid].accID
   616  	return SnapshotList[accID]
   617  }
   618  
   619  func (sm *SnapshotMeta) MergeTableInfo(SnapshotList map[uint32][]types.TS) error {
   620  	sm.Lock()
   621  	defer sm.Unlock()
   622  	if len(sm.tables) == 0 {
   623  		return nil
   624  	}
   625  	for accID, tables := range sm.tables {
   626  		if SnapshotList[accID] == nil {
   627  			for _, table := range tables {
   628  				if !table.deleteAt.IsEmpty() {
   629  					delete(sm.tables[accID], table.tid)
   630  					delete(sm.acctIndexes, table.tid)
   631  				}
   632  			}
   633  			continue
   634  		}
   635  		for _, table := range tables {
   636  			if !table.deleteAt.IsEmpty() && !isSnapshotRefers(table, SnapshotList[accID]) {
   637  				delete(sm.tables[accID], table.tid)
   638  				delete(sm.acctIndexes, table.tid)
   639  			}
   640  		}
   641  	}
   642  	return nil
   643  }
   644  
   645  func (sm *SnapshotMeta) String() string {
   646  	sm.RLock()
   647  	defer sm.RUnlock()
   648  	return fmt.Sprintf("account count: %d, table count: %d, object count: %d",
   649  		len(sm.tables), len(sm.acctIndexes), len(sm.objects))
   650  }
   651  
   652  func isSnapshotRefers(table *TableInfo, snapVec []types.TS) bool {
   653  	if len(snapVec) == 0 {
   654  		return false
   655  	}
   656  	left, right := 0, len(snapVec)-1
   657  	for left <= right {
   658  		mid := left + (right-left)/2
   659  		snapTS := snapVec[mid]
   660  		if snapTS.GreaterEq(&table.createAt) && snapTS.Less(&table.deleteAt) {
   661  			logutil.Infof("isSnapshotRefers: %s, create %v, drop %v",
   662  				snapTS.ToString(), table.createAt.ToString(), table.deleteAt.ToString())
   663  			return true
   664  		} else if snapTS.Less(&table.createAt) {
   665  			left = mid + 1
   666  		} else {
   667  			right = mid - 1
   668  		}
   669  	}
   670  	return false
   671  }
   672  
   673  func CloseSnapshotList(snapshots map[uint32]containers.Vector) {
   674  	for _, snapshot := range snapshots {
   675  		snapshot.Close()
   676  	}
   677  }