github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/txndb.go (about) 1 // Copyright 2022 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 txnimpl 16 17 import ( 18 "sync" 19 "time" 20 21 "github.com/matrixorigin/matrixone/pkg/common/moerr" 22 "github.com/matrixorigin/matrixone/pkg/logutil" 23 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 28 ) 29 30 type txnDB struct { 31 store *txnStore 32 tables map[uint64]*txnTable 33 mu sync.RWMutex 34 entry *catalog.DBEntry 35 createEntry txnif.TxnEntry 36 dropEntry txnif.TxnEntry 37 ddlCSN uint32 38 idx int 39 } 40 41 func newTxnDB(store *txnStore, entry *catalog.DBEntry) *txnDB { 42 db := &txnDB{ 43 store: store, 44 tables: make(map[uint64]*txnTable), 45 entry: entry, 46 } 47 return db 48 } 49 50 func (db *txnDB) SetCreateEntry(e txnif.TxnEntry) error { 51 if db.createEntry != nil { 52 panic("logic error") 53 } 54 db.store.IncreateWriteCnt() 55 db.store.txn.GetMemo().AddCatalogChange() 56 db.createEntry = e 57 return nil 58 } 59 60 func (db *txnDB) SetDropEntry(e txnif.TxnEntry) error { 61 if db.dropEntry != nil { 62 panic("logic error") 63 } 64 db.store.IncreateWriteCnt() 65 db.store.txn.GetMemo().AddCatalogChange() 66 db.dropEntry = e 67 return nil 68 } 69 70 func (db *txnDB) LogTxnEntry(tableId uint64, entry txnif.TxnEntry, readed []*common.ID) (err error) { 71 table, err := db.getOrSetTable(tableId) 72 if err != nil { 73 return 74 } 75 return table.LogTxnEntry(entry, readed) 76 } 77 78 func (db *txnDB) LogSegmentID(tid, sid uint64) { 79 table, _ := db.getOrSetTable(tid) 80 table.LogSegmentID(sid) 81 } 82 83 func (db *txnDB) LogBlockID(tid, bid uint64) { 84 table, _ := db.getOrSetTable(tid) 85 table.LogBlockID(bid) 86 } 87 88 func (db *txnDB) Close() error { 89 var err error 90 for _, table := range db.tables { 91 if err = table.Close(); err != nil { 92 break 93 } 94 } 95 db.tables = nil 96 db.createEntry = nil 97 db.dropEntry = nil 98 return err 99 } 100 101 func (db *txnDB) BatchDedup(id uint64, pk containers.Vector) (err error) { 102 table, err := db.getOrSetTable(id) 103 if err != nil { 104 return err 105 } 106 if table.IsDeleted() { 107 return moerr.NewNotFoundNoCtx() 108 } 109 110 return table.DoBatchDedup(pk) 111 } 112 113 func (db *txnDB) Append(id uint64, bat *containers.Batch) error { 114 table, err := db.getOrSetTable(id) 115 if err != nil { 116 return err 117 } 118 if table.IsDeleted() { 119 return moerr.NewNotFoundNoCtx() 120 } 121 return table.Append(bat) 122 } 123 124 func (db *txnDB) AddBlksWithMetaLoc( 125 tid uint64, 126 pkVecs []containers.Vector, 127 file string, 128 metaLocs []string, 129 flag int32) error { 130 table, err := db.getOrSetTable(tid) 131 if err != nil { 132 return err 133 } 134 if table.IsDeleted() { 135 return moerr.NewNotFoundNoCtx() 136 } 137 return table.AddBlksWithMetaLoc(pkVecs, file, metaLocs, flag) 138 } 139 140 func (db *txnDB) DeleteOne(table *txnTable, id *common.ID, row uint32, dt handle.DeleteType) (err error) { 141 changed, nid, nrow, err := table.TransferDeleteIntent(id, row) 142 if err != nil { 143 return err 144 } 145 if !changed { 146 return table.RangeDelete(id, row, row, dt) 147 } 148 return table.RangeDelete(nid, nrow, nrow, dt) 149 } 150 151 func (db *txnDB) RangeDelete(id *common.ID, start, end uint32, dt handle.DeleteType) (err error) { 152 table, err := db.getOrSetTable(id.TableID) 153 if err != nil { 154 return err 155 } 156 if table.IsDeleted() { 157 return moerr.NewNotFoundNoCtx() 158 } 159 return table.RangeDelete(id, start, end, dt) 160 // if start == end { 161 // return db.DeleteOne(table, id, start, dt) 162 // } 163 // for i := start; i <= end; i++ { 164 // if err = db.DeleteOne(table, id, i, dt); err != nil { 165 // return 166 // } 167 // } 168 // return 169 } 170 171 func (db *txnDB) GetByFilter(tid uint64, filter *handle.Filter) (id *common.ID, offset uint32, err error) { 172 table, err := db.getOrSetTable(tid) 173 if err != nil { 174 return 175 } 176 if table.IsDeleted() { 177 err = moerr.NewNotFoundNoCtx() 178 return 179 } 180 return table.GetByFilter(filter) 181 } 182 183 func (db *txnDB) GetValue(id *common.ID, row uint32, colIdx uint16) (v any, err error) { 184 table, err := db.getOrSetTable(id.TableID) 185 if err != nil { 186 return 187 } 188 if table.IsDeleted() { 189 err = moerr.NewNotFoundNoCtx() 190 return 191 } 192 return table.GetValue(id, row, colIdx) 193 } 194 195 func (db *txnDB) CreateRelation(def any) (relation handle.Relation, err error) { 196 schema := def.(*catalog.Schema) 197 var factory catalog.TableDataFactory 198 if db.store.dataFactory != nil { 199 factory = db.store.dataFactory.MakeTableFactory() 200 } 201 meta, err := db.entry.CreateTableEntry(schema, db.store.txn, factory) 202 if err != nil { 203 return 204 } 205 table, err := db.getOrSetTable(meta.GetID()) 206 if err != nil { 207 return 208 } 209 relation = newRelation(table) 210 table.SetCreateEntry(meta) 211 return 212 } 213 214 func (db *txnDB) CreateRelationWithTableId(tableId uint64, def any) (relation handle.Relation, err error) { 215 schema := def.(*catalog.Schema) 216 var factory catalog.TableDataFactory 217 if db.store.dataFactory != nil { 218 factory = db.store.dataFactory.MakeTableFactory() 219 } 220 meta, err := db.entry.CreateTableEntryWithTableId(schema, db.store.txn, factory, tableId) 221 if err != nil { 222 return 223 } 224 table, err := db.getOrSetTable(meta.GetID()) 225 if err != nil { 226 return 227 } 228 relation = newRelation(table) 229 table.SetCreateEntry(meta) 230 return 231 } 232 233 func (db *txnDB) DropRelationByName(name string) (relation handle.Relation, err error) { 234 hasNewTxnEntry, meta, err := db.entry.DropTableEntry(name, db.store.txn) 235 if err != nil { 236 return nil, err 237 } 238 table, err := db.getOrSetTable(meta.GetID()) 239 if err != nil { 240 return nil, err 241 } 242 relation = newRelation(table) 243 if hasNewTxnEntry { 244 err = table.SetDropEntry(meta) 245 } 246 return 247 } 248 249 func (db *txnDB) DropRelationByID(id uint64) (relation handle.Relation, err error) { 250 hasNewTxnEntry, meta, err := db.entry.DropTableEntryByID(id, db.store.txn) 251 if err != nil { 252 return nil, err 253 } 254 table, err := db.getOrSetTable(meta.GetID()) 255 if err != nil { 256 return nil, err 257 } 258 relation = newRelation(table) 259 if hasNewTxnEntry { 260 err = table.SetDropEntry(meta) 261 } 262 return 263 } 264 265 func (db *txnDB) UnsafeGetRelation(id uint64) (relation handle.Relation, err error) { 266 meta, err := db.entry.GetTableEntryByID(id) 267 if err != nil { 268 return 269 } 270 table, err := db.getOrSetTable(meta.GetID()) 271 if err != nil { 272 return 273 } 274 relation = newRelation(table) 275 return 276 } 277 278 func (db *txnDB) GetRelationByName(name string) (relation handle.Relation, err error) { 279 meta, err := db.entry.TxnGetTableEntryByName(name, db.store.txn) 280 if err != nil { 281 return 282 } 283 table, err := db.getOrSetTable(meta.GetID()) 284 if err != nil { 285 return 286 } 287 relation = newRelation(table) 288 return 289 } 290 291 func (db *txnDB) GetRelationByID(id uint64) (relation handle.Relation, err error) { 292 meta, err := db.entry.TxnGetTableEntryByID(id, db.store.txn) 293 if err != nil { 294 return 295 } 296 table, err := db.getOrSetTable(meta.GetID()) 297 if err != nil { 298 return 299 } 300 relation = newRelation(table) 301 return 302 } 303 304 func (db *txnDB) GetSegment(id *common.ID) (seg handle.Segment, err error) { 305 var table *txnTable 306 if table, err = db.getOrSetTable(id.TableID); err != nil { 307 return 308 } 309 return table.GetSegment(id.SegmentID) 310 } 311 312 func (db *txnDB) CreateSegment(tid uint64, is1PC bool) (seg handle.Segment, err error) { 313 var table *txnTable 314 if table, err = db.getOrSetTable(tid); err != nil { 315 return 316 } 317 return table.CreateSegment(is1PC) 318 } 319 320 func (db *txnDB) CreateNonAppendableSegment(tid uint64, is1PC bool) (seg handle.Segment, err error) { 321 var table *txnTable 322 if table, err = db.getOrSetTable(tid); err != nil { 323 return 324 } 325 return table.CreateNonAppendableSegment(is1PC) 326 } 327 328 func (db *txnDB) getOrSetTable(id uint64) (table *txnTable, err error) { 329 db.mu.RLock() 330 table = db.tables[id] 331 db.mu.RUnlock() 332 if table != nil { 333 return 334 } 335 var entry *catalog.TableEntry 336 if entry, err = db.entry.GetTableEntryByID(id); err != nil { 337 return 338 } 339 db.mu.Lock() 340 defer db.mu.Unlock() 341 table = db.tables[id] 342 if table != nil { 343 return 344 } 345 if db.store.warChecker == nil { 346 db.store.warChecker = newWarChecker(db.store.txn, db.store.catalog) 347 } 348 table = newTxnTable(db.store, entry) 349 table.idx = len(db.tables) 350 db.tables[id] = table 351 return 352 } 353 354 func (db *txnDB) CreateNonAppendableBlock(id *common.ID) (blk handle.Block, err error) { 355 var table *txnTable 356 if table, err = db.getOrSetTable(id.TableID); err != nil { 357 return 358 } 359 return table.CreateNonAppendableBlock(id.SegmentID) 360 } 361 362 func (db *txnDB) CreateNonAppendableBlockWithMeta( 363 id *common.ID, 364 metaLoc string, 365 deltaLoc string) (blk handle.Block, err error) { 366 var table *txnTable 367 if table, err = db.getOrSetTable(id.TableID); err != nil { 368 return 369 } 370 return table.CreateNonAppendableBlockWithMeta(id.SegmentID, metaLoc, deltaLoc) 371 } 372 373 func (db *txnDB) GetBlock(id *common.ID) (blk handle.Block, err error) { 374 var table *txnTable 375 if table, err = db.getOrSetTable(id.TableID); err != nil { 376 return 377 } 378 return table.GetBlock(id) 379 } 380 381 func (db *txnDB) CreateBlock(tid, sid uint64, is1PC bool) (blk handle.Block, err error) { 382 var table *txnTable 383 if table, err = db.getOrSetTable(tid); err != nil { 384 return 385 } 386 return table.CreateBlock(sid, is1PC) 387 } 388 389 func (db *txnDB) SoftDeleteBlock(id *common.ID) (err error) { 390 var table *txnTable 391 if table, err = db.getOrSetTable(id.TableID); err != nil { 392 return 393 } 394 return table.SoftDeleteBlock(id) 395 } 396 func (db *txnDB) UpdateMetaLoc(id *common.ID, metaLoc string) (err error) { 397 var table *txnTable 398 if table, err = db.getOrSetTable(id.TableID); err != nil { 399 return 400 } 401 return table.UpdateMetaLoc(id, metaLoc) 402 } 403 func (db *txnDB) UpdateDeltaLoc(id *common.ID, deltaLoc string) (err error) { 404 var table *txnTable 405 if table, err = db.getOrSetTable(id.TableID); err != nil { 406 return 407 } 408 return table.UpdateDeltaLoc(id, deltaLoc) 409 } 410 func (db *txnDB) SoftDeleteSegment(id *common.ID) (err error) { 411 var table *txnTable 412 if table, err = db.getOrSetTable(id.TableID); err != nil { 413 return 414 } 415 return table.SoftDeleteSegment(id.SegmentID) 416 } 417 func (db *txnDB) NeedRollback() bool { 418 return db.createEntry != nil && db.dropEntry != nil 419 } 420 func (db *txnDB) ApplyRollback() (err error) { 421 if db.createEntry != nil { 422 if err = db.createEntry.ApplyRollback(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil { 423 return 424 } 425 } 426 for _, table := range db.tables { 427 if err = table.ApplyRollback(); err != nil { 428 break 429 } 430 } 431 if db.dropEntry != nil { 432 if err = db.dropEntry.ApplyRollback(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil { 433 return 434 } 435 } 436 return 437 } 438 439 func (db *txnDB) WaitPrepared() (err error) { 440 for _, table := range db.tables { 441 table.WaitSynced() 442 } 443 return 444 } 445 func (db *txnDB) Apply1PCCommit() (err error) { 446 if db.createEntry != nil && db.createEntry.Is1PC() { 447 if err = db.createEntry.ApplyCommit(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil { 448 return 449 } 450 } 451 for _, table := range db.tables { 452 if err = table.Apply1PCCommit(); err != nil { 453 break 454 } 455 } 456 if db.dropEntry != nil && db.dropEntry.Is1PC() { 457 if err = db.dropEntry.ApplyCommit(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil { 458 return 459 } 460 } 461 return 462 } 463 func (db *txnDB) ApplyCommit() (err error) { 464 now := time.Now() 465 if db.createEntry != nil && !db.createEntry.Is1PC() { 466 if err = db.createEntry.ApplyCommit(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil { 467 return 468 } 469 } 470 for _, table := range db.tables { 471 if err = table.ApplyCommit(); err != nil { 472 break 473 } 474 } 475 if db.dropEntry != nil && !db.dropEntry.Is1PC() { 476 if err = db.dropEntry.ApplyCommit(db.store.cmdMgr.MakeLogIndex(db.ddlCSN)); err != nil { 477 return 478 } 479 } 480 logutil.Debugf("Txn-%X ApplyCommit Takes %s", db.store.txn.GetID(), time.Since(now)) 481 return 482 } 483 484 func (db *txnDB) PrePrepare() (err error) { 485 for _, table := range db.tables { 486 if table.NeedRollback() { 487 if err = table.PrepareRollback(); err != nil { 488 return 489 } 490 delete(db.tables, table.GetID()) 491 } 492 } 493 for _, table := range db.tables { 494 if err = table.PrePreareTransfer(); err != nil { 495 return 496 } 497 } 498 for _, table := range db.tables { 499 if err = table.PrePrepareDedup(); err != nil { 500 return 501 } 502 } 503 for _, table := range db.tables { 504 if err = table.PrePrepare(); err != nil { 505 panic(err) 506 } 507 } 508 return 509 } 510 511 func (db *txnDB) PrepareCommit() (err error) { 512 now := time.Now() 513 if db.createEntry != nil { 514 if err = db.createEntry.PrepareCommit(); err != nil { 515 return 516 } 517 } 518 for _, table := range db.tables { 519 if err = table.PrepareCommit(); err != nil { 520 break 521 } 522 } 523 if db.dropEntry != nil { 524 if err = db.dropEntry.PrepareCommit(); err != nil { 525 return 526 } 527 } 528 529 logutil.Debugf("Txn-%X PrepareCommit Takes %s", db.store.txn.GetID(), time.Since(now)) 530 531 return 532 } 533 534 func (db *txnDB) PreApplyCommit() (err error) { 535 for _, table := range db.tables { 536 // table.ApplyAppend() 537 if err = table.PreApplyCommit(); err != nil { 538 return 539 } 540 } 541 return 542 } 543 544 func (db *txnDB) CollectCmd(cmdMgr *commandManager) (err error) { 545 if db.createEntry != nil { 546 csn := cmdMgr.GetCSN() 547 entry := db.createEntry 548 cmd, err := entry.MakeCommand(csn) 549 if err != nil { 550 panic(err) 551 } 552 cmdMgr.AddCmd(cmd) 553 db.ddlCSN = csn 554 } 555 tables := make([]*txnTable, len(db.tables)) 556 for _, table := range db.tables { 557 tables[table.idx] = table 558 } 559 for _, table := range tables { 560 if err = table.CollectCmd(cmdMgr); err != nil { 561 return 562 } 563 } 564 if db.dropEntry != nil { 565 csn := cmdMgr.GetCSN() 566 cmd, err := db.dropEntry.MakeCommand(csn) 567 if err != nil { 568 panic(err) 569 } 570 cmdMgr.AddCmd(cmd) 571 db.ddlCSN = csn 572 } 573 return 574 } 575 576 func (db *txnDB) AddTxnEntry(t txnif.TxnEntryType, entry txnif.TxnEntry) { 577 // TODO 578 } 579 580 func (db *txnDB) PrepareRollback() error { 581 var err error 582 if db.createEntry != nil { 583 if err := db.createEntry.PrepareRollback(); err != nil { 584 return err 585 } 586 } 587 for _, table := range db.tables { 588 if err = table.PrepareRollback(); err != nil { 589 break 590 } 591 } 592 if db.dropEntry != nil { 593 if err := db.dropEntry.PrepareRollback(); err != nil { 594 return err 595 } 596 } 597 598 return err 599 }