github.com/matrixorigin/matrixone@v1.2.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 "context" 19 "runtime/trace" 20 "sync" 21 "sync/atomic" 22 "time" 23 24 v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" 25 26 "github.com/matrixorigin/matrixone/pkg/perfcounter" 27 "go.uber.org/zap" 28 29 "github.com/matrixorigin/matrixone/pkg/common/moerr" 30 "github.com/matrixorigin/matrixone/pkg/common/moprobe" 31 "github.com/matrixorigin/matrixone/pkg/logutil" 32 "github.com/matrixorigin/matrixone/pkg/objectio" 33 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 34 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 35 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" 36 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/db/dbutils" 37 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle" 38 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 39 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/entry" 40 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables" 41 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables/updates" 42 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 43 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal" 44 ) 45 46 var ( 47 _tracerPool = sync.Pool{ 48 New: func() any { 49 return &txnTracer{} 50 }, 51 } 52 ) 53 54 func getTracer() *txnTracer { 55 return _tracerPool.Get().(*txnTracer) 56 } 57 58 func putTracer(tracer *txnTracer) { 59 tracer.task = nil 60 tracer.state = 0 61 _tracerPool.Put(tracer) 62 } 63 64 type txnTracer struct { 65 state uint8 66 task *trace.Task 67 stamp time.Time 68 } 69 70 func (tracer *txnTracer) Trigger(state uint8) { 71 switch state { 72 case 0: // start preparing wait 73 _, tracer.task = trace.NewTask(context.Background(), "1-PreparingWait") 74 tracer.stamp = time.Now() 75 tracer.state = 0 76 77 case 1: // end preparing wait and start preparing 78 if tracer.task != nil && tracer.state == 0 { 79 tracer.task.End() 80 v2.TxnPreparingWaitDurationHistogram.Observe(time.Since(tracer.stamp).Seconds()) 81 } 82 _, tracer.task = trace.NewTask(context.Background(), "2-Preparing") 83 tracer.stamp = time.Now() 84 tracer.state = 1 85 86 case 2: // end preparing and start prepare wal wait 87 if tracer.task != nil && tracer.state == 1 { 88 tracer.task.End() 89 v2.TxnPreparingDurationHistogram.Observe(time.Since(tracer.stamp).Seconds()) 90 } 91 _, tracer.task = trace.NewTask(context.Background(), "3-PrepareWalWait") 92 tracer.stamp = time.Now() 93 tracer.state = 2 94 95 case 3: // end prepare wal wait and start prepare wal 96 if tracer.task != nil && tracer.state == 2 { 97 tracer.task.End() 98 v2.TxnPrepareWalWaitDurationHistogram.Observe(time.Since(tracer.stamp).Seconds()) 99 } 100 _, tracer.task = trace.NewTask(context.Background(), "4-PrepareWal") 101 tracer.stamp = time.Now() 102 tracer.state = 3 103 104 case 4: // end prepare wal and start prepared wait 105 if tracer.task != nil && tracer.state == 3 { 106 tracer.task.End() 107 v2.TxnPrepareWalDurationHistogram.Observe(time.Since(tracer.stamp).Seconds()) 108 } 109 _, tracer.task = trace.NewTask(context.Background(), "5-PreparedWait") 110 tracer.stamp = time.Now() 111 tracer.state = 4 112 113 case 5: // end prepared wait and start prepared 114 if tracer.task != nil && tracer.state == 4 { 115 tracer.task.End() 116 v2.TxnPreparedWaitDurationHistogram.Observe(time.Since(tracer.stamp).Seconds()) 117 } 118 _, tracer.task = trace.NewTask(context.Background(), "6-Prepared") 119 tracer.stamp = time.Now() 120 tracer.state = 5 121 } 122 } 123 124 func (tracer *txnTracer) Stop() { 125 if tracer.task != nil && tracer.state == 5 { 126 tracer.task.End() 127 v2.TxnPreparedDurationHistogram.Observe(time.Since(tracer.stamp).Seconds()) 128 } 129 tracer.task = nil 130 tracer.state = 0 131 } 132 133 type txnStore struct { 134 ctx context.Context 135 txnbase.NoopTxnStore 136 mu sync.RWMutex 137 rt *dbutils.Runtime 138 dbs map[uint64]*txnDB 139 driver wal.Driver 140 txn txnif.AsyncTxn 141 catalog *catalog.Catalog 142 cmdMgr *commandManager 143 logs []entry.Entry 144 warChecker *warChecker 145 dataFactory *tables.DataFactory 146 writeOps atomic.Uint32 147 tracer *txnTracer 148 149 wg sync.WaitGroup 150 } 151 152 var TxnStoreFactory = func( 153 ctx context.Context, 154 catalog *catalog.Catalog, 155 driver wal.Driver, 156 rt *dbutils.Runtime, 157 dataFactory *tables.DataFactory, 158 maxMessageSize uint64) txnbase.TxnStoreFactory { 159 return func() txnif.TxnStore { 160 return newStore(ctx, catalog, driver, rt, dataFactory, maxMessageSize) 161 } 162 } 163 164 func newStore( 165 ctx context.Context, 166 catalog *catalog.Catalog, 167 driver wal.Driver, 168 rt *dbutils.Runtime, 169 dataFactory *tables.DataFactory, 170 maxMessageSize uint64) *txnStore { 171 return &txnStore{ 172 ctx: ctx, 173 rt: rt, 174 dbs: make(map[uint64]*txnDB), 175 catalog: catalog, 176 cmdMgr: newCommandManager(driver, maxMessageSize), 177 driver: driver, 178 logs: make([]entry.Entry, 0), 179 dataFactory: dataFactory, 180 wg: sync.WaitGroup{}, 181 } 182 } 183 184 func (store *txnStore) StartTrace() { 185 if store.IsReadonly() || store.GetTransactionType() == txnif.TxnType_Heartbeat { 186 return 187 } 188 store.tracer = getTracer() 189 store.tracer.Trigger(txnif.TraceStart) 190 } 191 192 func (store *txnStore) EndTrace() { 193 if store.tracer == nil { 194 return 195 } 196 tracer := store.tracer 197 store.tracer = nil 198 tracer.Stop() 199 putTracer(tracer) 200 } 201 202 func (store *txnStore) TriggerTrace(state uint8) { 203 if store.tracer == nil { 204 return 205 } 206 store.tracer.Trigger(state) 207 } 208 209 func (store *txnStore) GetContext() context.Context { return store.ctx } 210 func (store *txnStore) SetContext(ctx context.Context) { store.ctx = ctx } 211 212 func (store *txnStore) IsReadonly() bool { 213 return store.writeOps.Load() == 0 214 } 215 216 func (store *txnStore) IncreateWriteCnt() int { 217 return int(store.writeOps.Add(1)) 218 } 219 220 func (store *txnStore) LogTxnEntry(dbId uint64, tableId uint64, entry txnif.TxnEntry, readed []*common.ID) (err error) { 221 db, err := store.getOrSetDB(dbId) 222 if err != nil { 223 return 224 } 225 return db.LogTxnEntry(tableId, entry, readed) 226 } 227 228 func (store *txnStore) LogTxnState(sync bool) (logEntry entry.Entry, err error) { 229 cmd := txnbase.NewTxnStateCmd( 230 store.txn.GetID(), 231 store.txn.GetTxnState(false), 232 store.txn.GetCommitTS(), 233 ) 234 var buf []byte 235 if buf, err = cmd.MarshalBinary(); err != nil { 236 return 237 } 238 logEntry = entry.GetBase() 239 logEntry.SetType(IOET_WALEntry_TxnRecord) 240 if err = logEntry.SetPayload(buf); err != nil { 241 return 242 } 243 info := &entry.Info{ 244 Group: wal.GroupC, 245 } 246 logEntry.SetInfo(info) 247 var lsn uint64 248 lsn, err = store.driver.AppendEntry(wal.GroupC, logEntry) 249 if err != nil { 250 return 251 } 252 if sync { 253 err = logEntry.WaitDone() 254 } 255 logutil.Debugf("LogTxnState LSN=%d, Size=%d", lsn, len(buf)) 256 return 257 } 258 259 func (store *txnStore) Close() error { 260 var err error 261 for _, db := range store.dbs { 262 if err = db.Close(); err != nil { 263 break 264 } 265 } 266 store.dbs = nil 267 store.cmdMgr = nil 268 store.logs = nil 269 store.warChecker = nil 270 return err 271 } 272 273 func (store *txnStore) BindTxn(txn txnif.AsyncTxn) { 274 store.txn = txn 275 } 276 277 func (store *txnStore) BatchDedup(dbId, id uint64, pk containers.Vector) (err error) { 278 db, err := store.getOrSetDB(dbId) 279 if err != nil { 280 return err 281 } 282 // if table.IsDeleted() { 283 // return txnbase.ErrNotFound 284 // } 285 286 return db.BatchDedup(id, pk) 287 } 288 289 func (store *txnStore) Append(ctx context.Context, dbId, id uint64, data *containers.Batch) error { 290 store.IncreateWriteCnt() 291 db, err := store.getOrSetDB(dbId) 292 if err != nil { 293 return err 294 } 295 // if db.IsDeleted() { 296 // return txnbase.ErrNotFound 297 // } 298 return db.Append(ctx, id, data) 299 } 300 301 func (store *txnStore) AddObjsWithMetaLoc( 302 ctx context.Context, 303 dbId, tid uint64, 304 stats containers.Vector, 305 ) error { 306 store.IncreateWriteCnt() 307 db, err := store.getOrSetDB(dbId) 308 if err != nil { 309 return err 310 } 311 return db.AddObjsWithMetaLoc(ctx, tid, stats) 312 } 313 314 func (store *txnStore) RangeDelete( 315 id *common.ID, start, end uint32, 316 pkVec containers.Vector, dt handle.DeleteType, 317 ) (err error) { 318 db, err := store.getOrSetDB(id.DbID) 319 if err != nil { 320 return err 321 } 322 return db.RangeDelete(id, start, end, pkVec, dt) 323 } 324 325 func (store *txnStore) TryDeleteByDeltaloc( 326 id *common.ID, deltaloc objectio.Location, 327 ) (ok bool, err error) { 328 db, err := store.getOrSetDB(id.DbID) 329 if err != nil { 330 return 331 } 332 return db.TryDeleteByDeltaloc(id, deltaloc) 333 } 334 335 func (store *txnStore) UpdateDeltaLoc(id *common.ID, deltaLoc objectio.Location) (err error) { 336 store.IncreateWriteCnt() 337 db, err := store.getOrSetDB(id.DbID) 338 if err != nil { 339 return err 340 } 341 // if table.IsDeleted() { 342 // return txnbase.ErrNotFound 343 // } 344 return db.UpdateDeltaLoc(id, deltaLoc) 345 } 346 347 func (store *txnStore) GetByFilter(ctx context.Context, dbId, tid uint64, filter *handle.Filter) (id *common.ID, offset uint32, err error) { 348 db, err := store.getOrSetDB(dbId) 349 if err != nil { 350 return 351 } 352 // if table.IsDeleted() { 353 // err = txnbase.ErrNotFound 354 // return 355 // } 356 return db.GetByFilter(ctx, tid, filter) 357 } 358 359 func (store *txnStore) GetValue(id *common.ID, row uint32, colIdx uint16) (v any, isNull bool, err error) { 360 db, err := store.getOrSetDB(id.DbID) 361 if err != nil { 362 return 363 } 364 // if table.IsDeleted() { 365 // err = txnbase.ErrNotFound 366 // return 367 // } 368 return db.GetValue(id, row, colIdx) 369 } 370 371 func (store *txnStore) DatabaseNames() (names []string) { 372 it := newDBIt(store.txn, store.catalog) 373 for it.Valid() { 374 names = append(names, it.GetCurr().GetName()) 375 it.Next() 376 } 377 return 378 } 379 380 func (store *txnStore) UseDatabase(name string) (err error) { 381 return err 382 } 383 384 func (store *txnStore) UnsafeGetDatabase(id uint64) (h handle.Database, err error) { 385 meta, err := store.catalog.GetDatabaseByID(id) 386 if err != nil { 387 return 388 } 389 var db *txnDB 390 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 391 return 392 } 393 h = buildDB(db) 394 return 395 } 396 397 func (store *txnStore) GetDatabase(name string) (h handle.Database, err error) { 398 defer func() { 399 if err == moerr.GetOkExpectedEOB() { 400 err = moerr.NewBadDBNoCtx(name) 401 } 402 }() 403 meta, err := store.catalog.TxnGetDBEntryByName(name, store.txn) 404 if err != nil { 405 return 406 } 407 var db *txnDB 408 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 409 return 410 } 411 h = buildDB(db) 412 return 413 } 414 415 func (store *txnStore) GetDatabaseByID(id uint64) (h handle.Database, err error) { 416 meta, err := store.catalog.TxnGetDBEntryByID(id, store.txn) 417 if err != nil { 418 return 419 } 420 var db *txnDB 421 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 422 return 423 } 424 h = buildDB(db) 425 return 426 } 427 428 func (store *txnStore) CreateDatabase(name, createSql, datTyp string) (h handle.Database, err error) { 429 meta, err := store.catalog.CreateDBEntry(name, createSql, datTyp, store.txn) 430 if err != nil { 431 return nil, err 432 } 433 var db *txnDB 434 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 435 return 436 } 437 if err = db.SetCreateEntry(meta); err != nil { 438 return 439 } 440 h = buildDB(db) 441 return 442 } 443 444 func (store *txnStore) CreateDatabaseWithID(name, createSql, datTyp string, id uint64) (h handle.Database, err error) { 445 meta, err := store.catalog.CreateDBEntryWithID(name, createSql, datTyp, id, store.txn) 446 if err != nil { 447 return nil, err 448 } 449 var db *txnDB 450 if db, err = store.getOrSetDB(meta.GetID()); err != nil { 451 return 452 } 453 if err = db.SetCreateEntry(meta); err != nil { 454 return 455 } 456 h = buildDB(db) 457 return 458 } 459 460 func (store *txnStore) DropDatabase(name string) (h handle.Database, err error) { 461 hasNewEntry, meta, err := store.catalog.DropDBEntryByName(name, store.txn) 462 if err != nil { 463 return 464 } 465 db, err := store.getOrSetDB(meta.GetID()) 466 if err != nil { 467 return 468 } 469 if hasNewEntry { 470 if err = db.SetDropEntry(meta); err != nil { 471 return 472 } 473 } 474 h = buildDB(db) 475 return 476 } 477 478 func (store *txnStore) ObserveTxn( 479 visitDatabase func(db any), 480 visitTable func(tbl any), 481 rotateTable func(dbName, tblName string, dbid, tid uint64), 482 visitMetadata func(block any), 483 visitObject func(obj any), 484 visitAppend func(bat any), 485 visitDelete func(ctx context.Context, vnode txnif.DeleteNode)) { 486 for _, db := range store.dbs { 487 if db.createEntry != nil || db.dropEntry != nil { 488 visitDatabase(db.entry) 489 } 490 dbName := db.entry.GetName() 491 dbid := db.entry.ID 492 for _, tbl := range db.tables { 493 tblName := tbl.GetLocalSchema().Name 494 tid := tbl.entry.ID 495 rotateTable(dbName, tblName, dbid, tid) 496 if tbl.createEntry != nil || tbl.dropEntry != nil { 497 visitTable(tbl.entry) 498 } 499 for _, iTxnEntry := range tbl.txnEntries.entries { 500 switch txnEntry := iTxnEntry.(type) { 501 case *catalog.ObjectEntry: 502 visitObject(txnEntry) 503 case *updates.DeltalocChain: 504 visitMetadata(txnEntry) 505 case *updates.DeleteNode: 506 visitDelete(store.ctx, txnEntry) 507 case *catalog.TableEntry: 508 if tbl.createEntry != nil || tbl.dropEntry != nil { 509 continue 510 } 511 visitTable(txnEntry) 512 } 513 } 514 if tbl.tableSpace != nil { 515 for _, node := range tbl.tableSpace.nodes { 516 anode, ok := node.(*anode) 517 if ok { 518 schema := anode.table.GetLocalSchema() 519 bat := &containers.BatchWithVersion{ 520 Version: schema.Version, 521 NextSeqnum: uint16(schema.Extra.NextColSeqnum), 522 Seqnums: schema.AllSeqnums(), 523 Batch: anode.data, 524 } 525 visitAppend(bat) 526 } 527 } 528 } 529 } 530 } 531 } 532 func (store *txnStore) AddWaitEvent(cnt int) { 533 store.wg.Add(cnt) 534 } 535 func (store *txnStore) DoneWaitEvent(cnt int) { 536 store.wg.Add(-cnt) 537 } 538 func (store *txnStore) DropDatabaseByID(id uint64) (h handle.Database, err error) { 539 hasNewEntry, meta, err := store.catalog.DropDBEntryByID(id, store.txn) 540 if err != nil { 541 return 542 } 543 db, err := store.getOrSetDB(meta.GetID()) 544 if err != nil { 545 return 546 } 547 if hasNewEntry { 548 if err = db.SetDropEntry(meta); err != nil { 549 return 550 } 551 } 552 h = buildDB(db) 553 return 554 } 555 556 func (store *txnStore) CreateRelation(dbId uint64, def any) (relation handle.Relation, err error) { 557 db, err := store.getOrSetDB(dbId) 558 if err != nil { 559 return 560 } 561 return db.CreateRelation(def) 562 } 563 564 func (store *txnStore) CreateRelationWithTableId(dbId uint64, tableId uint64, def any) (relation handle.Relation, err error) { 565 db, err := store.getOrSetDB(dbId) 566 if err != nil { 567 return 568 } 569 return db.CreateRelationWithTableId(tableId, def) 570 } 571 572 func (store *txnStore) DropRelationByName(dbId uint64, name string) (relation handle.Relation, err error) { 573 db, err := store.getOrSetDB(dbId) 574 if err != nil { 575 return nil, err 576 } 577 return db.DropRelationByName(name) 578 } 579 580 func (store *txnStore) DropRelationByID(dbId uint64, id uint64) (relation handle.Relation, err error) { 581 db, err := store.getOrSetDB(dbId) 582 if err != nil { 583 return nil, err 584 } 585 return db.DropRelationByID(id) 586 } 587 588 func (store *txnStore) UnsafeGetRelation(dbId, id uint64) (relation handle.Relation, err error) { 589 db, err := store.getOrSetDB(dbId) 590 if err != nil { 591 return nil, err 592 } 593 return db.UnsafeGetRelation(id) 594 } 595 596 func (store *txnStore) GetRelationByName(dbId uint64, name string) (relation handle.Relation, err error) { 597 db, err := store.getOrSetDB(dbId) 598 if err != nil { 599 return nil, err 600 } 601 return db.GetRelationByName(name) 602 } 603 604 func (store *txnStore) GetRelationByID(dbId uint64, id uint64) (relation handle.Relation, err error) { 605 db, err := store.getOrSetDB(dbId) 606 if err != nil { 607 return nil, err 608 } 609 return db.GetRelationByID(id) 610 } 611 612 func (store *txnStore) GetObject(id *common.ID) (obj handle.Object, err error) { 613 var db *txnDB 614 if db, err = store.getOrSetDB(id.DbID); err != nil { 615 return 616 } 617 return db.GetObject(id) 618 } 619 620 func (store *txnStore) CreateObject(dbId, tid uint64, is1PC bool) (obj handle.Object, err error) { 621 var db *txnDB 622 if db, err = store.getOrSetDB(dbId); err != nil { 623 return 624 } 625 return db.CreateObject(tid, is1PC) 626 } 627 628 func (store *txnStore) CreateNonAppendableObject(dbId, tid uint64, is1PC bool, opt *objectio.CreateObjOpt) (obj handle.Object, err error) { 629 var db *txnDB 630 if db, err = store.getOrSetDB(dbId); err != nil { 631 return 632 } 633 return db.CreateNonAppendableObject(tid, is1PC, opt) 634 } 635 636 func (store *txnStore) getOrSetDB(id uint64) (db *txnDB, err error) { 637 store.mu.RLock() 638 db = store.dbs[id] 639 store.mu.RUnlock() 640 if db != nil { 641 return 642 } 643 var entry *catalog.DBEntry 644 if entry, err = store.catalog.GetDatabaseByID(id); err != nil { 645 return 646 } 647 store.mu.Lock() 648 defer store.mu.Unlock() 649 db = store.dbs[id] 650 if db != nil { 651 return 652 } 653 db = newTxnDB(store, entry) 654 db.idx = len(store.dbs) 655 store.dbs[id] = db 656 return 657 } 658 func (store *txnStore) UpdateObjectStats(id *common.ID, stats *objectio.ObjectStats) error { 659 db, err := store.getOrSetDB(id.DbID) 660 if err != nil { 661 return err 662 } 663 db.UpdateObjectStats(id, stats) 664 return nil 665 } 666 667 func (store *txnStore) SoftDeleteObject(id *common.ID) (err error) { 668 var db *txnDB 669 if db, err = store.getOrSetDB(id.DbID); err != nil { 670 return 671 } 672 perfcounter.Update(store.ctx, func(counter *perfcounter.CounterSet) { 673 counter.TAE.Object.SoftDelete.Add(1) 674 }) 675 return db.SoftDeleteObject(id) 676 } 677 678 func (store *txnStore) ApplyRollback() (err error) { 679 if store.cmdMgr.GetCSN() != 0 { 680 for _, db := range store.dbs { 681 if err = db.ApplyRollback(); err != nil { 682 break 683 } 684 } 685 } 686 store.CleanUp() 687 return 688 } 689 690 func (store *txnStore) WaitPrepared(ctx context.Context) (err error) { 691 for _, db := range store.dbs { 692 if err = db.WaitPrepared(); err != nil { 693 return 694 } 695 } 696 moprobe.WithRegion(ctx, moprobe.TxnStoreWaitWALFlush, func() { 697 for _, e := range store.logs { 698 if err = e.WaitDone(); err != nil { 699 break 700 } 701 e.Free() 702 } 703 }) 704 store.wg.Wait() 705 return 706 } 707 708 func (store *txnStore) ApplyCommit() (err error) { 709 for _, db := range store.dbs { 710 if err = db.ApplyCommit(); err != nil { 711 break 712 } 713 } 714 store.CleanUp() 715 return 716 } 717 718 func (store *txnStore) Freeze() (err error) { 719 for _, db := range store.dbs { 720 if db.NeedRollback() { 721 if err = db.PrepareRollback(); err != nil { 722 return 723 } 724 delete(store.dbs, db.entry.GetID()) 725 } 726 if err = db.Freeze(); err != nil { 727 return 728 } 729 } 730 return 731 } 732 733 func (store *txnStore) PrePrepare(ctx context.Context) (err error) { 734 for _, db := range store.dbs { 735 if err = db.PrePrepare(ctx); err != nil { 736 return 737 } 738 } 739 return 740 } 741 742 func (store *txnStore) PrepareCommit() (err error) { 743 if store.warChecker != nil { 744 if err = store.warChecker.checkAll( 745 store.txn.GetPrepareTS()); err != nil { 746 return err 747 } 748 } 749 for _, db := range store.dbs { 750 if err = db.PrepareCommit(); err != nil { 751 break 752 } 753 } 754 755 return 756 } 757 758 func (store *txnStore) PreApplyCommit() (err error) { 759 for _, db := range store.dbs { 760 if err = db.PreApplyCommit(); err != nil { 761 return 762 } 763 } 764 // logutil.Debugf("Txn-%X PrepareCommit Takes %s", store.txn.GetID(), time.Since(now)) 765 return 766 } 767 768 func (store *txnStore) PrepareWAL() (err error) { 769 if err = store.CollectCmd(); err != nil { 770 return 771 } 772 773 if store.cmdMgr.GetCSN() == 0 { 774 return 775 } 776 777 // Apply the record from the command list. 778 // Split the commands by max message size. 779 for store.cmdMgr.cmd.MoreCmds() { 780 logEntry, err := store.cmdMgr.ApplyTxnRecord(store.txn) 781 if err != nil { 782 return err 783 } 784 if logEntry != nil { 785 store.logs = append(store.logs, logEntry) 786 } 787 } 788 789 t1 := time.Now() 790 for _, db := range store.dbs { 791 if err = db.Apply1PCCommit(); err != nil { 792 return 793 } 794 } 795 t2 := time.Now() 796 if t2.Sub(t1) > time.Millisecond*500 { 797 logutil.Warn( 798 "SLOW-LOG", 799 zap.String("txn", store.txn.String()), 800 zap.Duration("apply-1pc-commit-duration", t2.Sub(t1)), 801 ) 802 } 803 return 804 } 805 806 func (store *txnStore) CollectCmd() (err error) { 807 dbs := make([]*txnDB, len(store.dbs)) 808 for _, db := range store.dbs { 809 dbs[db.idx] = db 810 } 811 for _, db := range dbs { 812 if err = db.CollectCmd(store.cmdMgr); err != nil { 813 return 814 } 815 } 816 return 817 } 818 819 func (store *txnStore) AddTxnEntry(t txnif.TxnEntryType, entry txnif.TxnEntry) { 820 // TODO 821 } 822 823 func (store *txnStore) PrepareRollback() error { 824 var err error 825 for _, db := range store.dbs { 826 if err = db.PrepareRollback(); err != nil { 827 break 828 } 829 } 830 831 return err 832 } 833 834 func (store *txnStore) GetLSN() uint64 { return store.cmdMgr.lsn } 835 836 func (store *txnStore) CleanUp() { 837 for _, db := range store.dbs { 838 db.CleanUp() 839 } 840 }