github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/store.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 txnimpl 16 17 import ( 18 "sync" 19 "sync/atomic" 20 "time" 21 22 "github.com/matrixorigin/matrixone/pkg/common/moerr" 23 "github.com/matrixorigin/matrixone/pkg/logutil" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/buffer/base" 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/iface/handle" 29 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 30 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/entry" 31 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model" 32 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables" 33 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 34 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal" 35 ) 36 37 type txnStore struct { 38 txnbase.NoopTxnStore 39 mu sync.RWMutex 40 transferTable *model.HashPageTable 41 dbs map[uint64]*txnDB 42 driver wal.Driver 43 nodesMgr base.INodeManager 44 txn txnif.AsyncTxn 45 catalog *catalog.Catalog 46 cmdMgr *commandManager 47 logs []entry.Entry 48 warChecker *warChecker 49 dataFactory *tables.DataFactory 50 writeOps atomic.Uint32 51 } 52 53 var TxnStoreFactory = func( 54 catalog *catalog.Catalog, 55 driver wal.Driver, 56 transferTable *model.HashPageTable, 57 txnBufMgr base.INodeManager, 58 dataFactory *tables.DataFactory) txnbase.TxnStoreFactory { 59 return func() txnif.TxnStore { 60 return newStore(catalog, driver, transferTable, txnBufMgr, dataFactory) 61 } 62 } 63 64 func newStore( 65 catalog *catalog.Catalog, 66 driver wal.Driver, 67 transferTable *model.HashPageTable, 68 txnBufMgr base.INodeManager, 69 dataFactory *tables.DataFactory) *txnStore { 70 return &txnStore{ 71 transferTable: transferTable, 72 dbs: make(map[uint64]*txnDB), 73 catalog: catalog, 74 cmdMgr: newCommandManager(driver), 75 driver: driver, 76 logs: make([]entry.Entry, 0), 77 dataFactory: dataFactory, 78 nodesMgr: txnBufMgr, 79 } 80 } 81 82 func (store *txnStore) IsReadonly() bool { 83 return store.writeOps.Load() == 0 84 } 85 86 func (store *txnStore) IncreateWriteCnt() int { 87 return int(store.writeOps.Add(1)) 88 } 89 90 func (store *txnStore) LogTxnEntry(dbId uint64, tableId uint64, entry txnif.TxnEntry, readed []*common.ID) (err error) { 91 db, err := store.getOrSetDB(dbId) 92 if err != nil { 93 return 94 } 95 return db.LogTxnEntry(tableId, entry, readed) 96 } 97 98 func (store *txnStore) LogTxnState(sync bool) (logEntry entry.Entry, err error) { 99 cmd := txnbase.NewTxnStateCmd( 100 store.txn.GetID(), 101 store.txn.GetTxnState(false), 102 store.txn.GetCommitTS(), 103 ) 104 var buf []byte 105 if buf, err = cmd.Marshal(); err != nil { 106 return 107 } 108 logEntry = entry.GetBase() 109 logEntry.SetType(ETTxnState) 110 if err = logEntry.SetPayload(buf); err != nil { 111 return 112 } 113 info := &entry.Info{ 114 Group: wal.GroupC, 115 TxnId: store.txn.GetID(), 116 } 117 logEntry.SetInfo(info) 118 var lsn uint64 119 lsn, err = store.driver.AppendEntry(wal.GroupC, logEntry) 120 if err != nil { 121 return 122 } 123 if sync { 124 err = logEntry.WaitDone() 125 } 126 logutil.Debugf("LogTxnState LSN=%d, Size=%d", lsn, len(buf)) 127 return 128 } 129 130 func (store *txnStore) LogSegmentID(dbId, tid, sid uint64) { 131 db, _ := store.getOrSetDB(dbId) 132 db.LogSegmentID(tid, sid) 133 } 134 135 func (store *txnStore) LogBlockID(dbId, tid, bid uint64) { 136 db, _ := store.getOrSetDB(dbId) 137 db.LogBlockID(tid, bid) 138 } 139 140 func (store *txnStore) Close() error { 141 var err error 142 for _, db := range store.dbs { 143 if err = db.Close(); err != nil { 144 break 145 } 146 } 147 store.dbs = nil 148 store.cmdMgr = nil 149 store.logs = nil 150 store.warChecker = nil 151 return err 152 } 153 154 func (store *txnStore) BindTxn(txn txnif.AsyncTxn) { 155 store.txn = txn 156 } 157 158 func (store *txnStore) BatchDedup(dbId, id uint64, pk containers.Vector) (err error) { 159 db, err := store.getOrSetDB(dbId) 160 if err != nil { 161 return err 162 } 163 // if table.IsDeleted() { 164 // return txnbase.ErrNotFound 165 // } 166 167 return db.BatchDedup(id, pk) 168 } 169 170 func (store *txnStore) Append(dbId, id uint64, data *containers.Batch) error { 171 store.IncreateWriteCnt() 172 db, err := store.getOrSetDB(dbId) 173 if err != nil { 174 return err 175 } 176 // if db.IsDeleted() { 177 // return txnbase.ErrNotFound 178 // } 179 return db.Append(id, data) 180 } 181 182 func (store *txnStore) AddBlksWithMetaLoc( 183 dbId, tid uint64, 184 pkVecs []containers.Vector, 185 file string, 186 metaLoc []string, 187 flag int32, 188 ) error { 189 store.IncreateWriteCnt() 190 db, err := store.getOrSetDB(dbId) 191 if err != nil { 192 return err 193 } 194 return db.AddBlksWithMetaLoc(tid, pkVecs, file, metaLoc, flag) 195 } 196 197 func (store *txnStore) RangeDelete(dbId uint64, id *common.ID, start, end uint32, dt handle.DeleteType) (err error) { 198 db, err := store.getOrSetDB(dbId) 199 if err != nil { 200 return err 201 } 202 return db.RangeDelete(id, start, end, dt) 203 } 204 205 func (store *txnStore) UpdateMetaLoc(dbId uint64, id *common.ID, metaLoc string) (err error) { 206 db, err := store.getOrSetDB(dbId) 207 if err != nil { 208 return err 209 } 210 // if table.IsDeleted() { 211 // return txnbase.ErrNotFound 212 // } 213 return db.UpdateMetaLoc(id, metaLoc) 214 } 215 216 func (store *txnStore) UpdateDeltaLoc(dbId uint64, id *common.ID, deltaLoc string) (err error) { 217 db, err := store.getOrSetDB(dbId) 218 if err != nil { 219 return err 220 } 221 // if table.IsDeleted() { 222 // return txnbase.ErrNotFound 223 // } 224 return db.UpdateDeltaLoc(id, deltaLoc) 225 } 226 227 func (store *txnStore) GetByFilter(dbId, tid uint64, filter *handle.Filter) (id *common.ID, offset uint32, err error) { 228 db, err := store.getOrSetDB(dbId) 229 if err != nil { 230 return 231 } 232 // if table.IsDeleted() { 233 // err = txnbase.ErrNotFound 234 // return 235 // } 236 return db.GetByFilter(tid, filter) 237 } 238 239 func (store *txnStore) GetValue(dbId uint64, id *common.ID, row uint32, colIdx uint16) (v any, err error) { 240 db, err := store.getOrSetDB(dbId) 241 if err != nil { 242 return 243 } 244 // if table.IsDeleted() { 245 // err = txnbase.ErrNotFound 246 // return 247 // } 248 return db.GetValue(id, row, colIdx) 249 } 250 251 func (store *txnStore) DatabaseNames() (names []string) { 252 it := newDBIt(store.txn, store.catalog) 253 for it.Valid() { 254 names = append(names, it.GetCurr().GetName()) 255 it.Next() 256 } 257 return 258 } 259 260 func (store *txnStore) UseDatabase(name string) (err error) { 261 return err 262 } 263 264 func (store *txnStore) UnsafeGetDatabase(id uint64) (h handle.Database, err error) { 265 meta, err := store.catalog.GetDatabaseByID(id) 266 if err != nil { 267 return 268 } 269 var db *txnDB 270 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 271 return 272 } 273 h = buildDB(db) 274 return 275 } 276 277 func (store *txnStore) GetDatabase(name string) (h handle.Database, err error) { 278 defer func() { 279 if err == moerr.GetOkExpectedEOB() { 280 err = moerr.NewBadDBNoCtx(name) 281 } 282 }() 283 meta, err := store.catalog.TxnGetDBEntryByName(name, store.txn) 284 if err != nil { 285 return 286 } 287 var db *txnDB 288 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 289 return 290 } 291 h = buildDB(db) 292 return 293 } 294 295 func (store *txnStore) GetDatabaseByID(id uint64) (h handle.Database, err error) { 296 meta, err := store.catalog.TxnGetDBEntryByID(id, store.txn) 297 if err != nil { 298 return 299 } 300 var db *txnDB 301 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 302 return 303 } 304 h = buildDB(db) 305 return 306 } 307 308 func (store *txnStore) CreateDatabase(name, createSql string) (h handle.Database, err error) { 309 meta, err := store.catalog.CreateDBEntry(name, createSql, store.txn) 310 if err != nil { 311 return nil, err 312 } 313 var db *txnDB 314 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 315 return 316 } 317 if err = db.SetCreateEntry(meta); err != nil { 318 return 319 } 320 h = buildDB(db) 321 return 322 } 323 324 func (store *txnStore) CreateDatabaseWithID(name, createSql string, id uint64) (h handle.Database, err error) { 325 meta, err := store.catalog.CreateDBEntryWithID(name, createSql, id, store.txn) 326 if err != nil { 327 return nil, err 328 } 329 var db *txnDB 330 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 331 return 332 } 333 if err = db.SetCreateEntry(meta); err != nil { 334 return 335 } 336 h = buildDB(db) 337 return 338 } 339 340 func (store *txnStore) DropDatabase(name string) (h handle.Database, err error) { 341 hasNewEntry, meta, err := store.catalog.DropDBEntry(name, store.txn) 342 if err != nil { 343 return 344 } 345 db, err := store.getOrSetDB(meta.GetID()) 346 if err != nil { 347 return 348 } 349 if hasNewEntry { 350 if err = db.SetDropEntry(meta); err != nil { 351 return 352 } 353 } 354 h = buildDB(db) 355 return 356 } 357 358 func (store *txnStore) DropDatabaseByID(id uint64) (h handle.Database, err error) { 359 hasNewEntry, meta, err := store.catalog.DropDBEntryByID(id, store.txn) 360 if err != nil { 361 return 362 } 363 db, err := store.getOrSetDB(meta.GetID()) 364 if err != nil { 365 return 366 } 367 if hasNewEntry { 368 if err = db.SetDropEntry(meta); err != nil { 369 return 370 } 371 } 372 h = buildDB(db) 373 return 374 } 375 376 func (store *txnStore) CreateRelation(dbId uint64, def any) (relation handle.Relation, err error) { 377 db, err := store.getOrSetDB(dbId) 378 if err != nil { 379 return 380 } 381 return db.CreateRelation(def) 382 } 383 384 func (store *txnStore) CreateRelationWithTableId(dbId uint64, tableId uint64, def any) (relation handle.Relation, err error) { 385 db, err := store.getOrSetDB(dbId) 386 if err != nil { 387 return 388 } 389 return db.CreateRelationWithTableId(tableId, def) 390 } 391 392 func (store *txnStore) DropRelationByName(dbId uint64, name string) (relation handle.Relation, err error) { 393 db, err := store.getOrSetDB(dbId) 394 if err != nil { 395 return nil, err 396 } 397 return db.DropRelationByName(name) 398 } 399 400 func (store *txnStore) DropRelationByID(dbId uint64, id uint64) (relation handle.Relation, err error) { 401 db, err := store.getOrSetDB(dbId) 402 if err != nil { 403 return nil, err 404 } 405 return db.DropRelationByID(id) 406 } 407 408 func (store *txnStore) UnsafeGetRelation(dbId, id uint64) (relation handle.Relation, err error) { 409 db, err := store.getOrSetDB(dbId) 410 if err != nil { 411 return nil, err 412 } 413 return db.UnsafeGetRelation(id) 414 } 415 416 func (store *txnStore) GetRelationByName(dbId uint64, name string) (relation handle.Relation, err error) { 417 db, err := store.getOrSetDB(dbId) 418 if err != nil { 419 return nil, err 420 } 421 return db.GetRelationByName(name) 422 } 423 424 func (store *txnStore) GetRelationByID(dbId uint64, id uint64) (relation handle.Relation, err error) { 425 db, err := store.getOrSetDB(dbId) 426 if err != nil { 427 return nil, err 428 } 429 return db.GetRelationByID(id) 430 } 431 432 func (store *txnStore) GetSegment(dbId uint64, id *common.ID) (seg handle.Segment, err error) { 433 var db *txnDB 434 if db, err = store.getOrSetDB(dbId); err != nil { 435 return 436 } 437 return db.GetSegment(id) 438 } 439 440 func (store *txnStore) CreateSegment(dbId, tid uint64, is1PC bool) (seg handle.Segment, err error) { 441 var db *txnDB 442 if db, err = store.getOrSetDB(dbId); err != nil { 443 return 444 } 445 return db.CreateSegment(tid, is1PC) 446 } 447 448 func (store *txnStore) CreateNonAppendableSegment(dbId, tid uint64, is1PC bool) (seg handle.Segment, err error) { 449 var db *txnDB 450 if db, err = store.getOrSetDB(dbId); err != nil { 451 return 452 } 453 return db.CreateNonAppendableSegment(tid, is1PC) 454 } 455 456 func (store *txnStore) getOrSetDB(id uint64) (db *txnDB, err error) { 457 store.mu.RLock() 458 db = store.dbs[id] 459 store.mu.RUnlock() 460 if db != nil { 461 return 462 } 463 var entry *catalog.DBEntry 464 if entry, err = store.catalog.GetDatabaseByID(id); err != nil { 465 return 466 } 467 store.mu.Lock() 468 defer store.mu.Unlock() 469 db = store.dbs[id] 470 if db != nil { 471 return 472 } 473 db = newTxnDB(store, entry) 474 db.idx = len(store.dbs) 475 store.dbs[id] = db 476 return 477 } 478 479 func (store *txnStore) CreateNonAppendableBlock(dbId uint64, id *common.ID) (blk handle.Block, err error) { 480 var db *txnDB 481 if db, err = store.getOrSetDB(dbId); err != nil { 482 return 483 } 484 return db.CreateNonAppendableBlock(id) 485 } 486 487 func (store *txnStore) CreateNonAppendableBlockWithMeta( 488 dbId uint64, 489 id *common.ID, 490 metaLoc string, 491 deltaLoc string) (blk handle.Block, err error) { 492 var db *txnDB 493 if db, err = store.getOrSetDB(dbId); err != nil { 494 return 495 } 496 return db.CreateNonAppendableBlockWithMeta(id, metaLoc, deltaLoc) 497 } 498 499 func (store *txnStore) GetBlock(dbId uint64, id *common.ID) (blk handle.Block, err error) { 500 var db *txnDB 501 if db, err = store.getOrSetDB(dbId); err != nil { 502 return 503 } 504 return db.GetBlock(id) 505 } 506 507 func (store *txnStore) CreateBlock(dbId, tid, sid uint64, is1PC bool) (blk handle.Block, err error) { 508 var db *txnDB 509 if db, err = store.getOrSetDB(dbId); err != nil { 510 return 511 } 512 return db.CreateBlock(tid, sid, is1PC) 513 } 514 515 func (store *txnStore) SoftDeleteBlock(dbId uint64, id *common.ID) (err error) { 516 var db *txnDB 517 if db, err = store.getOrSetDB(dbId); err != nil { 518 return 519 } 520 return db.SoftDeleteBlock(id) 521 } 522 523 func (store *txnStore) SoftDeleteSegment(dbId uint64, id *common.ID) (err error) { 524 var db *txnDB 525 if db, err = store.getOrSetDB(dbId); err != nil { 526 return 527 } 528 return db.SoftDeleteSegment(id) 529 } 530 531 func (store *txnStore) ApplyRollback() (err error) { 532 if store.cmdMgr.GetCSN() == 0 { 533 return 534 } 535 for _, db := range store.dbs { 536 if err = db.ApplyRollback(); err != nil { 537 break 538 } 539 } 540 return 541 } 542 543 func (store *txnStore) WaitPrepared() (err error) { 544 for _, db := range store.dbs { 545 if err = db.WaitPrepared(); err != nil { 546 return 547 } 548 } 549 for _, e := range store.logs { 550 if err = e.WaitDone(); err != nil { 551 break 552 } 553 e.Free() 554 } 555 return 556 } 557 558 func (store *txnStore) ApplyCommit() (err error) { 559 for _, db := range store.dbs { 560 if err = db.ApplyCommit(); err != nil { 561 break 562 } 563 } 564 return 565 } 566 567 func (store *txnStore) PrePrepare() (err error) { 568 for _, db := range store.dbs { 569 if db.NeedRollback() { 570 if err = db.PrepareRollback(); err != nil { 571 return 572 } 573 delete(store.dbs, db.entry.GetID()) 574 } 575 if err = db.PrePrepare(); err != nil { 576 return 577 } 578 } 579 return 580 } 581 582 func (store *txnStore) PrepareCommit() (err error) { 583 if store.warChecker != nil { 584 if err = store.warChecker.checkAll( 585 store.txn.GetPrepareTS()); err != nil { 586 return err 587 } 588 } 589 for _, db := range store.dbs { 590 if err = db.PrepareCommit(); err != nil { 591 break 592 } 593 } 594 595 return 596 } 597 598 func (store *txnStore) PreApplyCommit() (err error) { 599 now := time.Now() 600 for _, db := range store.dbs { 601 if err = db.PreApplyCommit(); err != nil { 602 return 603 } 604 } 605 if err = store.CollectCmd(); err != nil { 606 return 607 } 608 609 if store.cmdMgr.GetCSN() == 0 { 610 return 611 } 612 613 logEntry, err := store.cmdMgr.ApplyTxnRecord(store.txn.GetID(), store.txn) 614 if err != nil { 615 return 616 } 617 if logEntry != nil { 618 store.logs = append(store.logs, logEntry) 619 } 620 for _, db := range store.dbs { 621 if err = db.Apply1PCCommit(); err != nil { 622 return 623 } 624 } 625 logutil.Debugf("Txn-%X PrepareCommit Takes %s", store.txn.GetID(), time.Since(now)) 626 return 627 } 628 629 func (store *txnStore) CollectCmd() (err error) { 630 dbs := make([]*txnDB, len(store.dbs)) 631 for _, db := range store.dbs { 632 dbs[db.idx] = db 633 } 634 for _, db := range dbs { 635 if err = db.CollectCmd(store.cmdMgr); err != nil { 636 return 637 } 638 } 639 return 640 } 641 642 func (store *txnStore) AddTxnEntry(t txnif.TxnEntryType, entry txnif.TxnEntry) { 643 // TODO 644 } 645 646 func (store *txnStore) PrepareRollback() error { 647 var err error 648 for _, db := range store.dbs { 649 if err = db.PrepareRollback(); err != nil { 650 break 651 } 652 } 653 654 return err 655 } 656 657 func (store *txnStore) GetLSN() uint64 { return store.cmdMgr.lsn }