github.com/KinWaiYuen/client-go/v2@v2.5.4/internal/mockstore/mocktikv/mvcc.go (about) 1 // Copyright 2021 TiKV Authors 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 // NOTE: The code in this file is based on code from the 16 // TiDB project, licensed under the Apache License v 2.0 17 // 18 // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/mockstore/mocktikv/mvcc.go 19 // 20 21 // Copyright 2016 PingCAP, Inc. 22 // 23 // Licensed under the Apache License, Version 2.0 (the "License"); 24 // you may not use this file except in compliance with the License. 25 // You may obtain a copy of the License at 26 // 27 // http://www.apache.org/licenses/LICENSE-2.0 28 // 29 // Unless required by applicable law or agreed to in writing, software 30 // distributed under the License is distributed on an "AS IS" BASIS, 31 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 // See the License for the specific language governing permissions and 33 // limitations under the License. 34 35 package mocktikv 36 37 import ( 38 "bytes" 39 "encoding/binary" 40 "io" 41 "math" 42 43 "github.com/KinWaiYuen/client-go/v2/util/codec" 44 "github.com/google/btree" 45 "github.com/pingcap/errors" 46 "github.com/pingcap/kvproto/pkg/kvrpcpb" 47 ) 48 49 type mvccValueType int 50 51 const ( 52 typePut mvccValueType = iota 53 typeDelete 54 typeRollback 55 typeLock 56 ) 57 58 type mvccValue struct { 59 valueType mvccValueType 60 startTS uint64 61 commitTS uint64 62 value []byte 63 } 64 65 type mvccLock struct { 66 startTS uint64 67 primary []byte 68 value []byte 69 op kvrpcpb.Op 70 ttl uint64 71 forUpdateTS uint64 72 txnSize uint64 73 minCommitTS uint64 74 } 75 76 type mvccEntry struct { 77 key MvccKey 78 values []mvccValue 79 lock *mvccLock 80 } 81 82 // MarshalBinary implements encoding.BinaryMarshaler interface. 83 func (l *mvccLock) MarshalBinary() ([]byte, error) { 84 var ( 85 mh marshalHelper 86 buf bytes.Buffer 87 ) 88 mh.WriteNumber(&buf, l.startTS) 89 mh.WriteSlice(&buf, l.primary) 90 mh.WriteSlice(&buf, l.value) 91 mh.WriteNumber(&buf, l.op) 92 mh.WriteNumber(&buf, l.ttl) 93 mh.WriteNumber(&buf, l.forUpdateTS) 94 mh.WriteNumber(&buf, l.txnSize) 95 mh.WriteNumber(&buf, l.minCommitTS) 96 return buf.Bytes(), errors.Trace(mh.err) 97 } 98 99 // UnmarshalBinary implements encoding.BinaryUnmarshaler interface. 100 func (l *mvccLock) UnmarshalBinary(data []byte) error { 101 var mh marshalHelper 102 buf := bytes.NewBuffer(data) 103 mh.ReadNumber(buf, &l.startTS) 104 mh.ReadSlice(buf, &l.primary) 105 mh.ReadSlice(buf, &l.value) 106 mh.ReadNumber(buf, &l.op) 107 mh.ReadNumber(buf, &l.ttl) 108 mh.ReadNumber(buf, &l.forUpdateTS) 109 mh.ReadNumber(buf, &l.txnSize) 110 mh.ReadNumber(buf, &l.minCommitTS) 111 return errors.Trace(mh.err) 112 } 113 114 // MarshalBinary implements encoding.BinaryMarshaler interface. 115 func (v mvccValue) MarshalBinary() ([]byte, error) { 116 var ( 117 mh marshalHelper 118 buf bytes.Buffer 119 ) 120 mh.WriteNumber(&buf, int64(v.valueType)) 121 mh.WriteNumber(&buf, v.startTS) 122 mh.WriteNumber(&buf, v.commitTS) 123 mh.WriteSlice(&buf, v.value) 124 return buf.Bytes(), errors.Trace(mh.err) 125 } 126 127 // UnmarshalBinary implements encoding.BinaryUnmarshaler interface. 128 func (v *mvccValue) UnmarshalBinary(data []byte) error { 129 var mh marshalHelper 130 buf := bytes.NewBuffer(data) 131 var vt int64 132 mh.ReadNumber(buf, &vt) 133 v.valueType = mvccValueType(vt) 134 mh.ReadNumber(buf, &v.startTS) 135 mh.ReadNumber(buf, &v.commitTS) 136 mh.ReadSlice(buf, &v.value) 137 return errors.Trace(mh.err) 138 } 139 140 type marshalHelper struct { 141 err error 142 } 143 144 func (mh *marshalHelper) WriteSlice(buf io.Writer, slice []byte) { 145 if mh.err != nil { 146 return 147 } 148 var tmp [binary.MaxVarintLen64]byte 149 off := binary.PutUvarint(tmp[:], uint64(len(slice))) 150 if err := writeFull(buf, tmp[:off]); err != nil { 151 mh.err = errors.Trace(err) 152 return 153 } 154 if err := writeFull(buf, slice); err != nil { 155 mh.err = errors.Trace(err) 156 } 157 } 158 159 func (mh *marshalHelper) WriteNumber(buf io.Writer, n interface{}) { 160 if mh.err != nil { 161 return 162 } 163 err := binary.Write(buf, binary.LittleEndian, n) 164 if err != nil { 165 mh.err = errors.Trace(err) 166 } 167 } 168 169 func writeFull(w io.Writer, slice []byte) error { 170 written := 0 171 for written < len(slice) { 172 n, err := w.Write(slice[written:]) 173 if err != nil { 174 return errors.Trace(err) 175 } 176 written += n 177 } 178 return nil 179 } 180 181 func (mh *marshalHelper) ReadNumber(r io.Reader, n interface{}) { 182 if mh.err != nil { 183 return 184 } 185 err := binary.Read(r, binary.LittleEndian, n) 186 if err != nil { 187 mh.err = errors.Trace(err) 188 } 189 } 190 191 func (mh *marshalHelper) ReadSlice(r *bytes.Buffer, slice *[]byte) { 192 if mh.err != nil { 193 return 194 } 195 sz, err := binary.ReadUvarint(r) 196 if err != nil { 197 mh.err = errors.Trace(err) 198 return 199 } 200 const c10M = 10 * 1024 * 1024 201 if sz > c10M { 202 mh.err = errors.New("too large slice, maybe something wrong") 203 return 204 } 205 data := make([]byte, sz) 206 if _, err := io.ReadFull(r, data); err != nil { 207 mh.err = errors.Trace(err) 208 return 209 } 210 *slice = data 211 } 212 213 // lockErr returns ErrLocked. 214 // Note that parameter key is raw key, while key in ErrLocked is mvcc key. 215 func (l *mvccLock) lockErr(key []byte) error { 216 return &ErrLocked{ 217 Key: mvccEncode(key, lockVer), 218 Primary: l.primary, 219 StartTS: l.startTS, 220 ForUpdateTS: l.forUpdateTS, 221 TTL: l.ttl, 222 TxnSize: l.txnSize, 223 LockType: l.op, 224 } 225 } 226 227 func (l *mvccLock) check(ts uint64, key []byte, resolvedLocks []uint64) (uint64, error) { 228 // ignore when ts is older than lock or lock's type is Lock. 229 // Pessimistic lock doesn't block read. 230 if l.startTS > ts || l.op == kvrpcpb.Op_Lock || l.op == kvrpcpb.Op_PessimisticLock { 231 return ts, nil 232 } 233 // for point get latest version. 234 if ts == math.MaxUint64 && bytes.Equal(l.primary, key) { 235 return l.startTS - 1, nil 236 } 237 // Skip lock if the lock is resolved. 238 for _, resolved := range resolvedLocks { 239 if l.startTS == resolved { 240 return ts, nil 241 } 242 } 243 return 0, l.lockErr(key) 244 } 245 246 func (e *mvccEntry) Less(than btree.Item) bool { 247 return bytes.Compare(e.key, than.(*mvccEntry).key) < 0 248 } 249 250 func (e *mvccEntry) Get(ts uint64, isoLevel kvrpcpb.IsolationLevel, resolvedLocks []uint64) ([]byte, error) { 251 if isoLevel == kvrpcpb.IsolationLevel_SI && e.lock != nil { 252 var err error 253 ts, err = e.lock.check(ts, e.key.Raw(), resolvedLocks) 254 if err != nil { 255 return nil, err 256 } 257 } 258 for _, v := range e.values { 259 if v.commitTS <= ts && v.valueType != typeRollback && v.valueType != typeLock { 260 return v.value, nil 261 } 262 } 263 return nil, nil 264 } 265 266 // MVCCStore is a mvcc key-value storage. 267 type MVCCStore interface { 268 Get(key []byte, startTS uint64, isoLevel kvrpcpb.IsolationLevel, resolvedLocks []uint64) ([]byte, error) 269 Scan(startKey, endKey []byte, limit int, startTS uint64, isoLevel kvrpcpb.IsolationLevel, resolvedLocks []uint64) []Pair 270 ReverseScan(startKey, endKey []byte, limit int, startTS uint64, isoLevel kvrpcpb.IsolationLevel, resolvedLocks []uint64) []Pair 271 BatchGet(ks [][]byte, startTS uint64, isoLevel kvrpcpb.IsolationLevel, resolvedLocks []uint64) []Pair 272 PessimisticLock(req *kvrpcpb.PessimisticLockRequest) *kvrpcpb.PessimisticLockResponse 273 PessimisticRollback(keys [][]byte, startTS, forUpdateTS uint64) []error 274 Prewrite(req *kvrpcpb.PrewriteRequest) []error 275 Commit(keys [][]byte, startTS, commitTS uint64) error 276 Rollback(keys [][]byte, startTS uint64) error 277 Cleanup(key []byte, startTS, currentTS uint64) error 278 ScanLock(startKey, endKey []byte, maxTS uint64) ([]*kvrpcpb.LockInfo, error) 279 TxnHeartBeat(primaryKey []byte, startTS uint64, adviseTTL uint64) (uint64, error) 280 ResolveLock(startKey, endKey []byte, startTS, commitTS uint64) error 281 BatchResolveLock(startKey, endKey []byte, txnInfos map[uint64]uint64) error 282 GC(startKey, endKey []byte, safePoint uint64) error 283 DeleteRange(startKey, endKey []byte) error 284 CheckTxnStatus(primaryKey []byte, lockTS uint64, startTS, currentTS uint64, rollbackIfNotFound bool, resolvingPessimisticLock bool) (uint64, uint64, kvrpcpb.Action, error) 285 Close() error 286 } 287 288 // RawKV is a key-value storage. MVCCStore can be implemented upon it with timestamp encoded into key. 289 type RawKV interface { 290 RawGet(key []byte) []byte 291 RawBatchGet(keys [][]byte) [][]byte 292 RawScan(startKey, endKey []byte, limit int) []Pair // Scan the range of [startKey, endKey) 293 RawReverseScan(startKey, endKey []byte, limit int) []Pair // Scan the range of [endKey, startKey) 294 RawPut(key, value []byte) 295 RawBatchPut(keys, values [][]byte) 296 RawDelete(key []byte) 297 RawBatchDelete(keys [][]byte) 298 RawDeleteRange(startKey, endKey []byte) 299 } 300 301 // MVCCDebugger is for debugging. 302 type MVCCDebugger interface { 303 MvccGetByStartTS(starTS uint64) (*kvrpcpb.MvccInfo, []byte) 304 MvccGetByKey(key []byte) *kvrpcpb.MvccInfo 305 } 306 307 // Pair is a KV pair read from MvccStore or an error if any occurs. 308 type Pair struct { 309 Key []byte 310 Value []byte 311 Err error 312 } 313 314 func regionContains(startKey []byte, endKey []byte, key []byte) bool { 315 return bytes.Compare(startKey, key) <= 0 && 316 (bytes.Compare(key, endKey) < 0 || len(endKey) == 0) 317 } 318 319 // MvccKey is the encoded key type. 320 // On TiKV, keys are encoded before they are saved into storage engine. 321 type MvccKey []byte 322 323 // NewMvccKey encodes a key into MvccKey. 324 func NewMvccKey(key []byte) MvccKey { 325 if len(key) == 0 { 326 return nil 327 } 328 return codec.EncodeBytes(nil, key) 329 } 330 331 // Raw decodes a MvccKey to original key. 332 func (key MvccKey) Raw() []byte { 333 if len(key) == 0 { 334 return nil 335 } 336 _, k, err := codec.DecodeBytes(key, nil) 337 if err != nil { 338 panic(err) 339 } 340 return k 341 }