github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/catalog/catalog.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 catalog 16 17 import ( 18 "bytes" 19 "context" 20 "fmt" 21 "sync" 22 "sync/atomic" 23 24 // "time" 25 26 pkgcatalog "github.com/matrixorigin/matrixone/pkg/catalog" 27 "github.com/matrixorigin/matrixone/pkg/common/moerr" 28 "github.com/matrixorigin/matrixone/pkg/container/types" 29 "github.com/matrixorigin/matrixone/pkg/logutil" 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/iface/txnif" 33 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tasks" 34 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 35 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal" 36 ) 37 38 // +--------+---------+----------+----------+------------+ 39 // | ID | Name | CreateAt | DeleteAt | CommitInfo | 40 // +--------+---------+----------+----------+------------+ 41 // |(uint64)|(varchar)| (uint64) | (uint64) | (varchar) | 42 // +--------+---------+----------+----------+------------+ 43 const ( 44 SnapshotAttr_SegID = "segment_id" 45 SnapshotAttr_TID = "table_id" 46 SnapshotAttr_DBID = "db_id" 47 SegmentAttr_ID = "id" 48 SegmentAttr_CreateAt = "create_at" 49 SegmentAttr_State = "state" 50 SegmentAttr_Sorted = "sorted" 51 SnapshotAttr_BlockMaxRow = "block_max_row" 52 SnapshotAttr_SegmentMaxBlock = "segment_max_block" 53 ) 54 55 type DataFactory interface { 56 MakeTableFactory() TableDataFactory 57 MakeSegmentFactory() SegmentDataFactory 58 MakeBlockFactory() BlockDataFactory 59 } 60 61 func rowIDToU64(rowID types.Rowid) uint64 { 62 return types.DecodeUint64(rowID[:8]) 63 } 64 65 type Catalog struct { 66 *IDAlloctor 67 *sync.RWMutex 68 69 scheduler tasks.TaskScheduler 70 71 entries map[uint64]*common.GenericDLNode[*DBEntry] 72 nameNodes map[string]*nodeList[*DBEntry] 73 link *common.GenericSortedDList[*DBEntry] 74 75 nodesMu sync.RWMutex 76 77 tableCnt atomic.Int32 78 columnCnt atomic.Int32 79 } 80 81 func genDBFullName(tenantID uint32, name string) string { 82 if name == pkgcatalog.MO_CATALOG { 83 tenantID = 0 84 } 85 return fmt.Sprintf("%d-%s", tenantID, name) 86 } 87 88 func compareDBFn(a, b *DBEntry) int { 89 return a.DBBaseEntry.DoCompre(b.DBBaseEntry) 90 } 91 92 func MockCatalog(scheduler tasks.TaskScheduler) *Catalog { 93 catalog := &Catalog{ 94 RWMutex: new(sync.RWMutex), 95 IDAlloctor: NewIDAllocator(), 96 entries: make(map[uint64]*common.GenericDLNode[*DBEntry]), 97 nameNodes: make(map[string]*nodeList[*DBEntry]), 98 link: common.NewGenericSortedDList(compareDBFn), 99 scheduler: scheduler, 100 } 101 catalog.InitSystemDB() 102 return catalog 103 } 104 105 func NewEmptyCatalog() *Catalog { 106 return &Catalog{ 107 RWMutex: new(sync.RWMutex), 108 IDAlloctor: NewIDAllocator(), 109 entries: make(map[uint64]*common.GenericDLNode[*DBEntry]), 110 nameNodes: make(map[string]*nodeList[*DBEntry]), 111 link: common.NewGenericSortedDList(compareDBFn), 112 scheduler: nil, 113 } 114 } 115 116 func OpenCatalog(scheduler tasks.TaskScheduler, dataFactory DataFactory) (*Catalog, error) { 117 catalog := &Catalog{ 118 RWMutex: new(sync.RWMutex), 119 IDAlloctor: NewIDAllocator(), 120 entries: make(map[uint64]*common.GenericDLNode[*DBEntry]), 121 nameNodes: make(map[string]*nodeList[*DBEntry]), 122 link: common.NewGenericSortedDList(compareDBFn), 123 scheduler: scheduler, 124 } 125 catalog.InitSystemDB() 126 return catalog, nil 127 } 128 129 func (catalog *Catalog) InitSystemDB() { 130 sysDB := NewSystemDBEntry(catalog) 131 dbTables := NewSystemTableEntry(sysDB, pkgcatalog.MO_DATABASE_ID, SystemDBSchema) 132 tableTables := NewSystemTableEntry(sysDB, pkgcatalog.MO_TABLES_ID, SystemTableSchema) 133 columnTables := NewSystemTableEntry(sysDB, pkgcatalog.MO_COLUMNS_ID, SystemColumnSchema) 134 err := sysDB.AddEntryLocked(dbTables, nil, false) 135 if err != nil { 136 panic(err) 137 } 138 if err = sysDB.AddEntryLocked(tableTables, nil, false); err != nil { 139 panic(err) 140 } 141 if err = sysDB.AddEntryLocked(columnTables, nil, false); err != nil { 142 panic(err) 143 } 144 if err = catalog.AddEntryLocked(sysDB, nil, false); err != nil { 145 panic(err) 146 } 147 } 148 func (catalog *Catalog) GCByTS(ctx context.Context, ts types.TS) { 149 logutil.Infof("GC Catalog %v", ts.ToString()) 150 processor := LoopProcessor{} 151 processor.DatabaseFn = func(d *DBEntry) error { 152 d.RLock() 153 needGC := d.DeleteBefore(ts) 154 d.RUnlock() 155 if needGC { 156 catalog.RemoveEntry(d) 157 } 158 return nil 159 } 160 processor.TableFn = func(te *TableEntry) error { 161 te.RLock() 162 needGC := te.DeleteBefore(ts) 163 te.RUnlock() 164 if needGC { 165 db := te.db 166 db.RemoveEntry(te) 167 } 168 return nil 169 } 170 processor.SegmentFn = func(se *SegmentEntry) error { 171 se.RLock() 172 needGC := se.DeleteBefore(ts) 173 se.RUnlock() 174 if needGC { 175 tbl := se.table 176 tbl.RemoveEntry(se) 177 } 178 return nil 179 } 180 processor.BlockFn = func(be *BlockEntry) error { 181 be.RLock() 182 needGC := be.DeleteBefore(ts) 183 be.RUnlock() 184 if needGC { 185 seg := be.segment 186 seg.RemoveEntry(be) 187 } 188 return nil 189 } 190 err := catalog.RecurLoop(&processor) 191 if err != nil { 192 panic(err) 193 } 194 } 195 func (catalog *Catalog) ReplayCmd( 196 txncmd txnif.TxnCmd, 197 dataFactory DataFactory, 198 idxCtx *wal.Index, 199 observer wal.ReplayObserver) { 200 switch txncmd.GetType() { 201 case txnbase.CmdComposed: 202 cmds := txncmd.(*txnbase.ComposedCmd) 203 idxCtx.Size = cmds.CmdSize 204 for i, cmds := range cmds.Cmds { 205 idx := idxCtx.Clone() 206 idx.CSN = uint32(i) 207 catalog.ReplayCmd(cmds, dataFactory, idx, observer) 208 } 209 case CmdUpdateDatabase: 210 cmd := txncmd.(*EntryCommand) 211 catalog.onReplayUpdateDatabase(cmd, idxCtx, observer) 212 case CmdUpdateTable: 213 cmd := txncmd.(*EntryCommand) 214 catalog.onReplayUpdateTable(cmd, dataFactory, idxCtx, observer) 215 case CmdUpdateSegment: 216 cmd := txncmd.(*EntryCommand) 217 catalog.onReplayUpdateSegment(cmd, dataFactory, idxCtx, observer) 218 case CmdUpdateBlock: 219 cmd := txncmd.(*EntryCommand) 220 catalog.onReplayUpdateBlock(cmd, dataFactory, idxCtx, observer) 221 default: 222 panic("unsupport") 223 } 224 } 225 226 func (catalog *Catalog) onReplayUpdateDatabase(cmd *EntryCommand, idx *wal.Index, observer wal.ReplayObserver) { 227 catalog.OnReplayDBID(cmd.DB.ID) 228 var err error 229 un := cmd.entry.GetLatestNodeLocked().(*DBMVCCNode) 230 un.SetLogIndex(idx) 231 if un.Is1PC() { 232 if err := un.ApplyCommit(nil); err != nil { 233 panic(err) 234 } 235 } 236 237 db, err := catalog.GetDatabaseByID(cmd.entry.GetID()) 238 if err != nil { 239 cmd.DB.RWMutex = new(sync.RWMutex) 240 cmd.DB.catalog = catalog 241 cmd.entry.GetLatestNodeLocked().SetLogIndex(idx) 242 err = catalog.AddEntryLocked(cmd.DB, un.GetTxn(), false) 243 if err != nil { 244 panic(err) 245 } 246 return 247 } 248 249 dbun := db.SearchNode(un) 250 if dbun == nil { 251 db.Insert(un) 252 } else { 253 return 254 // panic(fmt.Sprintf("logic err: duplicate node %v and %v", dbun.String(), un.String())) 255 } 256 } 257 258 func (catalog *Catalog) OnReplayDatabaseBatch(ins, insTxn, del, delTxn *containers.Batch) { 259 for i := 0; i < ins.Length(); i++ { 260 dbid := ins.GetVectorByName(pkgcatalog.SystemDBAttr_ID).Get(i).(uint64) 261 name := string(ins.GetVectorByName(pkgcatalog.SystemDBAttr_Name).Get(i).([]byte)) 262 txnNode := txnbase.ReadTuple(insTxn, i) 263 tenantID := ins.GetVectorByName(pkgcatalog.SystemDBAttr_AccID).Get(i).(uint32) 264 userID := ins.GetVectorByName(pkgcatalog.SystemDBAttr_Creator).Get(i).(uint32) 265 roleID := ins.GetVectorByName(pkgcatalog.SystemDBAttr_Owner).Get(i).(uint32) 266 createAt := ins.GetVectorByName(pkgcatalog.SystemDBAttr_CreateAt).Get(i).(types.Timestamp) 267 catalog.onReplayCreateDB(dbid, name, txnNode, tenantID, userID, roleID, createAt) 268 } 269 for i := 0; i < del.Length(); i++ { 270 dbid := delTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64) 271 txnNode := txnbase.ReadTuple(delTxn, i) 272 catalog.onReplayDeleteDB(dbid, txnNode) 273 } 274 } 275 276 func (catalog *Catalog) onReplayCreateDB(dbid uint64, name string, txnNode *txnbase.TxnMVCCNode, tenantID, userID, roleID uint32, createAt types.Timestamp) { 277 catalog.OnReplayDBID(dbid) 278 db, _ := catalog.GetDatabaseByID(dbid) 279 if db != nil { 280 dbCreatedAt := db.GetCreatedAt() 281 if !dbCreatedAt.Equal(txnNode.End) { 282 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), dbCreatedAt.ToString())) 283 } 284 return 285 } 286 db = NewReplayDBEntry() 287 db.catalog = catalog 288 db.ID = dbid 289 db.name = name 290 db.acInfo = accessInfo{ 291 TenantID: tenantID, 292 UserID: userID, 293 RoleID: roleID, 294 CreateAt: createAt, 295 } 296 _ = catalog.AddEntryLocked(db, nil, true) 297 un := &DBMVCCNode{ 298 EntryMVCCNode: &EntryMVCCNode{ 299 CreatedAt: txnNode.End, 300 }, 301 TxnMVCCNode: txnNode, 302 } 303 db.Insert(un) 304 } 305 func (catalog *Catalog) onReplayDeleteDB(dbid uint64, txnNode *txnbase.TxnMVCCNode) { 306 catalog.OnReplayDBID(dbid) 307 db, err := catalog.GetDatabaseByID(dbid) 308 if err != nil { 309 logutil.Infof("delete %d", dbid) 310 logutil.Info(catalog.SimplePPString(common.PPL3)) 311 panic(err) 312 } 313 dbDeleteAt := db.GetDeleteAt() 314 if !dbDeleteAt.IsEmpty() { 315 if !dbDeleteAt.Equal(txnNode.End) { 316 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), dbDeleteAt.ToString())) 317 } 318 return 319 } 320 un := &DBMVCCNode{ 321 EntryMVCCNode: &EntryMVCCNode{ 322 CreatedAt: db.GetCreatedAt(), 323 DeletedAt: txnNode.End, 324 }, 325 TxnMVCCNode: txnNode, 326 } 327 db.Insert(un) 328 } 329 func (catalog *Catalog) onReplayUpdateTable(cmd *EntryCommand, dataFactory DataFactory, idx *wal.Index, observer wal.ReplayObserver) { 330 catalog.OnReplayTableID(cmd.Table.ID) 331 // prepareTS := cmd.GetTs() 332 // if prepareTS.LessEq(catalog.GetCheckpointed().MaxTS) { 333 // if observer != nil { 334 // observer.OnStaleIndex(idx) 335 // } 336 // return 337 // } 338 db, err := catalog.GetDatabaseByID(cmd.DBID) 339 if err != nil { 340 panic(err) 341 } 342 tbl, err := db.GetTableEntryByID(cmd.Table.ID) 343 344 un := cmd.entry.GetLatestNodeLocked().(*TableMVCCNode) 345 un.SetLogIndex(idx) 346 if un.Is1PC() { 347 if err := un.ApplyCommit(nil); err != nil { 348 panic(err) 349 } 350 } 351 352 if err != nil { 353 cmd.Table.db = db 354 cmd.Table.tableData = dataFactory.MakeTableFactory()(cmd.Table) 355 err = db.AddEntryLocked(cmd.Table, un.GetTxn(), false) 356 if err != nil { 357 logutil.Warn(catalog.SimplePPString(common.PPL3)) 358 panic(err) 359 } 360 return 361 } 362 tblun := tbl.SearchNode(un) 363 if tblun == nil { 364 tbl.Insert(un) //TODO isvalid 365 } 366 367 } 368 369 func (catalog *Catalog) OnReplayTableBatch(ins, insTxn, insCol, del, delTxn *containers.Batch, dataFactory DataFactory) { 370 schemaOffset := 0 371 for i := 0; i < ins.Length(); i++ { 372 tid := ins.GetVectorByName(pkgcatalog.SystemRelAttr_ID).Get(i).(uint64) 373 dbid := ins.GetVectorByName(pkgcatalog.SystemRelAttr_DBID).Get(i).(uint64) 374 name := string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_Name).Get(i).([]byte)) 375 schema := NewEmptySchema(name) 376 schemaOffset = schema.ReadFromBatch(insCol, schemaOffset, tid) 377 schema.Comment = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_Comment).Get(i).([]byte)) 378 schema.Partition = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_Partition).Get(i).([]byte)) 379 schema.Relkind = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_Kind).Get(i).([]byte)) 380 schema.Createsql = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_CreateSQL).Get(i).([]byte)) 381 schema.View = string(ins.GetVectorByName(pkgcatalog.SystemRelAttr_ViewDef).Get(i).([]byte)) 382 schema.Constraint = ins.GetVectorByName(pkgcatalog.SystemRelAttr_Constraint).Get(i).([]byte) 383 schema.AcInfo = accessInfo{} 384 schema.AcInfo.RoleID = ins.GetVectorByName(pkgcatalog.SystemRelAttr_Owner).Get(i).(uint32) 385 schema.AcInfo.UserID = ins.GetVectorByName(pkgcatalog.SystemRelAttr_Creator).Get(i).(uint32) 386 schema.AcInfo.CreateAt = ins.GetVectorByName(pkgcatalog.SystemRelAttr_CreateAt).Get(i).(types.Timestamp) 387 schema.AcInfo.TenantID = ins.GetVectorByName(pkgcatalog.SystemRelAttr_AccID).Get(i).(uint32) 388 schema.BlockMaxRows = insTxn.GetVectorByName(SnapshotAttr_BlockMaxRow).Get(i).(uint32) 389 schema.SegmentMaxBlocks = insTxn.GetVectorByName(SnapshotAttr_SegmentMaxBlock).Get(i).(uint16) 390 txnNode := txnbase.ReadTuple(insTxn, i) 391 catalog.onReplayCreateTable(dbid, tid, schema, txnNode, dataFactory) 392 } 393 for i := 0; i < del.Length(); i++ { 394 dbid := delTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64) 395 tid := delTxn.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64) 396 txnNode := txnbase.ReadTuple(delTxn, i) 397 catalog.onReplayDeleteTable(dbid, tid, txnNode) 398 } 399 } 400 401 func (catalog *Catalog) onReplayCreateTable(dbid, tid uint64, schema *Schema, txnNode *txnbase.TxnMVCCNode, dataFactory DataFactory) { 402 catalog.OnReplayTableID(tid) 403 db, err := catalog.GetDatabaseByID(dbid) 404 if err != nil { 405 logutil.Info(catalog.SimplePPString(common.PPL3)) 406 panic(err) 407 } 408 tbl, _ := db.GetTableEntryByID(tid) 409 if tbl != nil { 410 tblCreatedAt := tbl.GetCreatedAt() 411 if tblCreatedAt.Greater(txnNode.End) { 412 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), tblCreatedAt.ToString())) 413 } 414 // update constraint 415 un := &TableMVCCNode{ 416 EntryMVCCNode: &EntryMVCCNode{ 417 CreatedAt: tblCreatedAt, 418 }, 419 TxnMVCCNode: txnNode, 420 SchemaConstraints: string(schema.Constraint), 421 } 422 tbl.Insert(un) 423 424 return 425 } 426 tbl = NewReplayTableEntry() 427 tbl.schema = schema 428 tbl.db = db 429 tbl.ID = tid 430 tbl.tableData = dataFactory.MakeTableFactory()(tbl) 431 _ = db.AddEntryLocked(tbl, nil, true) 432 un := &TableMVCCNode{ 433 EntryMVCCNode: &EntryMVCCNode{ 434 CreatedAt: txnNode.End, 435 }, 436 TxnMVCCNode: txnNode, 437 SchemaConstraints: string(schema.Constraint), 438 } 439 tbl.Insert(un) 440 } 441 func (catalog *Catalog) onReplayDeleteTable(dbid, tid uint64, txnNode *txnbase.TxnMVCCNode) { 442 catalog.OnReplayTableID(tid) 443 db, err := catalog.GetDatabaseByID(dbid) 444 if err != nil { 445 logutil.Info(catalog.SimplePPString(common.PPL3)) 446 panic(err) 447 } 448 tbl, err := db.GetTableEntryByID(tid) 449 if err != nil { 450 logutil.Info(catalog.SimplePPString(common.PPL3)) 451 panic(err) 452 } 453 tableDeleteAt := tbl.GetDeleteAt() 454 if !tableDeleteAt.IsEmpty() { 455 if !tableDeleteAt.Equal(txnNode.End) { 456 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), tableDeleteAt.ToString())) 457 } 458 return 459 } 460 prev := tbl.MVCCChain.GetLatestCommittedNode().(*TableMVCCNode) 461 un := &TableMVCCNode{ 462 EntryMVCCNode: &EntryMVCCNode{ 463 CreatedAt: prev.CreatedAt, 464 DeletedAt: txnNode.End, 465 }, 466 TxnMVCCNode: txnNode, 467 } 468 tbl.Insert(un) 469 470 } 471 func (catalog *Catalog) onReplayUpdateSegment( 472 cmd *EntryCommand, 473 dataFactory DataFactory, 474 idx *wal.Index, 475 observer wal.ReplayObserver) { 476 catalog.OnReplaySegmentID(cmd.Segment.ID) 477 478 un := cmd.entry.GetLatestNodeLocked().(*MetadataMVCCNode) 479 un.SetLogIndex(idx) 480 if un.Is1PC() { 481 if err := un.ApplyCommit(nil); err != nil { 482 panic(err) 483 } 484 } 485 db, err := catalog.GetDatabaseByID(cmd.DBID) 486 if err != nil { 487 panic(err) 488 } 489 tbl, err := db.GetTableEntryByID(cmd.TableID) 490 if err != nil { 491 logutil.Infof("tbl %d-%d", cmd.DBID, cmd.TableID) 492 logutil.Info(catalog.SimplePPString(3)) 493 panic(err) 494 } 495 seg, err := tbl.GetSegmentByID(cmd.Segment.ID) 496 if err != nil { 497 cmd.Segment.table = tbl 498 cmd.Segment.RWMutex = new(sync.RWMutex) 499 cmd.Segment.segData = dataFactory.MakeSegmentFactory()(cmd.Segment) 500 tbl.AddEntryLocked(cmd.Segment) 501 } else { 502 node := seg.SearchNode(un) 503 if node == nil { 504 seg.Insert(un) 505 } else { 506 node.Update(un) 507 } 508 } 509 } 510 511 func (catalog *Catalog) OnReplaySegmentBatch(ins, insTxn, del, delTxn *containers.Batch, dataFactory DataFactory) { 512 idVec := ins.GetVectorByName(SegmentAttr_ID) 513 for i := 0; i < idVec.Length(); i++ { 514 dbid := insTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64) 515 tid := insTxn.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64) 516 appendable := ins.GetVectorByName(SegmentAttr_State).Get(i).(bool) 517 state := ES_NotAppendable 518 if appendable { 519 state = ES_Appendable 520 } 521 sorted := ins.GetVectorByName(SegmentAttr_Sorted).Get(i).(bool) 522 sid := ins.GetVectorByName(SegmentAttr_ID).Get(i).(uint64) 523 txnNode := txnbase.ReadTuple(insTxn, i) 524 catalog.onReplayCreateSegment(dbid, tid, sid, state, sorted, txnNode, dataFactory) 525 } 526 idVec = delTxn.GetVectorByName(SnapshotAttr_DBID) 527 for i := 0; i < idVec.Length(); i++ { 528 dbid := delTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64) 529 tid := delTxn.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64) 530 sid := del.GetVectorByName(AttrRowID).Get(i).(types.Rowid) 531 txnNode := txnbase.ReadTuple(delTxn, i) 532 catalog.onReplayDeleteSegment(dbid, tid, rowIDToU64(sid), txnNode) 533 } 534 } 535 func (catalog *Catalog) onReplayCreateSegment(dbid, tbid, segid uint64, state EntryState, sorted bool, txnNode *txnbase.TxnMVCCNode, dataFactory DataFactory) { 536 catalog.OnReplaySegmentID(segid) 537 db, err := catalog.GetDatabaseByID(dbid) 538 if err != nil { 539 logutil.Info(catalog.SimplePPString(common.PPL3)) 540 panic(err) 541 } 542 rel, err := db.GetTableEntryByID(tbid) 543 if err != nil { 544 logutil.Info(catalog.SimplePPString(common.PPL3)) 545 panic(err) 546 } 547 seg, _ := rel.GetSegmentByID(segid) 548 if seg != nil { 549 segCreatedAt := seg.GetCreatedAt() 550 if !segCreatedAt.Equal(txnNode.End) { 551 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), segCreatedAt.ToString())) 552 } 553 return 554 } 555 seg = NewReplaySegmentEntry() 556 seg.table = rel 557 seg.ID = segid 558 seg.state = state 559 seg.sorted = sorted 560 seg.segData = dataFactory.MakeSegmentFactory()(seg) 561 rel.AddEntryLocked(seg) 562 un := &MetadataMVCCNode{ 563 EntryMVCCNode: &EntryMVCCNode{ 564 CreatedAt: txnNode.End, 565 }, 566 TxnMVCCNode: txnNode, 567 } 568 seg.Insert(un) 569 } 570 func (catalog *Catalog) onReplayDeleteSegment(dbid, tbid, segid uint64, txnNode *txnbase.TxnMVCCNode) { 571 catalog.OnReplaySegmentID(segid) 572 db, err := catalog.GetDatabaseByID(dbid) 573 if err != nil { 574 logutil.Info(catalog.SimplePPString(common.PPL3)) 575 panic(err) 576 } 577 rel, err := db.GetTableEntryByID(tbid) 578 if err != nil { 579 logutil.Info(catalog.SimplePPString(common.PPL3)) 580 panic(err) 581 } 582 seg, err := rel.GetSegmentByID(segid) 583 if err != nil { 584 logutil.Info(catalog.SimplePPString(common.PPL3)) 585 panic(err) 586 } 587 segDeleteAt := seg.GetDeleteAt() 588 if !segDeleteAt.IsEmpty() { 589 if !segDeleteAt.Equal(txnNode.End) { 590 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), segDeleteAt.ToString())) 591 } 592 return 593 } 594 prevUn := seg.MVCCChain.GetLatestNodeLocked().(*MetadataMVCCNode) 595 un := &MetadataMVCCNode{ 596 EntryMVCCNode: &EntryMVCCNode{ 597 CreatedAt: prevUn.CreatedAt, 598 DeletedAt: txnNode.End, 599 }, 600 TxnMVCCNode: txnNode, 601 } 602 seg.Insert(un) 603 } 604 func (catalog *Catalog) onReplayUpdateBlock(cmd *EntryCommand, 605 dataFactory DataFactory, 606 idx *wal.Index, 607 observer wal.ReplayObserver) { 608 catalog.OnReplayBlockID(cmd.Block.ID) 609 prepareTS := cmd.GetTs() 610 db, err := catalog.GetDatabaseByID(cmd.DBID) 611 if err != nil { 612 panic(err) 613 } 614 tbl, err := db.GetTableEntryByID(cmd.TableID) 615 if err != nil { 616 panic(err) 617 } 618 seg, err := tbl.GetSegmentByID(cmd.SegmentID) 619 if err != nil { 620 panic(err) 621 } 622 blk, err := seg.GetBlockEntryByID(cmd.Block.ID) 623 un := cmd.entry.GetLatestNodeLocked().(*MetadataMVCCNode) 624 un.SetLogIndex(idx) 625 if un.Is1PC() { 626 if err := un.ApplyCommit(nil); err != nil { 627 panic(err) 628 } 629 } 630 if err == nil { 631 blkun := blk.SearchNode(un) 632 if blkun != nil { 633 blkun.Update(un) 634 } else { 635 blk.Insert(un) 636 } 637 return 638 } 639 cmd.Block.RWMutex = new(sync.RWMutex) 640 cmd.Block.segment = seg 641 cmd.Block.blkData = dataFactory.MakeBlockFactory()(cmd.Block) 642 if observer != nil { 643 observer.OnTimeStamp(prepareTS) 644 } 645 seg.AddEntryLocked(cmd.Block) 646 } 647 648 func (catalog *Catalog) OnReplayBlockBatch(ins, insTxn, del, delTxn *containers.Batch, dataFactory DataFactory) { 649 for i := 0; i < ins.Length(); i++ { 650 dbid := insTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64) 651 tid := insTxn.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64) 652 sid := insTxn.GetVectorByName(SnapshotAttr_SegID).Get(i).(uint64) 653 appendable := ins.GetVectorByName(pkgcatalog.BlockMeta_EntryState).Get(i).(bool) 654 state := ES_NotAppendable 655 if appendable { 656 state = ES_Appendable 657 } 658 blkID := ins.GetVectorByName(pkgcatalog.BlockMeta_ID).Get(i).(uint64) 659 metaLoc := string(ins.GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Get(i).([]byte)) 660 deltaLoc := string(ins.GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Get(i).([]byte)) 661 txnNode := txnbase.ReadTuple(insTxn, i) 662 catalog.onReplayCreateBlock(dbid, tid, sid, blkID, state, metaLoc, deltaLoc, txnNode, dataFactory) 663 } 664 for i := 0; i < del.Length(); i++ { 665 dbid := delTxn.GetVectorByName(SnapshotAttr_DBID).Get(i).(uint64) 666 tid := delTxn.GetVectorByName(SnapshotAttr_TID).Get(i).(uint64) 667 sid := delTxn.GetVectorByName(SnapshotAttr_SegID).Get(i).(uint64) 668 blkID := del.GetVectorByName(AttrRowID).Get(i).(types.Rowid) 669 un := txnbase.ReadTuple(delTxn, i) 670 metaLoc := string(delTxn.GetVectorByName(pkgcatalog.BlockMeta_MetaLoc).Get(i).([]byte)) 671 deltaLoc := string(delTxn.GetVectorByName(pkgcatalog.BlockMeta_DeltaLoc).Get(i).([]byte)) 672 catalog.onReplayDeleteBlock(dbid, tid, sid, rowIDToU64(blkID), metaLoc, deltaLoc, un) 673 } 674 } 675 func (catalog *Catalog) onReplayCreateBlock( 676 dbid, tid, segid, blkid uint64, 677 state EntryState, 678 metaloc, deltaloc string, 679 txnNode *txnbase.TxnMVCCNode, 680 dataFactory DataFactory) { 681 catalog.OnReplayBlockID(blkid) 682 db, err := catalog.GetDatabaseByID(dbid) 683 if err != nil { 684 logutil.Info(catalog.SimplePPString(common.PPL3)) 685 panic(err) 686 } 687 rel, err := db.GetTableEntryByID(tid) 688 if err != nil { 689 logutil.Info(catalog.SimplePPString(common.PPL3)) 690 panic(err) 691 } 692 seg, err := rel.GetSegmentByID(segid) 693 if err != nil { 694 logutil.Info(catalog.SimplePPString(common.PPL3)) 695 panic(err) 696 } 697 blk, _ := seg.GetBlockEntryByID(blkid) 698 var un *MetadataMVCCNode 699 if blk == nil { 700 blk = NewReplayBlockEntry() 701 blk.segment = seg 702 blk.ID = blkid 703 blk.state = state 704 blk.blkData = dataFactory.MakeBlockFactory()(blk) 705 seg.AddEntryLocked(blk) 706 un = &MetadataMVCCNode{ 707 EntryMVCCNode: &EntryMVCCNode{ 708 CreatedAt: txnNode.End, 709 }, 710 TxnMVCCNode: txnNode, 711 MetaLoc: metaloc, 712 DeltaLoc: deltaloc, 713 } 714 } else { 715 prevUn := blk.MVCCChain.GetLatestNodeLocked().(*MetadataMVCCNode) 716 un = &MetadataMVCCNode{ 717 EntryMVCCNode: &EntryMVCCNode{ 718 CreatedAt: prevUn.CreatedAt, 719 }, 720 TxnMVCCNode: txnNode, 721 MetaLoc: metaloc, 722 DeltaLoc: deltaloc, 723 } 724 node := blk.MVCCChain.SearchNode(un).(*MetadataMVCCNode) 725 if node != nil { 726 if !node.CreatedAt.Equal(un.CreatedAt) { 727 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", node.CreatedAt.ToString(), un.CreatedAt.ToString())) 728 } 729 if node.MetaLoc != un.MetaLoc { 730 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", node.MetaLoc, un.MetaLoc)) 731 } 732 if node.DeltaLoc != un.DeltaLoc { 733 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", node.DeltaLoc, un.DeltaLoc)) 734 } 735 return 736 } 737 } 738 blk.Insert(un) 739 } 740 func (catalog *Catalog) onReplayDeleteBlock(dbid, tid, segid, blkid uint64, metaloc, deltaloc string, txnNode *txnbase.TxnMVCCNode) { 741 catalog.OnReplayBlockID(blkid) 742 db, err := catalog.GetDatabaseByID(dbid) 743 if err != nil { 744 logutil.Info(catalog.SimplePPString(common.PPL3)) 745 panic(err) 746 } 747 rel, err := db.GetTableEntryByID(tid) 748 if err != nil { 749 logutil.Info(catalog.SimplePPString(common.PPL3)) 750 panic(err) 751 } 752 seg, err := rel.GetSegmentByID(segid) 753 if err != nil { 754 logutil.Info(catalog.SimplePPString(common.PPL3)) 755 panic(err) 756 } 757 blk, err := seg.GetBlockEntryByID(blkid) 758 if err != nil { 759 logutil.Info(catalog.SimplePPString(common.PPL3)) 760 panic(err) 761 } 762 blkDeleteAt := blk.GetDeleteAt() 763 if !blkDeleteAt.IsEmpty() { 764 if !blkDeleteAt.Equal(txnNode.End) { 765 panic(moerr.NewInternalErrorNoCtx("logic err expect %s, get %s", txnNode.End.ToString(), blkDeleteAt.ToString())) 766 } 767 return 768 } 769 prevUn := blk.MVCCChain.GetLatestNodeLocked().(*MetadataMVCCNode) 770 un := &MetadataMVCCNode{ 771 EntryMVCCNode: &EntryMVCCNode{ 772 CreatedAt: prevUn.CreatedAt, 773 DeletedAt: txnNode.End, 774 }, 775 TxnMVCCNode: txnNode, 776 MetaLoc: metaloc, 777 DeltaLoc: deltaloc, 778 } 779 blk.Insert(un) 780 } 781 func (catalog *Catalog) ReplayTableRows() { 782 rows := uint64(0) 783 tableProcessor := new(LoopProcessor) 784 tableProcessor.BlockFn = func(be *BlockEntry) error { 785 if !be.IsActive() { 786 return nil 787 } 788 rows += be.GetBlockData().GetRowsOnReplay() 789 return nil 790 } 791 processor := new(LoopProcessor) 792 processor.TableFn = func(tbl *TableEntry) error { 793 if tbl.db.name == pkgcatalog.MO_CATALOG { 794 return nil 795 } 796 rows = 0 797 err := tbl.RecurLoop(tableProcessor) 798 if err != nil { 799 panic(err) 800 } 801 tbl.rows.Store(rows) 802 return nil 803 } 804 err := catalog.RecurLoop(processor) 805 if err != nil { 806 panic(err) 807 } 808 } 809 func (catalog *Catalog) Close() error { 810 return nil 811 } 812 813 func (catalog *Catalog) CoarseDBCnt() int { 814 catalog.RLock() 815 defer catalog.RUnlock() 816 return len(catalog.entries) 817 } 818 819 func (catalog *Catalog) CoarseTableCnt() int { 820 return int(catalog.tableCnt.Load()) 821 } 822 823 func (catalog *Catalog) CoarseColumnCnt() int { 824 return int(catalog.columnCnt.Load()) 825 } 826 827 func (catalog *Catalog) AddTableCnt(cnt int) { 828 if catalog.tableCnt.Add(int32(cnt)) < 0 { 829 panic("logic error") 830 } 831 } 832 833 func (catalog *Catalog) AddColumnCnt(cnt int) { 834 if catalog.columnCnt.Add(int32(cnt)) < 0 { 835 panic("logic error") 836 } 837 } 838 839 func (catalog *Catalog) GetItemNodeByIDLocked(id uint64) *common.GenericDLNode[*DBEntry] { 840 return catalog.entries[id] 841 } 842 843 func (catalog *Catalog) GetScheduler() tasks.TaskScheduler { return catalog.scheduler } 844 func (catalog *Catalog) GetDatabaseByID(id uint64) (db *DBEntry, err error) { 845 catalog.RLock() 846 defer catalog.RUnlock() 847 node := catalog.entries[id] 848 if node == nil { 849 err = moerr.GetOkExpectedEOB() 850 return 851 } 852 db = node.GetPayload() 853 return 854 } 855 856 func (catalog *Catalog) AddEntryLocked(database *DBEntry, txn txnif.TxnReader, skipDedup bool) error { 857 nn := catalog.nameNodes[database.GetFullName()] 858 if nn == nil { 859 n := catalog.link.Insert(database) 860 catalog.entries[database.GetID()] = n 861 862 nn := newNodeList(catalog.GetItemNodeByIDLocked, 863 dbVisibilityFn[*DBEntry], 864 &catalog.nodesMu, 865 database.name) 866 catalog.nameNodes[database.GetFullName()] = nn 867 868 nn.CreateNode(database.GetID()) 869 } else { 870 node := nn.GetNode() 871 if !skipDedup { 872 record := node.GetPayload() 873 err := record.PrepareAdd(txn) 874 if err != nil { 875 return err 876 } 877 } 878 n := catalog.link.Insert(database) 879 catalog.entries[database.GetID()] = n 880 nn.CreateNode(database.GetID()) 881 } 882 return nil 883 } 884 885 func (catalog *Catalog) MakeDBIt(reverse bool) *common.GenericSortedDListIt[*DBEntry] { 886 catalog.RLock() 887 defer catalog.RUnlock() 888 return common.NewGenericSortedDListIt(catalog.RWMutex, catalog.link, reverse) 889 } 890 891 func (catalog *Catalog) SimplePPString(level common.PPLevel) string { 892 return catalog.PPString(level, 0, "") 893 } 894 895 func (catalog *Catalog) PPString(level common.PPLevel, depth int, prefix string) string { 896 var w bytes.Buffer 897 cnt := 0 898 it := catalog.MakeDBIt(true) 899 for it.Valid() { 900 cnt++ 901 entry := it.Get().GetPayload() 902 _ = w.WriteByte('\n') 903 _, _ = w.WriteString(entry.PPString(level, depth+1, "")) 904 it.Next() 905 } 906 907 var w2 bytes.Buffer 908 _, _ = w2.WriteString(fmt.Sprintf("CATALOG[CNT=%d]", cnt)) 909 _, _ = w2.WriteString(w.String()) 910 return w2.String() 911 } 912 913 func (catalog *Catalog) RemoveEntry(database *DBEntry) error { 914 if database.IsSystemDB() { 915 logutil.Warnf("system db cannot be removed") 916 return moerr.NewTAEErrorNoCtx("not permitted") 917 } 918 logutil.Info("[Catalog]", common.OperationField("remove"), 919 common.OperandField(database.String())) 920 // database.Close() 921 catalog.Lock() 922 defer catalog.Unlock() 923 if n, ok := catalog.entries[database.GetID()]; !ok { 924 return moerr.NewBadDBNoCtx(database.GetName()) 925 } else { 926 nn := catalog.nameNodes[database.GetFullName()] 927 nn.DeleteNode(database.GetID()) 928 catalog.link.Delete(n) 929 if nn.Length() == 0 { 930 delete(catalog.nameNodes, database.GetFullName()) 931 } 932 delete(catalog.entries, database.GetID()) 933 } 934 return nil 935 } 936 937 func (catalog *Catalog) txnGetNodeByName( 938 tenantID uint32, 939 name string, 940 ts types.TS) (*common.GenericDLNode[*DBEntry], error) { 941 catalog.RLock() 942 defer catalog.RUnlock() 943 fullName := genDBFullName(tenantID, name) 944 node := catalog.nameNodes[fullName] 945 if node == nil { 946 return nil, moerr.NewBadDBNoCtx(name) 947 } 948 return node.TxnGetNodeLocked(ts) 949 } 950 951 func (catalog *Catalog) GetDBEntryByName( 952 tenantID uint32, 953 name string, 954 ts types.TS) (db *DBEntry, err error) { 955 n, err := catalog.txnGetNodeByName(tenantID, name, ts) 956 if err != nil { 957 return 958 } 959 db = n.GetPayload() 960 return 961 } 962 963 func (catalog *Catalog) TxnGetDBEntryByName(name string, txn txnif.AsyncTxn) (*DBEntry, error) { 964 n, err := catalog.txnGetNodeByName(txn.GetTenantID(), name, txn.GetStartTS()) 965 if err != nil { 966 return nil, err 967 } 968 return n.GetPayload(), nil 969 } 970 971 func (catalog *Catalog) TxnGetDBEntryByID(id uint64, txn txnif.AsyncTxn) (*DBEntry, error) { 972 dbEntry, err := catalog.GetDatabaseByID(id) 973 if err != nil { 974 return nil, err 975 } 976 visiable, dropped := dbEntry.GetVisibility(txn.GetStartTS()) 977 if !visiable || dropped { 978 return nil, moerr.GetOkExpectedEOB() 979 } 980 return dbEntry, nil 981 } 982 983 func (catalog *Catalog) DropDBEntry( 984 name string, 985 txn txnif.AsyncTxn) (newEntry bool, deleted *DBEntry, err error) { 986 if name == pkgcatalog.MO_CATALOG { 987 err = moerr.NewTAEErrorNoCtx("not permitted") 988 return 989 } 990 dn, err := catalog.txnGetNodeByName(txn.GetTenantID(), name, txn.GetStartTS()) 991 if err != nil { 992 return 993 } 994 entry := dn.GetPayload() 995 entry.Lock() 996 defer entry.Unlock() 997 if newEntry, err = entry.DropEntryLocked(txn); err == nil { 998 deleted = entry 999 } 1000 return 1001 } 1002 1003 func (catalog *Catalog) DropDBEntryByID(id uint64, txn txnif.AsyncTxn) (newEntry bool, deleted *DBEntry, err error) { 1004 if id == pkgcatalog.MO_CATALOG_ID { 1005 err = moerr.NewTAEErrorNoCtx("not permitted") 1006 return 1007 } 1008 entry, err := catalog.GetDatabaseByID(id) 1009 if err != nil { 1010 return 1011 } 1012 entry.Lock() 1013 defer entry.Unlock() 1014 if newEntry, err = entry.DropEntryLocked(txn); err == nil { 1015 deleted = entry 1016 } 1017 return 1018 } 1019 1020 func (catalog *Catalog) CreateDBEntry(name, createSql string, txn txnif.AsyncTxn) (*DBEntry, error) { 1021 var err error 1022 catalog.Lock() 1023 defer catalog.Unlock() 1024 entry := NewDBEntry(catalog, name, createSql, txn) 1025 err = catalog.AddEntryLocked(entry, txn, false) 1026 1027 return entry, err 1028 } 1029 1030 func (catalog *Catalog) CreateDBEntryWithID(name, createSql string, id uint64, txn txnif.AsyncTxn) (*DBEntry, error) { 1031 var err error 1032 catalog.Lock() 1033 defer catalog.Unlock() 1034 if _, exist := catalog.entries[id]; exist { 1035 return nil, moerr.GetOkExpectedDup() 1036 } 1037 entry := NewDBEntryWithID(catalog, name, createSql, id, txn) 1038 err = catalog.AddEntryLocked(entry, txn, false) 1039 1040 return entry, err 1041 } 1042 1043 func (catalog *Catalog) CreateDBEntryByTS(name string, ts types.TS) (*DBEntry, error) { 1044 entry := NewDBEntryByTS(catalog, name, ts) 1045 err := catalog.AddEntryLocked(entry, nil, false) 1046 return entry, err 1047 } 1048 1049 func (catalog *Catalog) RecurLoop(processor Processor) (err error) { 1050 dbIt := catalog.MakeDBIt(true) 1051 for dbIt.Valid() { 1052 dbEntry := dbIt.Get().GetPayload() 1053 if err = processor.OnDatabase(dbEntry); err != nil { 1054 // XXX: Performance problem. Error should not be used 1055 // to handle normal return code. 1056 if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) { 1057 err = nil 1058 dbIt.Next() 1059 continue 1060 } 1061 break 1062 } 1063 if err = dbEntry.RecurLoop(processor); err != nil { 1064 return 1065 } 1066 dbIt.Next() 1067 } 1068 if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) { 1069 err = nil 1070 } 1071 return err 1072 }