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 }