github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/logstore/driver/logservicedriver/info.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 "fmt" 19 "math" 20 "sync" 21 "sync/atomic" 22 "time" 23 24 "github.com/RoaringBitmap/roaring/roaring64" 25 "github.com/matrixorigin/matrixone/pkg/common/moerr" 26 "github.com/matrixorigin/matrixone/pkg/logutil" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 28 ) 29 30 var ErrDriverLsnNotFound = moerr.NewInternalErrorNoCtx("driver info: driver lsn not found") 31 var ErrRetryTimeOut = moerr.NewInternalErrorNoCtx("driver info: retry time out") 32 33 type driverInfo struct { 34 addr map[uint64]*common.ClosedIntervals //logservicelsn-driverlsn TODO drop on truncate 35 validLsn *roaring64.Bitmap 36 addrMu sync.RWMutex 37 driverLsn uint64 // 38 syncing uint64 39 synced uint64 40 syncedMu sync.RWMutex 41 driverLsnMu sync.RWMutex 42 43 truncating atomic.Uint64 // 44 truncatedLogserviceLsn uint64 // 45 46 appending uint64 47 appended *common.ClosedIntervals 48 appendedMu sync.RWMutex 49 commitCond sync.Cond 50 inReplay bool 51 } 52 53 func newDriverInfo() *driverInfo { 54 return &driverInfo{ 55 addr: make(map[uint64]*common.ClosedIntervals), 56 validLsn: roaring64.NewBitmap(), 57 addrMu: sync.RWMutex{}, 58 driverLsnMu: sync.RWMutex{}, 59 appended: common.NewClosedIntervals(), 60 appendedMu: sync.RWMutex{}, 61 commitCond: *sync.NewCond(new(sync.Mutex)), 62 } 63 } 64 65 func (d *LogServiceDriver) GetCurrSeqNum() uint64 { 66 d.driverLsnMu.Lock() 67 lsn := d.driverLsn 68 d.driverLsnMu.Unlock() 69 return lsn 70 } 71 func (info *driverInfo) PreReplay() { 72 info.inReplay = true 73 } 74 func (info *driverInfo) PostReplay() { 75 info.inReplay = false 76 } 77 func (info *driverInfo) IsReplaying() bool { 78 return info.inReplay 79 } 80 func (info *driverInfo) onReplay(r *replayer) { 81 info.driverLsn = r.maxDriverLsn 82 info.synced = r.maxDriverLsn 83 info.syncing = r.maxDriverLsn 84 if r.minDriverLsn != math.MaxUint64 { 85 info.truncating.Store(r.minDriverLsn - 1) 86 } 87 info.truncatedLogserviceLsn = r.truncatedLogserviceLsn 88 info.appended.TryMerge(*common.NewClosedIntervalsBySlice(r.appended)) 89 } 90 91 func (info *driverInfo) onReplayRecordEntry(lsn uint64, driverLsns *common.ClosedIntervals) { 92 info.addr[lsn] = driverLsns 93 info.validLsn.Add(lsn) 94 } 95 96 func (info *driverInfo) getNextValidLogserviceLsn(lsn uint64) uint64 { 97 info.addrMu.Lock() 98 defer info.addrMu.Unlock() 99 if info.validLsn.GetCardinality() == 0 { 100 return 0 101 } 102 max := info.validLsn.Maximum() 103 if lsn >= max { 104 return max 105 } 106 lsn++ 107 for !info.validLsn.Contains(lsn) { 108 lsn++ 109 } 110 return lsn 111 } 112 113 func (info *driverInfo) isToTruncate(logserviceLsn, driverLsn uint64) bool { 114 maxlsn := info.getMaxDriverLsn(logserviceLsn) 115 if maxlsn == 0 { 116 return false 117 } 118 return maxlsn <= driverLsn 119 } 120 121 func (info *driverInfo) getMaxDriverLsn(logserviceLsn uint64) uint64 { 122 info.addrMu.RLock() 123 intervals, ok := info.addr[logserviceLsn] 124 if !ok { 125 info.addrMu.RUnlock() 126 return 0 127 } 128 lsn := intervals.GetMax() 129 info.addrMu.RUnlock() 130 return lsn 131 } 132 133 func (info *driverInfo) allocateDriverLsn() uint64 { 134 info.driverLsn++ 135 lsn := info.driverLsn 136 return lsn 137 } 138 139 func (info *driverInfo) getDriverLsn() uint64 { 140 info.driverLsnMu.RLock() 141 lsn := info.driverLsn 142 info.driverLsnMu.RUnlock() 143 return lsn 144 } 145 146 func (info *driverInfo) getAppended() uint64 { 147 info.appendedMu.RLock() 148 defer info.appendedMu.RUnlock() 149 if info.appended == nil || len(info.appended.Intervals) == 0 || info.appended.Intervals[0].Start != 1 { 150 return 0 151 } 152 return info.appended.Intervals[0].End 153 } 154 155 func (info *driverInfo) retryAllocateAppendLsnWithTimeout(maxPendding uint64, timeout time.Duration) (lsn uint64, err error) { 156 lsn, err = info.tryAllocate(maxPendding) 157 if err == ErrTooMuchPenddings { 158 err = RetryWithTimeout(timeout, func() (shouldReturn bool) { 159 info.commitCond.L.Lock() 160 lsn, err = info.tryAllocate(maxPendding) 161 if err != ErrTooMuchPenddings { 162 info.commitCond.L.Unlock() 163 return true 164 } 165 info.commitCond.Wait() 166 info.commitCond.L.Unlock() 167 lsn, err = info.tryAllocate(maxPendding) 168 return err != ErrTooMuchPenddings 169 }) 170 } 171 return 172 } 173 174 func (info *driverInfo) tryAllocate(maxPendding uint64) (lsn uint64, err error) { 175 appended := info.getAppended() 176 if info.appending-appended >= maxPendding { 177 return 0, ErrTooMuchPenddings 178 } 179 info.appending++ 180 return info.appending, nil 181 } 182 183 func (info *driverInfo) logAppend(appender *driverAppender) { 184 info.addrMu.Lock() 185 array := make([]uint64, 0) 186 for key := range appender.entry.meta.addr { 187 array = append(array, key) 188 } 189 info.validLsn.Add(appender.logserviceLsn) 190 interval := common.NewClosedIntervalsBySlice(array) 191 info.addr[appender.logserviceLsn] = interval 192 info.addrMu.Unlock() 193 if interval.GetMin() != info.syncing+1 { 194 panic(fmt.Sprintf("logic err, expect %d, min is %d", info.syncing+1, interval.GetMin())) 195 } 196 if len(interval.Intervals) != 1 { 197 logutil.Debugf("interval is %v", interval) 198 panic("logic err") 199 } 200 info.syncing = interval.GetMax() 201 } 202 203 func (info *driverInfo) gcAddr(logserviceLsn uint64) { 204 info.addrMu.Lock() 205 defer info.addrMu.Unlock() 206 lsnToDelete := make([]uint64, 0) 207 for serviceLsn := range info.addr { 208 if serviceLsn < logserviceLsn { 209 lsnToDelete = append(lsnToDelete, serviceLsn) 210 } 211 } 212 for _, lsn := range lsnToDelete { 213 delete(info.addr, lsn) 214 } 215 } 216 217 func (info *driverInfo) getSynced() uint64 { 218 info.syncedMu.RLock() 219 lsn := info.synced 220 info.syncedMu.RUnlock() 221 return lsn 222 } 223 func (info *driverInfo) onAppend(appended []uint64) { 224 info.syncedMu.Lock() 225 info.synced = info.syncing 226 info.syncedMu.Unlock() 227 228 appendedArray := common.NewClosedIntervalsBySlice(appended) 229 info.appendedMu.Lock() 230 info.appended.TryMerge(*appendedArray) 231 info.appendedMu.Unlock() 232 233 info.commitCond.L.Lock() 234 info.commitCond.Broadcast() 235 info.commitCond.L.Unlock() 236 } 237 238 func (info *driverInfo) tryGetLogServiceLsnByDriverLsn(driverLsn uint64) (uint64, error) { 239 lsn, err := info.getLogServiceLsnByDriverLsn(driverLsn) 240 if err == ErrDriverLsnNotFound { 241 if lsn <= info.getDriverLsn() { 242 for i := 0; i < 10; i++ { 243 logutil.Infof("retry get logserviceLsn, driverlsn=%d", driverLsn) 244 info.commitCond.L.Lock() 245 lsn, err = info.getLogServiceLsnByDriverLsn(driverLsn) 246 if err == nil { 247 info.commitCond.L.Unlock() 248 break 249 } 250 info.commitCond.Wait() 251 info.commitCond.L.Unlock() 252 if err == nil { 253 break 254 } 255 } 256 if err != nil { 257 return 0, ErrRetryTimeOut 258 } 259 } 260 } 261 return lsn, err 262 } 263 264 func (info *driverInfo) getLogServiceLsnByDriverLsn(driverLsn uint64) (uint64, error) { 265 info.addrMu.RLock() 266 defer info.addrMu.RUnlock() 267 for lsn, intervals := range info.addr { 268 if intervals.Contains(*common.NewClosedIntervalsByInt(driverLsn)) { 269 return lsn, nil 270 } 271 } 272 return 0, ErrDriverLsnNotFound 273 }