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 }