github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/db/gc/table.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 gc
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"fmt"
    21  	pkgcatalog "github.com/matrixorigin/matrixone/pkg/catalog"
    22  	"github.com/matrixorigin/matrixone/pkg/container/types"
    23  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    24  	"github.com/matrixorigin/matrixone/pkg/objectio"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/dataio/blockio"
    29  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logtail"
    30  	"sync"
    31  )
    32  
    33  // GCTable is a data structure in memory after consuming checkpoint
    34  type GCTable struct {
    35  	sync.Mutex
    36  	dbs map[uint32]*dropDB
    37  }
    38  
    39  func NewGCTable() *GCTable {
    40  	table := GCTable{
    41  		dbs: make(map[uint32]*dropDB),
    42  	}
    43  	return &table
    44  }
    45  
    46  func (t *GCTable) addBlock(id common.ID, name string) {
    47  	t.Lock()
    48  	defer t.Unlock()
    49  	db := t.dbs[id.PartID]
    50  	if db == nil {
    51  		db = NewDropDB(id.PartID)
    52  	}
    53  	db.addBlock(id, name)
    54  	t.dbs[id.PartID] = db
    55  }
    56  
    57  func (t *GCTable) deleteBlock(id common.ID, name string) {
    58  	t.Lock()
    59  	defer t.Unlock()
    60  	db := t.dbs[id.PartID]
    61  	if db == nil {
    62  		db = NewDropDB(id.PartID)
    63  	}
    64  	db.deleteBlock(id, name)
    65  	t.dbs[id.PartID] = db
    66  }
    67  
    68  // Merge can merge two GCTables
    69  func (t *GCTable) Merge(GCTable *GCTable) {
    70  	for did, entry := range GCTable.dbs {
    71  		db := t.dbs[did]
    72  		if db == nil {
    73  			db = NewDropDB(did)
    74  		}
    75  		db.merge(entry)
    76  		if !db.drop {
    77  			db.drop = entry.drop
    78  		}
    79  		t.dbs[did] = db
    80  	}
    81  }
    82  
    83  // SoftGC is to remove objectentry that can be deleted from GCTable
    84  func (t *GCTable) SoftGC() []string {
    85  	gc := make([]string, 0)
    86  	for id, db := range t.dbs {
    87  		if t.dbs[id] == nil {
    88  			panic(any("error"))
    89  		}
    90  		objects := db.softGC()
    91  		gc = append(gc, objects...)
    92  	}
    93  	return gc
    94  }
    95  
    96  func (t *GCTable) dropDB(id common.ID) {
    97  	t.Lock()
    98  	defer t.Unlock()
    99  	db := t.dbs[id.PartID]
   100  	if db == nil {
   101  		db = NewDropDB(id.PartID)
   102  	}
   103  	db.drop = true
   104  	t.dbs[id.PartID] = db
   105  }
   106  
   107  func (t *GCTable) dropTable(id common.ID) {
   108  	t.Lock()
   109  	defer t.Unlock()
   110  	db := t.dbs[id.PartID]
   111  	if db == nil {
   112  		db = NewDropDB(id.PartID)
   113  	}
   114  	db.DropTable(id)
   115  	t.dbs[id.PartID] = db
   116  }
   117  
   118  func (t *GCTable) UpdateTable(data *logtail.CheckpointData) {
   119  	ins, insTxn, del, delTxn := data.GetBlkBatchs()
   120  	for i := 0; i < ins.Length(); i++ {
   121  		dbid := insTxn.GetVectorByName(catalog.SnapshotAttr_DBID).Get(i).(uint64)
   122  		tid := insTxn.GetVectorByName(catalog.SnapshotAttr_TID).Get(i).(uint64)
   123  		sid := insTxn.GetVectorByName(catalog.SnapshotAttr_SegID).Get(i).(uint64)
   124  		blkID := ins.GetVectorByName(pkgcatalog.BlockMeta_ID).Get(i).(uint64)
   125  		metaLoc := string(ins.GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Get(i).([]byte))
   126  		id := common.ID{
   127  			SegmentID: sid,
   128  			TableID:   tid,
   129  			BlockID:   blkID,
   130  			PartID:    uint32(dbid),
   131  		}
   132  		name, _, _ := blockio.DecodeMetaLoc(metaLoc)
   133  		t.addBlock(id, name)
   134  	}
   135  	for i := 0; i < del.Length(); i++ {
   136  		dbid := delTxn.GetVectorByName(catalog.SnapshotAttr_DBID).Get(i).(uint64)
   137  		tid := delTxn.GetVectorByName(catalog.SnapshotAttr_TID).Get(i).(uint64)
   138  		sid := delTxn.GetVectorByName(catalog.SnapshotAttr_SegID).Get(i).(uint64)
   139  		blkID := del.GetVectorByName(catalog.AttrRowID).Get(i).(types.Rowid)
   140  		metaLoc := string(delTxn.GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Get(i).([]byte))
   141  
   142  		id := common.ID{
   143  			SegmentID: sid,
   144  			TableID:   tid,
   145  			BlockID:   rowIDToU64(blkID),
   146  			PartID:    uint32(dbid),
   147  		}
   148  		name, _, _ := blockio.DecodeMetaLoc(metaLoc)
   149  		t.deleteBlock(id, name)
   150  	}
   151  	_, _, _, del, delTxn = data.GetTblBatchs()
   152  	for i := 0; i < del.Length(); i++ {
   153  		dbid := delTxn.GetVectorByName(catalog.SnapshotAttr_DBID).Get(i).(uint64)
   154  		tid := delTxn.GetVectorByName(catalog.SnapshotAttr_TID).Get(i).(uint64)
   155  		id := common.ID{
   156  			TableID: tid,
   157  			PartID:  uint32(dbid),
   158  		}
   159  		t.dropTable(id)
   160  	}
   161  
   162  	_, _, del, delTxn = data.GetDBBatchs()
   163  	for i := 0; i < del.Length(); i++ {
   164  		dbid := delTxn.GetVectorByName(catalog.SnapshotAttr_DBID).Get(i).(uint64)
   165  		id := common.ID{
   166  			PartID: uint32(dbid),
   167  		}
   168  		t.dropDB(id)
   169  	}
   170  }
   171  
   172  func rowIDToU64(rowID types.Rowid) uint64 {
   173  	return types.DecodeUint64(rowID[:8])
   174  }
   175  
   176  func (t *GCTable) rebuildTable(bats []*containers.Batch) {
   177  	files := make(map[string]bool)
   178  	for i := 0; i < bats[DeleteFile].Length(); i++ {
   179  		name := string(bats[DeleteFile].GetVectorByName(GCAttrObjectName).Get(i).([]byte))
   180  		files[name] = true
   181  	}
   182  	for i := 0; i < bats[CreateBlock].Length(); i++ {
   183  		dbid := bats[CreateBlock].GetVectorByName(GCAttrDBId).Get(i).(uint32)
   184  		tid := bats[CreateBlock].GetVectorByName(GCAttrTableId).Get(i).(uint64)
   185  		sid := bats[CreateBlock].GetVectorByName(GCAttrSegmentId).Get(i).(uint64)
   186  		blkID := bats[CreateBlock].GetVectorByName(GCAttrBlockId).Get(i).(uint64)
   187  		name := string(bats[CreateBlock].GetVectorByName(GCAttrObjectName).Get(i).([]byte))
   188  		if files[name] {
   189  			continue
   190  		}
   191  		id := common.ID{
   192  			SegmentID: sid,
   193  			TableID:   tid,
   194  			BlockID:   blkID,
   195  			PartID:    uint32(dbid),
   196  		}
   197  		t.addBlock(id, name)
   198  	}
   199  	for i := 0; i < bats[DeleteBlock].Length(); i++ {
   200  		dbid := bats[DeleteBlock].GetVectorByName(GCAttrDBId).Get(i).(uint32)
   201  		tid := bats[DeleteBlock].GetVectorByName(GCAttrTableId).Get(i).(uint64)
   202  		sid := bats[DeleteBlock].GetVectorByName(GCAttrSegmentId).Get(i).(uint64)
   203  		blkID := bats[DeleteBlock].GetVectorByName(GCAttrBlockId).Get(i).(uint64)
   204  		name := string(bats[DeleteBlock].GetVectorByName(GCAttrObjectName).Get(i).([]byte))
   205  		if files[name] {
   206  			continue
   207  		}
   208  		id := common.ID{
   209  			SegmentID: sid,
   210  			TableID:   tid,
   211  			BlockID:   blkID,
   212  			PartID:    dbid,
   213  		}
   214  		t.deleteBlock(id, name)
   215  	}
   216  	for i := 0; i < bats[DropTable].Length(); i++ {
   217  		dbid := bats[DropTable].GetVectorByName(GCAttrDBId).Get(i).(uint32)
   218  		tid := bats[DropTable].GetVectorByName(GCAttrTableId).Get(i).(uint64)
   219  		id := common.ID{
   220  			TableID: tid,
   221  			PartID:  dbid,
   222  		}
   223  		t.dropTable(id)
   224  	}
   225  	for i := 0; i < bats[DropDB].Length(); i++ {
   226  		dbid := bats[DropDB].GetVectorByName(GCAttrDBId).Get(i).(uint32)
   227  		id := common.ID{
   228  			PartID: dbid,
   229  		}
   230  		t.dropDB(id)
   231  	}
   232  }
   233  
   234  func (t *GCTable) makeBatchWithGCTable() []*containers.Batch {
   235  	bats := make([]*containers.Batch, 5)
   236  	bats[CreateBlock] = containers.NewBatch()
   237  	bats[DeleteBlock] = containers.NewBatch()
   238  	bats[DropTable] = containers.NewBatch()
   239  	bats[DropDB] = containers.NewBatch()
   240  	bats[DeleteFile] = containers.NewBatch()
   241  	return bats
   242  }
   243  
   244  func (t *GCTable) closeBatch(bs []*containers.Batch) {
   245  	for i := range bs {
   246  		bs[i].Close()
   247  	}
   248  }
   249  
   250  // collectData collects data from memory that can be written to s3
   251  func (t *GCTable) collectData(files []string) []*containers.Batch {
   252  	bats := t.makeBatchWithGCTable()
   253  	for i, attr := range BlockSchemaAttr {
   254  		bats[CreateBlock].AddVector(attr, containers.MakeVector(BlockSchemaTypes[i], false))
   255  		bats[DeleteBlock].AddVector(attr, containers.MakeVector(BlockSchemaTypes[i], false))
   256  	}
   257  	for i, attr := range DropTableSchemaAttr {
   258  		bats[DropTable].AddVector(attr, containers.MakeVector(DropTableSchemaTypes[i], false))
   259  	}
   260  	for i, attr := range DropDBSchemaAtt {
   261  		bats[DropDB].AddVector(attr, containers.MakeVector(DropDBSchemaTypes[i], false))
   262  	}
   263  	for i, attr := range DeleteFileSchemaAtt {
   264  		bats[DeleteFile].AddVector(attr, containers.MakeVector(DeleteFileSchemaTypes[i], false))
   265  	}
   266  	for did, entry := range t.dbs {
   267  		if entry.drop {
   268  			bats[DropDB].GetVectorByName(GCAttrDBId).Append(did)
   269  		}
   270  		for tid, table := range entry.tables {
   271  			if table.drop {
   272  				bats[DropTable].GetVectorByName(GCAttrTableId).Append(tid)
   273  				bats[DropTable].GetVectorByName(GCAttrDBId).Append(did)
   274  			}
   275  
   276  			for name, obj := range table.object {
   277  				for _, block := range obj.table.blocks {
   278  					bats[CreateBlock].GetVectorByName(GCAttrBlockId).Append(block.BlockID)
   279  					bats[CreateBlock].GetVectorByName(GCAttrSegmentId).Append(block.SegmentID)
   280  					bats[CreateBlock].GetVectorByName(GCAttrTableId).Append(block.TableID)
   281  					bats[CreateBlock].GetVectorByName(GCAttrDBId).Append(block.PartID)
   282  					bats[CreateBlock].GetVectorByName(GCAttrObjectName).Append([]byte(name))
   283  				}
   284  				for _, block := range obj.table.delete {
   285  					bats[DeleteBlock].GetVectorByName(GCAttrBlockId).Append(block.BlockID)
   286  					bats[DeleteBlock].GetVectorByName(GCAttrSegmentId).Append(block.SegmentID)
   287  					bats[DeleteBlock].GetVectorByName(GCAttrTableId).Append(block.TableID)
   288  					bats[DeleteBlock].GetVectorByName(GCAttrDBId).Append(block.PartID)
   289  					bats[DeleteBlock].GetVectorByName(GCAttrObjectName).Append([]byte(name))
   290  				}
   291  			}
   292  		}
   293  	}
   294  
   295  	for _, name := range files {
   296  		bats[DeleteFile].GetVectorByName(GCAttrObjectName).Append([]byte(name))
   297  	}
   298  	return bats
   299  }
   300  
   301  func (t *GCTable) replayData(ctx context.Context,
   302  	typ BatchType,
   303  	attrs []string,
   304  	types []types.Type,
   305  	bats []*containers.Batch,
   306  	bs []objectio.BlockObject) error {
   307  	for i := range attrs {
   308  		col, err := bs[typ].GetColumn(uint16(i))
   309  		if err != nil {
   310  			return err
   311  		}
   312  		colData, err := col.GetData(ctx, common.DefaultAllocator)
   313  		if err != nil {
   314  			return err
   315  		}
   316  		pkgVec := vector.New(types[i])
   317  		v := make([]byte, len(colData.Entries[0].Object.([]byte)))
   318  		copy(v, colData.Entries[0].Object.([]byte))
   319  		if err = pkgVec.Read(v); err != nil {
   320  			return err
   321  		}
   322  		var vec containers.Vector
   323  		if pkgVec.Length() == 0 {
   324  			vec = containers.MakeVector(types[i], false)
   325  		} else {
   326  			vec = containers.NewVectorWithSharedMemory(pkgVec, false)
   327  		}
   328  		bats[typ].AddVector(attrs[i], vec)
   329  	}
   330  	return nil
   331  }
   332  
   333  // SaveTable is to write data to s3
   334  func (t *GCTable) SaveTable(start, end types.TS, fs *objectio.ObjectFS, files []string) ([]objectio.BlockObject, error) {
   335  	bats := t.collectData(files)
   336  	defer t.closeBatch(bats)
   337  	name := blockio.EncodeCheckpointMetadataFileName(GCMetaDir, PrefixGCMeta, start, end)
   338  	writer := blockio.NewWriter(context.Background(), fs, name)
   339  	for i := range bats {
   340  		if _, err := writer.WriteBlock(bats[i]); err != nil {
   341  			return nil, err
   342  		}
   343  	}
   344  
   345  	blocks, err := writer.Sync()
   346  	//logutil.Infof("SaveTable %v-%v, table: %v, gc: %v", start.ToString(), end.ToString(), t.String(), files)
   347  	return blocks, err
   348  }
   349  
   350  // SaveFullTable is to write data to s3
   351  func (t *GCTable) SaveFullTable(start, end types.TS, fs *objectio.ObjectFS, files []string) ([]objectio.BlockObject, error) {
   352  	bats := t.collectData(files)
   353  	defer t.closeBatch(bats)
   354  	name := blockio.EncodeGCMetadataFileName(GCMetaDir, PrefixGCMeta, start, end)
   355  	writer := blockio.NewWriter(context.Background(), fs, name)
   356  	for i := range bats {
   357  		if _, err := writer.WriteBlock(bats[i]); err != nil {
   358  			return nil, err
   359  		}
   360  	}
   361  
   362  	blocks, err := writer.Sync()
   363  	//logutil.Infof("SaveTable %v-%v, table: %v, gc: %v", start.ToString(), end.ToString(), t.String(), files)
   364  	return blocks, err
   365  }
   366  
   367  // ReadTable reads an s3 file and replays a GCTable in memory
   368  func (t *GCTable) ReadTable(ctx context.Context, name string, size int64, fs *objectio.ObjectFS) error {
   369  	reader, err := objectio.NewObjectReader(name, fs.Service)
   370  	if err != nil {
   371  		return err
   372  	}
   373  	bs, err := reader.ReadAllMeta(ctx, size, common.DefaultAllocator)
   374  	if err != nil {
   375  		return err
   376  	}
   377  	bats := t.makeBatchWithGCTable()
   378  	defer t.closeBatch(bats)
   379  	err = t.replayData(ctx, CreateBlock, BlockSchemaAttr, BlockSchemaTypes, bats, bs)
   380  	if err != nil {
   381  		return err
   382  	}
   383  	err = t.replayData(ctx, DeleteBlock, BlockSchemaAttr, BlockSchemaTypes, bats, bs)
   384  	if err != nil {
   385  		return err
   386  	}
   387  	err = t.replayData(ctx, DropTable, DropTableSchemaAttr, DropTableSchemaTypes, bats, bs)
   388  	if err != nil {
   389  		return err
   390  	}
   391  	err = t.replayData(ctx, DropDB, DropDBSchemaAtt, DropDBSchemaTypes, bats, bs)
   392  	if err != nil {
   393  		return err
   394  	}
   395  	err = t.replayData(ctx, DeleteFile, DeleteFileSchemaAtt, DeleteFileSchemaTypes, bats, bs)
   396  	if err != nil {
   397  		return err
   398  	}
   399  
   400  	t.rebuildTable(bats)
   401  	return nil
   402  }
   403  
   404  // For test
   405  func (t *GCTable) Compare(table *GCTable) bool {
   406  	if len(t.dbs) != len(table.dbs) {
   407  		return false
   408  	}
   409  	for id, entry := range t.dbs {
   410  		db := table.dbs[id]
   411  		if db == nil {
   412  			return false
   413  		}
   414  		ok := entry.Compare(db)
   415  		if !ok {
   416  			return ok
   417  		}
   418  
   419  	}
   420  	return true
   421  }
   422  
   423  func (t *GCTable) String() string {
   424  	if len(t.dbs) == 0 {
   425  		return ""
   426  	}
   427  	var w bytes.Buffer
   428  	_, _ = w.WriteString("dbs:[\n")
   429  	for id, entry := range t.dbs {
   430  		_, _ = w.WriteString(fmt.Sprintf("db: %d, isdrop: %t ", id, entry.drop))
   431  		_, _ = w.WriteString(entry.String())
   432  	}
   433  	_, _ = w.WriteString("]\n")
   434  	return w.String()
   435  }