github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/txn/txnimpl/replaystore.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 20 "github.com/matrixorigin/matrixone/pkg/common/moerr" 21 "github.com/matrixorigin/matrixone/pkg/logutil" 22 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 23 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables/updates" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 28 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal" 29 ) 30 31 type replayTxnStore struct { 32 txnbase.NoopTxnStore 33 Cmd *txnbase.TxnCmd 34 Observer wal.ReplayObserver 35 catalog *catalog.Catalog 36 dataFactory *tables.DataFactory 37 wal wal.Driver 38 ctx context.Context 39 } 40 41 func MakeReplayTxn( 42 ctx context.Context, 43 mgr *txnbase.TxnManager, 44 txnCtx *txnbase.TxnCtx, 45 lsn uint64, 46 cmd *txnbase.TxnCmd, 47 observer wal.ReplayObserver, 48 catalog *catalog.Catalog, 49 dataFactory *tables.DataFactory, 50 wal wal.Driver) *txnbase.Txn { 51 store := &replayTxnStore{ 52 Cmd: cmd, 53 Observer: observer, 54 catalog: catalog, 55 dataFactory: dataFactory, 56 wal: wal, 57 ctx: ctx, 58 } 59 txn := txnbase.NewPersistedTxn( 60 mgr, 61 txnCtx, 62 store, 63 lsn, 64 store.prepareCommit, 65 store.prepareRollback, 66 store.applyCommit, 67 store.applyRollback) 68 return txn 69 } 70 func (store *replayTxnStore) GetContext() context.Context { 71 return store.ctx 72 } 73 func (store *replayTxnStore) IsReadonly() bool { return false } 74 75 func (store *replayTxnStore) prepareCommit(txn txnif.AsyncTxn) (err error) { 76 // PrepareCommit all commands 77 // Check idempotent of each command 78 // Record all idempotent error commands and skip apply|rollback later 79 store.Observer.OnTimeStamp(txn.GetPrepareTS()) 80 for _, command := range store.Cmd.Cmds { 81 command.SetReplayTxn(txn) 82 store.prepareCmd(command) 83 } 84 return 85 } 86 87 func (store *replayTxnStore) applyCommit(txn txnif.AsyncTxn) (err error) { 88 store.Cmd.ApplyCommit() 89 return 90 } 91 92 func (store *replayTxnStore) applyRollback(txn txnif.AsyncTxn) (err error) { 93 store.Cmd.ApplyRollback() 94 return 95 } 96 97 func (store *replayTxnStore) prepareRollback(txn txnif.AsyncTxn) (err error) { 98 panic(moerr.NewInternalErrorNoCtx("cannot prepareRollback rollback replay txn: %s", 99 txn.String())) 100 } 101 102 func (store *replayTxnStore) prepareCmd(txncmd txnif.TxnCmd) { 103 if txncmd.GetType() != txnbase.IOET_WALTxnEntry { 104 logutil.Debug("", common.OperationField("replay-cmd"), 105 common.OperandField(txncmd.Desc())) 106 } 107 var err error 108 switch cmd := txncmd.(type) { 109 case *catalog.EntryCommand[*catalog.EmptyMVCCNode, *catalog.DBNode], 110 *catalog.EntryCommand[*catalog.TableMVCCNode, *catalog.TableNode], 111 *catalog.EntryCommand[*catalog.MetadataMVCCNode, *catalog.ObjectNode], 112 *catalog.EntryCommand[*catalog.ObjectMVCCNode, *catalog.ObjectNode], 113 *catalog.EntryCommand[*catalog.MetadataMVCCNode, *catalog.BlockNode]: 114 store.catalog.ReplayCmd(txncmd, store.dataFactory, store.Observer) 115 case *AppendCmd: 116 store.replayAppendData(cmd, store.Observer) 117 case *updates.UpdateCmd: 118 store.replayDataCmds(cmd, store.Observer) 119 } 120 if err != nil { 121 panic(err) 122 } 123 } 124 125 func (store *replayTxnStore) replayAppendData(cmd *AppendCmd, observer wal.ReplayObserver) { 126 hasActive := false 127 for _, info := range cmd.Infos { 128 id := info.GetDest() 129 database, err := store.catalog.GetDatabaseByID(id.DbID) 130 if err != nil { 131 panic(err) 132 } 133 blk, err := database.GetBlockEntryByID(id) 134 if err != nil { 135 panic(err) 136 } 137 if !blk.IsActive() { 138 continue 139 } 140 if blk.ObjectPersisted() { 141 continue 142 } 143 hasActive = true 144 } 145 146 if !hasActive { 147 return 148 } 149 150 data := cmd.Data 151 if data != nil { 152 defer data.Close() 153 } 154 155 for _, info := range cmd.Infos { 156 id := info.GetDest() 157 database, err := store.catalog.GetDatabaseByID(id.DbID) 158 if err != nil { 159 panic(err) 160 } 161 blk, err := database.GetBlockEntryByID(id) 162 if err != nil { 163 panic(err) 164 } 165 if !blk.IsActive() { 166 continue 167 } 168 if blk.ObjectPersisted() { 169 continue 170 } 171 start := info.GetSrcOff() 172 bat := data.CloneWindow(int(start), int(info.GetSrcLen())) 173 bat.Compact() 174 defer bat.Close() 175 if err = blk.GetObjectData().OnReplayAppendPayload(bat); err != nil { 176 panic(err) 177 } 178 } 179 } 180 181 func (store *replayTxnStore) replayDataCmds(cmd *updates.UpdateCmd, observer wal.ReplayObserver) { 182 switch cmd.GetType() { 183 case updates.IOET_WALTxnCommand_AppendNode: 184 store.replayAppend(cmd, observer) 185 case updates.IOET_WALTxnCommand_DeleteNode, updates.IOET_WALTxnCommand_PersistedDeleteNode: 186 store.replayDelete(cmd, observer) 187 } 188 } 189 190 func (store *replayTxnStore) replayDelete(cmd *updates.UpdateCmd, observer wal.ReplayObserver) { 191 deleteNode := cmd.GetDeleteNode() 192 if deleteNode.Is1PC() { 193 if _, err := deleteNode.TxnMVCCNode.ApplyCommit(); err != nil { 194 panic(err) 195 } 196 } 197 id := deleteNode.GetID() 198 database, err := store.catalog.GetDatabaseByID(id.DbID) 199 if err != nil { 200 panic(err) 201 } 202 blk, err := database.GetBlockEntryByID(id) 203 if err != nil { 204 panic(err) 205 } 206 if !blk.IsActive() { 207 return 208 } 209 blkData := blk.GetObjectData() 210 _, blkOffset := id.BlockID.Offsets() 211 err = blkData.OnReplayDelete(blkOffset, deleteNode) 212 if err != nil { 213 panic(err) 214 } 215 216 } 217 218 func (store *replayTxnStore) replayAppend(cmd *updates.UpdateCmd, observer wal.ReplayObserver) { 219 appendNode := cmd.GetAppendNode() 220 if appendNode.Is1PC() { 221 if _, err := appendNode.TxnMVCCNode.ApplyCommit(); err != nil { 222 panic(err) 223 } 224 } 225 id := appendNode.GetID() 226 database, err := store.catalog.GetDatabaseByID(id.DbID) 227 if err != nil { 228 panic(err) 229 } 230 blk, err := database.GetBlockEntryByID(id) 231 if err != nil { 232 panic(err) 233 } 234 if !blk.IsActive() { 235 return 236 } 237 if blk.ObjectPersisted() { 238 return 239 } 240 if err = blk.GetObjectData().OnReplayAppend(appendNode); err != nil { 241 panic(err) 242 } 243 }