github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/storage/mvcc/mvcc.go (about) 1 // Copyright 2022 zGraph Authors. All rights reserved. 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 mvcc 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "io" 21 "math" 22 23 "github.com/google/btree" 24 "github.com/pingcap/errors" 25 "github.com/vescale/zgraph/storage/kv" 26 ) 27 28 type ValueType int 29 30 const ( 31 ValueTypePut ValueType = iota 32 ValueTypeDelete 33 ValueTypeRollback 34 ValueTypeLock 35 ) 36 37 type Value struct { 38 Type ValueType 39 StartVer kv.Version 40 CommitVer kv.Version 41 Value []byte 42 } 43 44 type Lock struct { 45 StartVer kv.Version 46 Primary []byte 47 Value []byte 48 Op Op 49 TTL uint64 50 } 51 52 type Entry struct { 53 Key Key 54 Values []Value 55 Lock *Lock 56 } 57 58 // MarshalBinary implements encoding.BinaryMarshaler interface. 59 func (l *Lock) MarshalBinary() ([]byte, error) { 60 var ( 61 mh marshalHelper 62 buf bytes.Buffer 63 ) 64 mh.WriteNumber(&buf, l.StartVer) 65 mh.WriteSlice(&buf, l.Primary) 66 mh.WriteSlice(&buf, l.Value) 67 mh.WriteNumber(&buf, l.Op) 68 mh.WriteNumber(&buf, l.TTL) 69 return buf.Bytes(), mh.err 70 } 71 72 // UnmarshalBinary implements encoding.BinaryUnmarshaler interface. 73 func (l *Lock) UnmarshalBinary(data []byte) error { 74 var mh marshalHelper 75 buf := bytes.NewBuffer(data) 76 mh.ReadNumber(buf, &l.StartVer) 77 mh.ReadSlice(buf, &l.Primary) 78 mh.ReadSlice(buf, &l.Value) 79 mh.ReadNumber(buf, &l.Op) 80 mh.ReadNumber(buf, &l.TTL) 81 return mh.err 82 } 83 84 // MarshalBinary implements encoding.BinaryMarshaler interface. 85 func (v *Value) MarshalBinary() ([]byte, error) { 86 var ( 87 mh marshalHelper 88 buf bytes.Buffer 89 ) 90 mh.WriteNumber(&buf, int64(v.Type)) 91 mh.WriteNumber(&buf, v.StartVer) 92 mh.WriteNumber(&buf, v.CommitVer) 93 mh.WriteSlice(&buf, v.Value) 94 return buf.Bytes(), mh.err 95 } 96 97 // UnmarshalBinary implements encoding.BinaryUnmarshaler interface. 98 func (v *Value) UnmarshalBinary(data []byte) error { 99 var mh marshalHelper 100 buf := bytes.NewBuffer(data) 101 var vt int64 102 mh.ReadNumber(buf, &vt) 103 v.Type = ValueType(vt) 104 mh.ReadNumber(buf, &v.StartVer) 105 mh.ReadNumber(buf, &v.CommitVer) 106 mh.ReadSlice(buf, &v.Value) 107 return mh.err 108 } 109 110 type marshalHelper struct { 111 err error 112 } 113 114 func (mh *marshalHelper) WriteSlice(buf io.Writer, slice []byte) { 115 if mh.err != nil { 116 return 117 } 118 var tmp [binary.MaxVarintLen64]byte 119 off := binary.PutUvarint(tmp[:], uint64(len(slice))) 120 if err := writeFull(buf, tmp[:off]); err != nil { 121 mh.err = err 122 } 123 if err := writeFull(buf, slice); err != nil { 124 mh.err = err 125 } 126 } 127 128 func (mh *marshalHelper) WriteNumber(buf io.Writer, n interface{}) { 129 if mh.err != nil { 130 return 131 } 132 err := binary.Write(buf, binary.LittleEndian, n) 133 if err != nil { 134 mh.err = errors.Trace(err) 135 } 136 } 137 138 func writeFull(w io.Writer, slice []byte) error { 139 written := 0 140 for written < len(slice) { 141 n, err := w.Write(slice[written:]) 142 if err != nil { 143 return errors.Trace(err) 144 } 145 written += n 146 } 147 return nil 148 } 149 150 func (mh *marshalHelper) ReadNumber(r io.Reader, n interface{}) { 151 if mh.err != nil { 152 return 153 } 154 err := binary.Read(r, binary.LittleEndian, n) 155 if err != nil { 156 mh.err = errors.WithStack(err) 157 } 158 } 159 160 func (mh *marshalHelper) ReadSlice(r *bytes.Buffer, slice *[]byte) { 161 if mh.err != nil { 162 return 163 } 164 sz, err := binary.ReadUvarint(r) 165 if err != nil { 166 mh.err = errors.WithStack(err) 167 return 168 } 169 const c10M = 10 * 1024 * 1024 170 if sz > c10M { 171 mh.err = errors.New("too large slice, maybe something wrong") 172 return 173 } 174 data := make([]byte, sz) 175 if _, err := io.ReadFull(r, data); err != nil { 176 mh.err = errors.WithStack(err) 177 return 178 } 179 *slice = data 180 } 181 182 // LockErr returns LockedError. 183 // Note that parameter key is raw key, while key in LockedError is mvcc key. 184 func (l *Lock) LockErr(key []byte) error { 185 return &LockedError{ 186 Key: key, 187 Primary: l.Primary, 188 StartVer: l.StartVer, 189 TTL: l.TTL, 190 } 191 } 192 193 func (l *Lock) Check(ver kv.Version, key []byte, resolvedLocks []kv.Version) (kv.Version, error) { 194 // ignore when ver is older than lock or lock's type is Lock. 195 if l.StartVer > ver || l.Op == Op_Lock { 196 return ver, nil 197 } 198 // for point get the latest version. 199 if ver == math.MaxUint64 && bytes.Equal(l.Primary, key) { 200 return l.StartVer - 1, nil 201 } 202 // Skip lock if the lock is resolved. 203 for _, resolved := range resolvedLocks { 204 if l.StartVer == resolved { 205 return ver, nil 206 } 207 } 208 return 0, l.LockErr(key) 209 } 210 211 func (e *Entry) Less(than btree.Item) bool { 212 return bytes.Compare(e.Key, than.(*Entry).Key) < 0 213 } 214 215 func (e *Entry) Get(ver kv.Version, resolvedLocks []kv.Version) ([]byte, error) { 216 if e.Lock != nil { 217 var err error 218 ver, err = e.Lock.Check(ver, e.Key.Raw(), resolvedLocks) 219 if err != nil { 220 return nil, err 221 } 222 } 223 for _, v := range e.Values { 224 if v.CommitVer <= ver && v.Type != ValueTypeRollback && v.Type != ValueTypeLock { 225 return v.Value, nil 226 } 227 } 228 return nil, nil 229 }