github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/db/replay.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 db 16 17 import ( 18 "bytes" 19 20 //"fmt" 21 22 "github.com/matrixorigin/matrixone/pkg/common/moerr" 23 "github.com/matrixorigin/matrixone/pkg/container/types" 24 25 "sync" 26 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 28 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 29 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/store" 30 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables" 31 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 32 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnimpl" 33 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal" 34 ) 35 36 type Replayer struct { 37 DataFactory *tables.DataFactory 38 db *DB 39 maxTs types.TS 40 staleIndexes []*wal.Index 41 once sync.Once 42 ckpedTS types.TS 43 } 44 45 func newReplayer(dataFactory *tables.DataFactory, db *DB, ckpedTS types.TS) *Replayer { 46 return &Replayer{ 47 DataFactory: dataFactory, 48 db: db, 49 staleIndexes: make([]*wal.Index, 0), 50 ckpedTS: ckpedTS, 51 } 52 } 53 54 func (replayer *Replayer) PreReplayWal() { 55 processor := new(catalog.LoopProcessor) 56 processor.BlockFn = func(entry *catalog.BlockEntry) (err error) { 57 entry.InitData(replayer.DataFactory) 58 return 59 } 60 processor.SegmentFn = func(entry *catalog.SegmentEntry) (err error) { 61 if entry.GetTable().IsVirtual() { 62 return moerr.GetOkStopCurrRecur() 63 } 64 dropCommit := entry.TreeMaxDropCommitEntry() 65 if dropCommit != nil && dropCommit.GetLogIndex().LSN <= replayer.db.Wal.GetCheckpointed() { 66 return moerr.GetOkStopCurrRecur() 67 } 68 entry.InitData(replayer.DataFactory) 69 return 70 } 71 if err := replayer.db.Catalog.RecurLoop(processor); err != nil { 72 if !moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) { 73 panic(err) 74 } 75 } 76 } 77 78 func (replayer *Replayer) Replay() { 79 if err := replayer.db.Wal.Replay(replayer.OnReplayEntry); err != nil { 80 panic(err) 81 } 82 if _, err := replayer.db.Wal.Checkpoint(replayer.staleIndexes); err != nil { 83 panic(err) 84 } 85 } 86 87 func (replayer *Replayer) OnStaleIndex(idx *wal.Index) { 88 replayer.staleIndexes = append(replayer.staleIndexes, idx) 89 } 90 91 func (replayer *Replayer) OnReplayEntry(group uint32, lsn uint64, payload []byte, typ uint16, info any) { 92 replayer.once.Do(replayer.PreReplayWal) 93 if group != wal.GroupPrepare && group != wal.GroupC { 94 return 95 } 96 idxCtx := store.NewIndex(lsn, 0, 0) 97 r := bytes.NewBuffer(payload) 98 txnCmd, _, err := txnbase.BuildCommandFrom(r) 99 if err != nil { 100 panic(err) 101 } 102 defer txnCmd.Close() 103 replayer.OnReplayTxn(txnCmd, idxCtx, lsn) 104 if err != nil { 105 panic(err) 106 } 107 } 108 109 func (replayer *Replayer) GetMaxTS() types.TS { 110 return replayer.maxTs 111 } 112 113 func (replayer *Replayer) OnTimeStamp(ts types.TS) { 114 if ts.Greater(replayer.maxTs) { 115 replayer.maxTs = ts 116 } 117 } 118 119 func (replayer *Replayer) OnReplayTxn(cmd txnif.TxnCmd, walIdx *wal.Index, lsn uint64) { 120 var err error 121 txnCmd := cmd.(*txnbase.TxnCmd) 122 if txnCmd.PrepareTS.LessEq(replayer.maxTs) { 123 return 124 } 125 txn := txnimpl.MakeReplayTxn(replayer.db.TxnMgr, txnCmd.TxnCtx, lsn, 126 txnCmd, replayer, replayer.db.Catalog, replayer.DataFactory, replayer.db.Wal) 127 if err = replayer.db.TxnMgr.OnReplayTxn(txn); err != nil { 128 panic(err) 129 } 130 if txn.Is2PC() { 131 if _, err = txn.Prepare(); err != nil { 132 panic(err) 133 } 134 } else { 135 if err = txn.Commit(); err != nil { 136 panic(err) 137 } 138 } 139 }