github.com/turingchain2020/turingchain@v1.1.21/common/db/mvcc.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package db 6 7 import ( 8 "bytes" 9 "fmt" 10 "strconv" 11 12 log "github.com/turingchain2020/turingchain/common/log/log15" 13 "github.com/turingchain2020/turingchain/types" 14 ) 15 16 var mvccPrefix = []byte(".-mvcc-.") 17 var mvccMeta = append(mvccPrefix, []byte("m.")...) 18 var mvccData = append(mvccPrefix, []byte("d.")...) 19 var mvccLast = append(mvccPrefix, []byte("l.")...) 20 var mvccMetaVersion = append(mvccMeta, []byte("version.")...) 21 var mvccMetaVersionKeyList = append(mvccMeta, []byte("versionkl.")...) 22 23 //MVCC mvcc interface 24 type MVCC interface { 25 MVCCKV 26 SetVersion(hash []byte, version int64) error 27 DelVersion(hash []byte) error 28 GetVersion(hash []byte) (int64, error) 29 GetV(key []byte, version int64) ([]byte, error) 30 SetV(key []byte, value []byte, version int64) error 31 DelV(key []byte, version int64) error 32 AddMVCC(kvs []*types.KeyValue, hash []byte, prevHash []byte, version int64) ([]*types.KeyValue, error) 33 DelMVCC(hash []byte, version int64, strict bool) ([]*types.KeyValue, error) 34 GetMaxVersion() (int64, error) 35 GetVersionHash(version int64) ([]byte, error) 36 //回收: 某个版本之前的所有数据 37 //1. 保证有一个最新版本 38 //2. 这个操作回遍历所有的key所以比较慢 39 Trash(version int64) error 40 } 41 42 //MVCCKV only return kv when change database 43 type MVCCKV interface { 44 GetSaveKV(key []byte, value []byte, version int64) (*types.KeyValue, error) 45 GetDelKV(key []byte, version int64) (*types.KeyValue, error) 46 SetVersionKV(hash []byte, version int64) ([]*types.KeyValue, error) 47 DelVersionKV([]byte, int64) ([]*types.KeyValue, error) 48 } 49 50 //MVCCHelper impl MVCC interface 51 type MVCCHelper struct { 52 *SimpleMVCC 53 db DB 54 } 55 56 //SimpleMVCC kvdb 57 type SimpleMVCC struct { 58 kvdb KVDB 59 } 60 61 var mvcclog = log.New("module", "db.mvcc") 62 63 //NewMVCC create MVCC object use db DB 64 func NewMVCC(db DB) *MVCCHelper { 65 return &MVCCHelper{SimpleMVCC: NewSimpleMVCC(NewKVDB(db)), db: db} 66 } 67 68 //PrintAll 打印全部 69 func (m *MVCCHelper) PrintAll() { 70 println("--meta--") 71 it := m.db.Iterator(mvccMeta, nil, true) 72 defer it.Close() 73 for it.Rewind(); it.Valid(); it.Next() { 74 if it.Error() != nil { 75 mvcclog.Error("PrintAll", "error", it.Error()) 76 return 77 } 78 println(string(it.Key()), string(it.Value())) 79 } 80 81 println("--data--") 82 it = m.db.Iterator(mvccData, nil, true) 83 defer it.Close() 84 for it.Rewind(); it.Valid(); it.Next() { 85 if it.Error() != nil { 86 mvcclog.Error("PrintAll", "error", it.Error()) 87 return 88 } 89 println(string(it.Key()), string(it.Value())) 90 } 91 println("--last--") 92 it = m.db.Iterator(mvccLast, nil, true) 93 defer it.Close() 94 for it.Rewind(); it.Valid(); it.Next() { 95 if it.Error() != nil { 96 mvcclog.Error("PrintAll", "error", it.Error()) 97 return 98 } 99 println(string(it.Key()), string(it.Value())) 100 } 101 } 102 103 //Trash del some old kv 104 func (m *MVCCHelper) Trash(version int64) error { 105 it := m.db.Iterator(mvccData, nil, true) 106 defer it.Close() 107 perfixkey := []byte("--.xxx.--") 108 for it.Rewind(); it.Valid(); it.Next() { 109 if it.Error() != nil { 110 mvcclog.Error("Trash", "error", it.Error()) 111 return it.Error() 112 } 113 //如果进入一个新的key, 这个key 忽略,不删除,也就是至少保留一个 114 if !bytes.HasPrefix(it.Key(), perfixkey) { 115 perfixkey = cutVersion(it.Key()) 116 if perfixkey == nil { 117 perfixkey = []byte("--.xxx.--") 118 } 119 continue 120 } 121 //第二个key 122 v, err := getVersion(it.Key()) 123 if err != nil { 124 mvcclog.Error("Trash get verson", "err", err) 125 continue 126 } 127 if v <= version { 128 err := m.db.Delete(it.Key()) 129 if err != nil { 130 mvcclog.Error("Trash Delete verson", "err", err) 131 } 132 } 133 } 134 return nil 135 } 136 137 //DelVersion del stateHash version map 138 func (m *MVCCHelper) DelVersion(hash []byte) error { 139 version, err := m.GetVersion(hash) 140 if err != nil { 141 return err 142 } 143 kvs, err := m.DelVersionKV(hash, version) 144 if err != nil { 145 return err 146 } 147 batch := m.db.NewBatch(true) 148 for _, v := range kvs { 149 batch.Delete(v.Key) 150 } 151 return batch.Write() 152 } 153 154 //SetVersion set stateHash -> version map 155 func (m *MVCCHelper) SetVersion(hash []byte, version int64) error { 156 kvlist, err := m.SetVersionKV(hash, version) 157 if err != nil { 158 return err 159 } 160 batch := m.db.NewBatch(true) 161 for _, v := range kvlist { 162 batch.Set(v.Key, v.Value) 163 } 164 return batch.Write() 165 } 166 167 //DelV del key with version 168 func (m *MVCCHelper) DelV(key []byte, version int64) error { 169 kv, err := m.GetDelKV(key, version) 170 if err != nil { 171 return err 172 } 173 return m.db.Delete(kv.Key) 174 } 175 176 //NewSimpleMVCC new 177 func NewSimpleMVCC(db KVDB) *SimpleMVCC { 178 return &SimpleMVCC{db} 179 } 180 181 //GetVersion get stateHash and version map 182 func (m *SimpleMVCC) GetVersion(hash []byte) (int64, error) { 183 key := getVersionHashKey(hash) 184 value, err := m.kvdb.Get(key) 185 if err != nil { 186 if err == ErrNotFoundInDb { 187 return 0, types.ErrNotFound 188 } 189 return 0, err 190 } 191 var data types.Int64 192 err = types.Decode(value, &data) 193 if err != nil { 194 return 0, err 195 } 196 if data.GetData() < 0 { 197 return 0, types.ErrVersion 198 } 199 return data.GetData(), nil 200 } 201 202 //GetVersionHash 获取版本hash 203 func (m *SimpleMVCC) GetVersionHash(version int64) ([]byte, error) { 204 key := getVersionKey(version) 205 value, err := m.kvdb.Get(key) 206 if err != nil { 207 if err == ErrNotFoundInDb { 208 return nil, types.ErrNotFound 209 } 210 return nil, err 211 } 212 return value, nil 213 } 214 215 //GetMaxVersion 获取最高版本 216 func (m *SimpleMVCC) GetMaxVersion() (int64, error) { 217 vals, err := m.kvdb.List(mvccMetaVersion, nil, 1, ListDESC) 218 if err != nil { 219 return 0, err 220 } 221 hash := vals[0] 222 return m.GetVersion(hash) 223 } 224 225 //GetSaveKV only export set key and value with version 226 func (m *SimpleMVCC) GetSaveKV(key []byte, value []byte, version int64) (*types.KeyValue, error) { 227 k, err := GetKey(key, version) 228 if err != nil { 229 return nil, err 230 } 231 return &types.KeyValue{Key: k, Value: value}, nil 232 } 233 234 //GetDelKV only export del key and value with version 235 func (m *SimpleMVCC) GetDelKV(key []byte, version int64) (*types.KeyValue, error) { 236 k, err := GetKey(key, version) 237 if err != nil { 238 return nil, err 239 } 240 return &types.KeyValue{Key: k}, nil 241 } 242 243 //GetDelKVList 获取列表 244 func (m *SimpleMVCC) GetDelKVList(version int64) ([]*types.KeyValue, error) { 245 k := getVersionKeyListKey(version) 246 data, err := m.kvdb.Get(k) 247 if err != nil { 248 return nil, err 249 } 250 var kvlist types.LocalDBSet 251 err = types.Decode(data, &kvlist) 252 if err != nil { 253 return nil, err 254 } 255 return kvlist.KV, nil 256 } 257 258 //SetVersionKV only export SetVersionKV key and value 259 func (m *SimpleMVCC) SetVersionKV(hash []byte, version int64) ([]*types.KeyValue, error) { 260 if version < 0 { 261 return nil, types.ErrVersion 262 } 263 key := append(mvccMeta, hash...) 264 data := &types.Int64{Data: version} 265 v1 := &types.KeyValue{Key: key, Value: types.Encode(data)} 266 267 k2 := append(mvccMetaVersion, pad(version)...) 268 v2 := &types.KeyValue{Key: k2, Value: hash} 269 return []*types.KeyValue{v1, v2}, nil 270 } 271 272 //DelVersionKV only export del version key value 273 func (m *SimpleMVCC) DelVersionKV(hash []byte, version int64) ([]*types.KeyValue, error) { 274 kvs, err := m.SetVersionKV(hash, version) 275 if err != nil { 276 return nil, err 277 } 278 for i := 0; i < len(kvs); i++ { 279 kvs[i].Value = nil 280 } 281 return kvs, nil 282 } 283 284 //SetV set key and value with version 285 func (m *SimpleMVCC) SetV(key []byte, value []byte, version int64) error { 286 kv, err := m.GetSaveKV(key, value, version) 287 if err != nil { 288 return err 289 } 290 return m.kvdb.Set(kv.Key, kv.Value) 291 } 292 293 //GetV get key with version 294 func (m *SimpleMVCC) GetV(key []byte, version int64) ([]byte, error) { 295 prefix := GetKeyPerfix(key) 296 search, err := GetKey(key, version) 297 if err != nil { 298 return nil, err 299 } 300 vals, err := m.kvdb.List(prefix, search, 1, ListSeek) 301 if err != nil { 302 return nil, err 303 } 304 k := vals[0] 305 val := vals[1] 306 v, err := getVersion(k) 307 if err != nil { 308 return nil, err 309 } 310 if v > version { 311 return nil, types.ErrVersion 312 } 313 return val, nil 314 } 315 316 //AddMVCC add keys in a version 317 //添加MVCC的规则: 318 //必须提供现有hash 和 prev 的hash, 而且这两个版本号相差1 319 func (m *SimpleMVCC) AddMVCC(kvs []*types.KeyValue, hash []byte, prevHash []byte, version int64) ([]*types.KeyValue, error) { 320 if version > 0 { 321 if prevHash == nil { 322 return nil, types.ErrPrevVersion 323 } 324 prevVersion := version - 1 325 vhash, err := m.GetVersionHash(prevVersion) 326 if err != nil { 327 return nil, err 328 } 329 if !bytes.Equal(vhash, prevHash) { 330 return nil, types.ErrPrevVersion 331 } 332 } 333 versionlist, err := m.SetVersionKV(hash, version) 334 if err != nil { 335 return nil, err 336 } 337 var kvlist []*types.KeyValue 338 kvlist = append(kvlist, versionlist...) 339 delkeys := &types.LocalDBSet{} 340 for i := 0; i < len(kvs); i++ { 341 //最原始的数据 342 delkeys.KV = append(delkeys.KV, &types.KeyValue{Key: kvs[i].Key}) 343 kv, err := m.GetSaveKV(kvs[i].Key, kvs[i].Value, version) 344 if err != nil { 345 return nil, err 346 } 347 kvlist = append(kvlist, kv) 348 } 349 kvlist = append(kvlist, &types.KeyValue{Key: getVersionKeyListKey(version), Value: types.Encode(delkeys)}) 350 return kvlist, nil 351 } 352 353 //DelMVCC 删除某个版本 354 //我们目前规定删除的方法: 355 //1 -> 1-2-3-4-5,6 version 必须连续的增长 356 //2 -> del 也必须从尾部开始删除 357 func (m *SimpleMVCC) DelMVCC(hash []byte, version int64, strict bool) ([]*types.KeyValue, error) { 358 kvs, err := m.GetDelKVList(version) 359 if err != nil { 360 return nil, err 361 } 362 return m.delMVCC(kvs, hash, version, strict) 363 } 364 365 func (m *SimpleMVCC) delMVCC(kvs []*types.KeyValue, hash []byte, version int64, strict bool) ([]*types.KeyValue, error) { 366 if strict { 367 maxv, err := m.GetMaxVersion() 368 if err != nil { 369 return nil, err 370 } 371 if maxv != version { 372 return nil, types.ErrCanOnlyDelTopVersion 373 } 374 } 375 //check hash and version is match 376 vdb, err := m.GetVersion(hash) 377 if err != nil { 378 return nil, err 379 } 380 if vdb != version { 381 return nil, types.ErrVersion 382 } 383 kv, err := m.DelVersionKV(hash, version) 384 if err != nil { 385 return nil, err 386 } 387 var kvlist []*types.KeyValue 388 kvlist = append(kvlist, kv...) 389 for _, v := range kvs { 390 kv, err := m.GetDelKV(v.Key, version) 391 if err != nil { 392 return nil, err 393 } 394 kvlist = append(kvlist, kv) 395 } 396 return kvlist, nil 397 } 398 399 func getVersionString(key []byte) (string, error) { 400 for i := len(key) - 1; i >= 0; i-- { 401 if key[i] == '.' { 402 return string(key[i+1:]), nil 403 } 404 } 405 return "", types.ErrVersion 406 } 407 408 func cutVersion(key []byte) []byte { 409 for i := len(key) - 1; i >= 0; i-- { 410 if key[i] == '.' { 411 d := make([]byte, i) 412 copy(d, key[0:i+1]) 413 return d 414 } 415 } 416 return nil 417 } 418 419 func getVersion(key []byte) (int64, error) { 420 s, err := getVersionString(key) 421 if err != nil { 422 return 0, err 423 } 424 return strconv.ParseInt(s, 10, 64) 425 } 426 427 func pad(version int64) []byte { 428 s := fmt.Sprintf("%020d", version) 429 return []byte(s) 430 } 431 432 //GetKeyPerfix 获取key前缀 433 func GetKeyPerfix(key []byte) []byte { 434 b := append([]byte{}, mvccData...) 435 newkey := append(b, key...) 436 newkey = append(newkey, []byte(".")...) 437 return newkey 438 } 439 440 //GetKey 获取键 441 func GetKey(key []byte, version int64) ([]byte, error) { 442 newkey := append(GetKeyPerfix(key), pad(version)...) 443 return newkey, nil 444 } 445 446 func getLastKey(key []byte) []byte { 447 b := append([]byte{}, mvccLast...) 448 return append(b, key...) 449 } 450 451 func getVersionHashKey(hash []byte) []byte { 452 b := append([]byte{}, mvccMeta...) 453 key := append(b, hash...) 454 return key 455 } 456 457 func getVersionKey(version int64) []byte { 458 b := append([]byte{}, mvccMetaVersion...) 459 key := append(b, pad(version)...) 460 return key 461 } 462 463 func getVersionKeyListKey(version int64) []byte { 464 b := append([]byte{}, mvccMetaVersionKeyList...) 465 key := append(b, pad(version)...) 466 return key 467 }