github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/logstore/driver/logservicedriver/replay.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 logservicedriver 16 17 import ( 18 "bytes" 19 "context" 20 "encoding/binary" 21 "fmt" 22 "io" 23 "math" 24 "time" 25 26 "github.com/matrixorigin/matrixone/pkg/logutil" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/driver" 28 ) 29 30 type replayer struct { 31 readMaxSize int 32 33 truncatedLogserviceLsn uint64 34 35 minDriverLsn uint64 36 maxDriverLsn uint64 37 38 driverLsnLogserviceLsnMap map[uint64]uint64 //start-lsn 39 40 replayHandle driver.ApplyHandle 41 replayedLsn uint64 42 inited bool 43 safeLsn uint64 44 nextToReadLsn uint64 45 d *LogServiceDriver 46 appended []uint64 47 48 applyDuration time.Duration 49 } 50 51 func newReplayer(h driver.ApplyHandle, readmaxsize int, d *LogServiceDriver) *replayer { 52 truncated := d.getLogserviceTruncate() 53 logutil.Infof("truncated %d", truncated) 54 return &replayer{ 55 minDriverLsn: math.MaxUint64, 56 driverLsnLogserviceLsnMap: make(map[uint64]uint64), 57 replayHandle: h, 58 readMaxSize: readmaxsize, 59 nextToReadLsn: truncated + 1, 60 replayedLsn: math.MaxUint64, 61 d: d, 62 appended: make([]uint64, 0), 63 } 64 } 65 66 func (r *replayer) replay() { 67 var err error 68 r.truncatedLogserviceLsn = r.d.getLogserviceTruncate() 69 for !r.readRecords() { 70 for r.replayedLsn < r.safeLsn { 71 err := r.replayLogserviceEntry(r.replayedLsn+1, true) 72 if err != nil { 73 panic(err) 74 } 75 } 76 } 77 err = r.replayLogserviceEntry(r.replayedLsn+1, false) 78 for err != ErrAllRecordsRead { 79 err = r.replayLogserviceEntry(r.replayedLsn+1, false) 80 81 } 82 r.d.lsns = make([]uint64, 0) 83 } 84 85 func (r *replayer) readRecords() (readEnd bool) { 86 nextLsn, safeLsn := r.d.readFromLogServiceInReplay(r.nextToReadLsn, r.readMaxSize, func(lsn uint64, record *recordEntry) { 87 if record.meta.metaType == TReplay { 88 cmd := NewEmptyReplayCmd() 89 cmd.Unmarshal(record.payload) 90 r.removeEntries(cmd.skipLsns) 91 return 92 } 93 drlsn := record.GetMinLsn() 94 r.driverLsnLogserviceLsnMap[drlsn] = lsn 95 if drlsn < r.replayedLsn { 96 if r.inited { 97 panic("logic err") 98 } 99 r.replayedLsn = drlsn - 1 100 } 101 }) 102 if nextLsn == r.nextToReadLsn { 103 return true 104 } 105 r.nextToReadLsn = nextLsn 106 if safeLsn > r.safeLsn { 107 r.safeLsn = safeLsn 108 } 109 return false 110 } 111 func (r *replayer) removeEntries(skipMap map[uint64]uint64) { 112 for lsn := range skipMap { 113 if _, ok := r.driverLsnLogserviceLsnMap[lsn]; !ok { 114 panic(fmt.Sprintf("lsn %d not existed, map is %v", lsn, r.driverLsnLogserviceLsnMap)) 115 } 116 delete(r.driverLsnLogserviceLsnMap, lsn) 117 } 118 } 119 func (r *replayer) replayLogserviceEntry(lsn uint64, safe bool) error { 120 logserviceLsn, ok := r.driverLsnLogserviceLsnMap[lsn] 121 if !ok { 122 if safe { 123 logutil.Infof("drlsn %d has been truncated", lsn) 124 r.minDriverLsn = lsn + 1 125 r.replayedLsn++ 126 return nil 127 } 128 if len(r.driverLsnLogserviceLsnMap) == 0 { 129 return ErrAllRecordsRead 130 } 131 r.AppendSkipCmd(r.driverLsnLogserviceLsnMap) 132 logutil.Infof("skip lsns %v", r.driverLsnLogserviceLsnMap) 133 return ErrAllRecordsRead 134 } 135 record, err := r.d.readFromCache(logserviceLsn) 136 if err == ErrAllRecordsRead { 137 return err 138 } 139 if err != nil { 140 panic(err) 141 } 142 t0 := time.Now() 143 intervals := record.replay(r.replayHandle) 144 r.applyDuration += time.Since(t0) 145 r.d.onReplayRecordEntry(logserviceLsn, intervals) 146 r.onReplayDriverLsn(intervals.GetMax()) 147 r.onReplayDriverLsn(intervals.GetMin()) 148 r.d.dropRecordByLsn(logserviceLsn) 149 r.replayedLsn = record.GetMaxLsn() 150 r.inited = true 151 delete(r.driverLsnLogserviceLsnMap, lsn) 152 return nil 153 } 154 155 func (r *replayer) AppendSkipCmd(skipMap map[uint64]uint64) { 156 cmd := NewReplayCmd(skipMap) 157 recordEntry := newRecordEntry() 158 recordEntry.meta.metaType = TReplay 159 recordEntry.cmd = cmd 160 size := recordEntry.prepareRecord() 161 c, lsn := r.d.getClient() 162 r.appended = append(r.appended, lsn) 163 c.TryResize(size) 164 record := c.record 165 copy(record.Payload(), recordEntry.payload) 166 record.ResizePayload(size) 167 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 168 _, err := c.c.Append(ctx, c.record) 169 cancel() 170 if err != nil { 171 err = RetryWithTimeout(r.d.config.RetryTimeout, func() (shouldReturn bool) { 172 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 173 _, err := c.c.Append(ctx, c.record) 174 cancel() 175 return err == nil 176 }) 177 if err != nil { 178 panic(err) 179 } 180 } 181 } 182 func (r *replayer) onReplayDriverLsn(lsn uint64) { 183 if lsn == 0 { 184 return 185 } 186 if lsn < r.minDriverLsn { 187 r.minDriverLsn = lsn 188 } 189 if lsn > r.maxDriverLsn { 190 r.maxDriverLsn = lsn 191 } 192 } 193 194 type ReplayCmd struct { 195 skipLsns map[uint64]uint64 196 } 197 198 func NewReplayCmd(skipLsns map[uint64]uint64) *ReplayCmd { 199 return &ReplayCmd{ 200 skipLsns: skipLsns, 201 } 202 } 203 func NewEmptyReplayCmd() *ReplayCmd { 204 return &ReplayCmd{ 205 skipLsns: make(map[uint64]uint64), 206 } 207 } 208 209 func (c *ReplayCmd) WriteTo(w io.Writer) (n int64, err error) { 210 length := uint16(len(c.skipLsns)) 211 if err = binary.Write(w, binary.BigEndian, length); err != nil { 212 return 213 } 214 n += 2 215 for drlsn, logserviceLsn := range c.skipLsns { 216 if err = binary.Write(w, binary.BigEndian, drlsn); err != nil { 217 return 218 } 219 n += 8 220 if err = binary.Write(w, binary.BigEndian, logserviceLsn); err != nil { 221 return 222 } 223 n += 8 224 } 225 return 226 } 227 228 func (c *ReplayCmd) ReadFrom(r io.Reader) (n int64, err error) { 229 length := uint16(0) 230 if err = binary.Read(r, binary.BigEndian, &length); err != nil { 231 return 232 } 233 n += 2 234 for i := 0; i < int(length); i++ { 235 drlsn := uint64(0) 236 lsn := uint64(0) 237 if err = binary.Read(r, binary.BigEndian, &drlsn); err != nil { 238 return 239 } 240 n += 8 241 if err = binary.Read(r, binary.BigEndian, &lsn); err != nil { 242 return 243 } 244 n += 8 245 c.skipLsns[drlsn] = lsn 246 } 247 return 248 } 249 250 func (c *ReplayCmd) Unmarshal(buf []byte) error { 251 bbuf := bytes.NewBuffer(buf) 252 _, err := c.ReadFrom(bbuf) 253 return err 254 } 255 256 func (c *ReplayCmd) Marshal() (buf []byte, err error) { 257 var bbuf bytes.Buffer 258 if _, err = c.WriteTo(&bbuf); err != nil { 259 return 260 } 261 buf = bbuf.Bytes() 262 return 263 }