github.com/ledgerwatch/erigon-lib@v1.0.0/kv/kvcache/cache.go (about) 1 /* 2 Copyright 2021 Erigon contributors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 package kvcache 17 18 import ( 19 "bytes" 20 "context" 21 "encoding/binary" 22 "fmt" 23 "hash" 24 "sort" 25 "sync" 26 "sync/atomic" 27 "time" 28 29 "github.com/VictoriaMetrics/metrics" 30 "github.com/c2h5oh/datasize" 31 btree2 "github.com/tidwall/btree" 32 "golang.org/x/crypto/sha3" 33 34 "github.com/ledgerwatch/erigon-lib/common" 35 "github.com/ledgerwatch/erigon-lib/gointerfaces" 36 "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" 37 "github.com/ledgerwatch/erigon-lib/kv" 38 ) 39 40 type CacheValidationResult struct { 41 RequestCancelled bool 42 Enabled bool 43 LatestStateBehind bool 44 CacheCleared bool 45 LatestStateID uint64 46 StateKeysOutOfSync [][]byte 47 CodeKeysOutOfSync [][]byte 48 } 49 50 type Cache interface { 51 // View - returns CacheView consistent with givent kv.Tx 52 View(ctx context.Context, tx kv.Tx) (CacheView, error) 53 OnNewBlock(sc *remote.StateChangeBatch) 54 Len() int 55 ValidateCurrentRoot(ctx context.Context, tx kv.Tx) (*CacheValidationResult, error) 56 } 57 type CacheView interface { 58 Get(k []byte) ([]byte, error) 59 GetCode(k []byte) ([]byte, error) 60 } 61 62 // Coherent works on top of Database Transaction and pair Coherent+ReadTransaction must 63 // provide "Serializable Isolation Level" semantic: all data form consistent db view at moment 64 // when read transaction started, read data are immutable until end of read transaction, reader can't see newer updates 65 // 66 // Every time a new state change comes, we do the following: 67 // - Check that prevBlockHeight and prevBlockHash match what is the top values we have, and if they don't we 68 // invalidate the cache, because we missed some messages and cannot consider the cache coherent anymore. 69 // - Clone the cache pointer (such that the previous pointer is still accessible, but new one shared the content with it), 70 // apply state updates to the cloned cache pointer and save under the new identified made from blockHeight and blockHash. 71 // - If there is a conditional variable corresponding to the identifier, remove it from the map and notify conditional 72 // variable, waking up the read-only transaction waiting on it. 73 // 74 // On the other hand, whenever we have a cache miss (by looking at the top cache), we do the following: 75 // - Once read the current block height and block hash (canonical) from underlying db transaction 76 // - Construct the identifier from the current block height and block hash 77 // - Look for the constructed identifier in the cache. If the identifier is found, use the corresponding 78 // cache in conjunction with this read-only transaction (it will be consistent with it). If the identifier is 79 // not found, it means that the transaction has been committed in Erigon, but the state update has not 80 // arrived yet (as shown in the picture on the right). Insert conditional variable for this identifier and wait on 81 // it until either cache with the given identifier appears, or timeout (indicating that the cache update 82 // mechanism is broken and cache is likely invalidated). 83 // 84 85 // Pair.Value == nil - is a marker of absense key in db 86 87 // Coherent 88 // High-level guaranties: 89 // - Keys/Values returned by cache are valid/immutable until end of db transaction 90 // - CacheView is always coherent with given db transaction - 91 // 92 // Rules of set view.isCanonical value: 93 // - method View can't parent.Clone() - because parent view is not coherent with current kv.Tx 94 // - only OnNewBlock method may do parent.Clone() and apply StateChanges to create coherent view of kv.Tx 95 // - parent.Clone() can't be caled if parent.isCanonical=false 96 // - only OnNewBlock method can set view.isCanonical=true 97 // 98 // Rules of filling cache.stateEvict: 99 // - changes in Canonical View SHOULD reflect in stateEvict 100 // - changes in Non-Canonical View SHOULD NOT reflect in stateEvict 101 type Coherent struct { 102 hasher hash.Hash 103 codeEvictLen *metrics.Counter 104 codeKeys *metrics.Counter 105 keys *metrics.Counter 106 evict *metrics.Counter 107 latestStateView *CoherentRoot 108 codeMiss *metrics.Counter 109 timeout *metrics.Counter 110 hits *metrics.Counter 111 codeHits *metrics.Counter 112 roots map[uint64]*CoherentRoot 113 stateEvict *ThreadSafeEvictionList 114 codeEvict *ThreadSafeEvictionList 115 miss *metrics.Counter 116 cfg CoherentConfig 117 latestStateVersionID uint64 118 lock sync.Mutex 119 waitExceededCount atomic.Int32 // used as a circuit breaker to stop the cache waiting for new blocks 120 } 121 122 type CoherentRoot struct { 123 cache *btree2.BTreeG[*Element] 124 codeCache *btree2.BTreeG[*Element] 125 ready chan struct{} // close when ready 126 readyChanClosed atomic.Bool // protecting `ready` field from double-close (on unwind). Consumers don't need check this field. 127 128 // Views marked as `Canonical` if it received onNewBlock message 129 // we may drop `Non-Canonical` views even if they had fresh keys 130 // keys added to `Non-Canonical` views SHOULD NOT be added to stateEvict 131 // cache.latestStateView is always `Canonical` 132 isCanonical bool 133 } 134 135 // CoherentView - dumb object, which proxy all requests to Coherent object. 136 // It's thread-safe, because immutable 137 type CoherentView struct { 138 tx kv.Tx 139 cache *Coherent 140 stateVersionID uint64 141 } 142 143 func (c *CoherentView) Get(k []byte) ([]byte, error) { return c.cache.Get(k, c.tx, c.stateVersionID) } 144 func (c *CoherentView) GetCode(k []byte) ([]byte, error) { 145 return c.cache.GetCode(k, c.tx, c.stateVersionID) 146 } 147 148 var _ Cache = (*Coherent)(nil) // compile-time interface check 149 var _ CacheView = (*CoherentView)(nil) // compile-time interface check 150 151 const ( 152 DEGREE = 32 153 MAX_WAITS = 100 154 ) 155 156 type CoherentConfig struct { 157 CacheSize datasize.ByteSize 158 CodeCacheSize datasize.ByteSize 159 WaitForNewBlock bool // should we wait 10ms for a new block message to arrive when calling View? 160 WithStorage bool 161 MetricsLabel string 162 NewBlockWait time.Duration // how long wait 163 KeepViews uint64 // keep in memory up to this amount of views, evict older 164 } 165 166 var DefaultCoherentConfig = CoherentConfig{ 167 KeepViews: 5, 168 NewBlockWait: 5 * time.Millisecond, 169 CacheSize: 2 * datasize.GB, 170 CodeCacheSize: 2 * datasize.GB, 171 MetricsLabel: "default", 172 WithStorage: true, 173 WaitForNewBlock: true, 174 } 175 176 func New(cfg CoherentConfig) *Coherent { 177 if cfg.KeepViews == 0 { 178 panic("empty config passed") 179 } 180 181 return &Coherent{ 182 roots: map[uint64]*CoherentRoot{}, 183 stateEvict: &ThreadSafeEvictionList{l: NewList()}, 184 codeEvict: &ThreadSafeEvictionList{l: NewList()}, 185 hasher: sha3.NewLegacyKeccak256(), 186 cfg: cfg, 187 miss: metrics.GetOrCreateCounter(fmt.Sprintf(`cache_total{result="miss",name="%s"}`, cfg.MetricsLabel)), 188 hits: metrics.GetOrCreateCounter(fmt.Sprintf(`cache_total{result="hit",name="%s"}`, cfg.MetricsLabel)), 189 timeout: metrics.GetOrCreateCounter(fmt.Sprintf(`cache_timeout_total{name="%s"}`, cfg.MetricsLabel)), 190 keys: metrics.GetOrCreateCounter(fmt.Sprintf(`cache_keys_total{name="%s"}`, cfg.MetricsLabel)), 191 evict: metrics.GetOrCreateCounter(fmt.Sprintf(`cache_list_total{name="%s"}`, cfg.MetricsLabel)), 192 codeMiss: metrics.GetOrCreateCounter(fmt.Sprintf(`cache_code_total{result="miss",name="%s"}`, cfg.MetricsLabel)), 193 codeHits: metrics.GetOrCreateCounter(fmt.Sprintf(`cache_code_total{result="hit",name="%s"}`, cfg.MetricsLabel)), 194 codeKeys: metrics.GetOrCreateCounter(fmt.Sprintf(`cache_code_keys_total{name="%s"}`, cfg.MetricsLabel)), 195 codeEvictLen: metrics.GetOrCreateCounter(fmt.Sprintf(`cache_code_list_total{name="%s"}`, cfg.MetricsLabel)), 196 } 197 } 198 199 // selectOrCreateRoot - used for usual getting root 200 func (c *Coherent) selectOrCreateRoot(versionID uint64) *CoherentRoot { 201 c.lock.Lock() 202 defer c.lock.Unlock() 203 r, ok := c.roots[versionID] 204 if ok { 205 return r 206 } 207 208 r = &CoherentRoot{ 209 ready: make(chan struct{}), 210 cache: btree2.NewBTreeG[*Element](Less), 211 codeCache: btree2.NewBTreeG[*Element](Less), 212 } 213 c.roots[versionID] = r 214 return r 215 } 216 217 // advanceRoot - used for advancing root onNewBlock 218 func (c *Coherent) advanceRoot(stateVersionID uint64) (r *CoherentRoot) { 219 r, rootExists := c.roots[stateVersionID] 220 221 // if nothing has progressed just return the existing root 222 if c.latestStateVersionID == stateVersionID && rootExists { 223 return r 224 } 225 226 if !rootExists { 227 r = &CoherentRoot{ready: make(chan struct{})} 228 c.roots[stateVersionID] = r 229 } 230 231 if prevView, ok := c.roots[stateVersionID-1]; ok && prevView.isCanonical { 232 //log.Info("advance: clone", "from", viewID-1, "to", viewID) 233 r.cache = prevView.cache.Copy() 234 r.codeCache = prevView.codeCache.Copy() 235 } else { 236 c.stateEvict.Init() 237 c.codeEvict.Init() 238 if r.cache == nil { 239 //log.Info("advance: new", "to", viewID) 240 r.cache = btree2.NewBTreeG[*Element](Less) 241 r.codeCache = btree2.NewBTreeG[*Element](Less) 242 } else { 243 r.cache.Walk(func(items []*Element) bool { 244 for _, i := range items { 245 c.stateEvict.PushFront(i) 246 } 247 return true 248 }) 249 r.codeCache.Walk(func(items []*Element) bool { 250 for _, i := range items { 251 c.codeEvict.PushFront(i) 252 } 253 return true 254 }) 255 } 256 } 257 r.isCanonical = true 258 259 c.evictRoots() 260 c.latestStateVersionID = stateVersionID 261 c.latestStateView = r 262 263 c.keys.Set(uint64(c.latestStateView.cache.Len())) 264 c.codeKeys.Set(uint64(c.latestStateView.codeCache.Len())) 265 c.evict.Set(uint64(c.stateEvict.Len())) 266 c.codeEvictLen.Set(uint64(c.codeEvict.Len())) 267 return r 268 } 269 270 func (c *Coherent) OnNewBlock(stateChanges *remote.StateChangeBatch) { 271 c.lock.Lock() 272 defer c.lock.Unlock() 273 c.waitExceededCount.Store(0) // reset the circuit breaker 274 id := stateChanges.StateVersionId 275 r := c.advanceRoot(id) 276 for _, sc := range stateChanges.ChangeBatch { 277 for i := range sc.Changes { 278 switch sc.Changes[i].Action { 279 case remote.Action_UPSERT: 280 addr := gointerfaces.ConvertH160toAddress(sc.Changes[i].Address) 281 v := sc.Changes[i].Data 282 //fmt.Printf("set: %x,%x\n", addr, v) 283 c.add(addr[:], v, r, id) 284 case remote.Action_UPSERT_CODE: 285 addr := gointerfaces.ConvertH160toAddress(sc.Changes[i].Address) 286 v := sc.Changes[i].Data 287 c.add(addr[:], v, r, id) 288 c.hasher.Reset() 289 c.hasher.Write(sc.Changes[i].Code) 290 k := make([]byte, 32) 291 c.hasher.Sum(k) 292 c.addCode(k, sc.Changes[i].Code, r, id) 293 case remote.Action_REMOVE: 294 addr := gointerfaces.ConvertH160toAddress(sc.Changes[i].Address) 295 c.add(addr[:], nil, r, id) 296 case remote.Action_STORAGE: 297 //skip, will check later 298 case remote.Action_CODE: 299 c.hasher.Reset() 300 c.hasher.Write(sc.Changes[i].Code) 301 k := make([]byte, 32) 302 c.hasher.Sum(k) 303 c.addCode(k, sc.Changes[i].Code, r, id) 304 default: 305 panic("not implemented yet") 306 } 307 if c.cfg.WithStorage && len(sc.Changes[i].StorageChanges) > 0 { 308 addr := gointerfaces.ConvertH160toAddress(sc.Changes[i].Address) 309 for _, change := range sc.Changes[i].StorageChanges { 310 loc := gointerfaces.ConvertH256ToHash(change.Location) 311 k := make([]byte, 20+8+32) 312 copy(k, addr[:]) 313 binary.BigEndian.PutUint64(k[20:], sc.Changes[i].Incarnation) 314 copy(k[20+8:], loc[:]) 315 c.add(k, change.Data, r, id) 316 } 317 } 318 } 319 } 320 321 switched := r.readyChanClosed.CompareAndSwap(false, true) 322 if switched { 323 close(r.ready) //broadcast 324 } 325 //log.Info("on new block handled", "viewID", stateChanges.StateVersionID) 326 } 327 328 func (c *Coherent) View(ctx context.Context, tx kv.Tx) (CacheView, error) { 329 idBytes, err := tx.GetOne(kv.Sequence, kv.PlainStateVersion) 330 if err != nil { 331 return nil, err 332 } 333 var id uint64 334 if len(idBytes) == 0 { 335 id = 0 336 } else { 337 id = binary.BigEndian.Uint64(idBytes) 338 } 339 r := c.selectOrCreateRoot(id) 340 341 if !c.cfg.WaitForNewBlock || c.waitExceededCount.Load() >= MAX_WAITS { 342 return &CoherentView{stateVersionID: id, tx: tx, cache: c}, nil 343 } 344 345 select { // fast non-blocking path 346 case <-r.ready: 347 //fmt.Printf("recv broadcast: %d\n", id) 348 return &CoherentView{stateVersionID: id, tx: tx, cache: c}, nil 349 default: 350 } 351 352 select { // slow blocking path 353 case <-r.ready: 354 //fmt.Printf("recv broadcast2: %d\n", tx.ViewID()) 355 case <-ctx.Done(): 356 return nil, fmt.Errorf("kvcache rootNum=%x, %w", tx.ViewID(), ctx.Err()) 357 case <-time.After(c.cfg.NewBlockWait): //TODO: switch to timer to save resources 358 c.timeout.Inc() 359 c.waitExceededCount.Add(1) 360 //log.Info("timeout", "db_id", id, "has_btree", r.cache != nil) 361 } 362 return &CoherentView{stateVersionID: id, tx: tx, cache: c}, nil 363 } 364 365 func (c *Coherent) getFromCache(k []byte, id uint64, code bool) (*Element, *CoherentRoot, error) { 366 // using the full lock here rather than RLock as RLock causes a lot of calls to runtime.usleep degrading 367 // performance under load 368 c.lock.Lock() 369 defer c.lock.Unlock() 370 r, ok := c.roots[id] 371 if !ok { 372 return nil, r, fmt.Errorf("too old ViewID: %d, latestStateVersionID=%d", id, c.latestStateVersionID) 373 } 374 isLatest := c.latestStateVersionID == id 375 376 var it *Element 377 if code { 378 it, _ = r.codeCache.Get(&Element{K: k}) 379 } else { 380 it, _ = r.cache.Get(&Element{K: k}) 381 } 382 if it != nil && isLatest { 383 c.stateEvict.MoveToFront(it) 384 } 385 386 return it, r, nil 387 } 388 func (c *Coherent) Get(k []byte, tx kv.Tx, id uint64) ([]byte, error) { 389 it, r, err := c.getFromCache(k, id, false) 390 if err != nil { 391 return nil, err 392 } 393 394 if it != nil { 395 //fmt.Printf("from cache: %#x,%x\n", k, it.(*Element).V) 396 c.hits.Inc() 397 return it.V, nil 398 } 399 c.miss.Inc() 400 401 v, err := tx.GetOne(kv.PlainState, k) 402 if err != nil { 403 return nil, err 404 } 405 //fmt.Printf("from db: %#x,%x\n", k, v) 406 407 c.lock.Lock() 408 defer c.lock.Unlock() 409 v = c.add(common.Copy(k), common.Copy(v), r, id).V 410 return v, nil 411 } 412 413 func (c *Coherent) GetCode(k []byte, tx kv.Tx, id uint64) ([]byte, error) { 414 it, r, err := c.getFromCache(k, id, true) 415 if err != nil { 416 return nil, err 417 } 418 419 if it != nil { 420 //fmt.Printf("from cache: %#x,%x\n", k, it.(*Element).V) 421 c.codeHits.Inc() 422 return it.V, nil 423 } 424 c.codeMiss.Inc() 425 426 v, err := tx.GetOne(kv.Code, k) 427 if err != nil { 428 return nil, err 429 } 430 //fmt.Printf("from db: %#x,%x\n", k, v) 431 432 c.lock.Lock() 433 defer c.lock.Unlock() 434 v = c.addCode(common.Copy(k), common.Copy(v), r, id).V 435 return v, nil 436 } 437 func (c *Coherent) removeOldest(r *CoherentRoot) { 438 e := c.stateEvict.Oldest() 439 if e != nil { 440 c.stateEvict.Remove(e) 441 r.cache.Delete(e) 442 } 443 } 444 func (c *Coherent) removeOldestCode(r *CoherentRoot) { 445 e := c.codeEvict.Oldest() 446 if e != nil { 447 c.codeEvict.Remove(e) 448 r.codeCache.Delete(e) 449 } 450 } 451 func (c *Coherent) add(k, v []byte, r *CoherentRoot, id uint64) *Element { 452 it := &Element{K: k, V: v} 453 replaced, _ := r.cache.Set(it) 454 if c.latestStateVersionID != id { 455 //fmt.Printf("add to non-last viewID: %d<%d\n", c.latestViewID, id) 456 return it 457 } 458 if replaced != nil { 459 c.stateEvict.Remove(replaced) 460 } 461 c.stateEvict.PushFront(it) 462 463 // clear down cache until size below the configured limit 464 for c.stateEvict.Size() > int(c.cfg.CacheSize.Bytes()) { 465 c.removeOldest(r) 466 } 467 468 return it 469 } 470 func (c *Coherent) addCode(k, v []byte, r *CoherentRoot, id uint64) *Element { 471 it := &Element{K: k, V: v} 472 replaced, _ := r.codeCache.Set(it) 473 if c.latestStateVersionID != id { 474 //fmt.Printf("add to non-last viewID: %d<%d\n", c.latestViewID, id) 475 return it 476 } 477 if replaced != nil { 478 c.codeEvict.Remove(replaced) 479 } 480 c.codeEvict.PushFront(it) 481 482 for c.codeEvict.Size() > int(c.cfg.CodeCacheSize.Bytes()) { 483 c.removeOldestCode(r) 484 } 485 486 return it 487 } 488 489 func (c *Coherent) ValidateCurrentRoot(ctx context.Context, tx kv.Tx) (*CacheValidationResult, error) { 490 491 result := &CacheValidationResult{ 492 Enabled: true, 493 RequestCancelled: false, 494 } 495 496 select { 497 case <-ctx.Done(): 498 result.RequestCancelled = true 499 return result, nil 500 default: 501 } 502 503 idBytes, err := tx.GetOne(kv.Sequence, kv.PlainStateVersion) 504 if err != nil { 505 return nil, err 506 } 507 stateID := binary.BigEndian.Uint64(idBytes) 508 result.LatestStateID = stateID 509 510 // if the latest view id in the cache is not the same as the tx or one below it 511 // then the cache will be a new one for the next call so return early 512 if stateID > c.latestStateVersionID { 513 result.LatestStateBehind = true 514 return result, nil 515 } 516 517 root := c.selectOrCreateRoot(c.latestStateVersionID) 518 519 // ensure the root is ready or wait and press on 520 select { 521 case <-root.ready: 522 case <-time.After(c.cfg.NewBlockWait): 523 } 524 525 // check context again after potentially waiting for root to be ready 526 select { 527 case <-ctx.Done(): 528 result.RequestCancelled = true 529 return result, nil 530 default: 531 } 532 533 clearCache := false 534 535 compare := func(cache *btree2.BTreeG[*Element], bucket string) (bool, [][]byte, error) { 536 keys := make([][]byte, 0) 537 538 for { 539 val, ok := cache.PopMax() 540 if !ok { 541 break 542 } 543 544 // check the db 545 inDb, err := tx.GetOne(bucket, val.K) 546 if err != nil { 547 return false, keys, err 548 } 549 550 if !bytes.Equal(inDb, val.V) { 551 keys = append(keys, val.K) 552 clearCache = true 553 } 554 555 select { 556 case <-ctx.Done(): 557 return true, keys, nil 558 default: 559 } 560 } 561 562 return false, keys, nil 563 } 564 565 cache, codeCache := c.cloneCaches(root) 566 567 cancelled, keys, err := compare(cache, kv.PlainState) 568 if err != nil { 569 return nil, err 570 } 571 result.StateKeysOutOfSync = keys 572 if cancelled { 573 result.RequestCancelled = true 574 return result, nil 575 } 576 577 cancelled, keys, err = compare(codeCache, kv.Code) 578 if err != nil { 579 return nil, err 580 } 581 result.CodeKeysOutOfSync = keys 582 if cancelled { 583 result.RequestCancelled = true 584 return result, nil 585 } 586 587 if clearCache { 588 c.clearCaches(root) 589 } 590 result.CacheCleared = clearCache 591 592 return result, nil 593 } 594 595 func (c *Coherent) cloneCaches(r *CoherentRoot) (cache *btree2.BTreeG[*Element], codeCache *btree2.BTreeG[*Element]) { 596 c.lock.Lock() 597 defer c.lock.Unlock() 598 cache = r.cache.Copy() 599 codeCache = r.codeCache.Copy() 600 return cache, codeCache 601 } 602 603 func (c *Coherent) clearCaches(r *CoherentRoot) { 604 c.lock.Lock() 605 defer c.lock.Unlock() 606 r.cache.Clear() 607 r.codeCache.Clear() 608 } 609 610 type Stat struct { 611 BlockNum uint64 612 BlockHash [32]byte 613 Lenght int 614 } 615 616 func DebugStats(cache Cache) []Stat { 617 res := []Stat{} 618 casted, ok := cache.(*Coherent) 619 if !ok { 620 return res 621 } 622 casted.lock.Lock() 623 for root, r := range casted.roots { 624 res = append(res, Stat{ 625 BlockNum: root, 626 Lenght: r.cache.Len(), 627 }) 628 } 629 casted.lock.Unlock() 630 sort.Slice(res, func(i, j int) bool { return res[i].BlockNum < res[j].BlockNum }) 631 return res 632 } 633 func AssertCheckValues(ctx context.Context, tx kv.Tx, cache Cache) (int, error) { 634 defer func(t time.Time) { fmt.Printf("AssertCheckValues:327: %s\n", time.Since(t)) }(time.Now()) 635 view, err := cache.View(ctx, tx) 636 if err != nil { 637 return 0, err 638 } 639 castedView, ok := view.(*CoherentView) 640 if !ok { 641 return 0, nil 642 } 643 casted, ok := cache.(*Coherent) 644 if !ok { 645 return 0, nil 646 } 647 checked := 0 648 casted.lock.Lock() 649 defer casted.lock.Unlock() 650 //log.Info("AssertCheckValues start", "db_id", tx.ViewID(), "mem_id", casted.id.Load(), "len", casted.cache.Len()) 651 root, ok := casted.roots[castedView.stateVersionID] 652 if !ok { 653 return 0, nil 654 } 655 root.cache.Walk(func(items []*Element) bool { 656 for _, i := range items { 657 k, v := i.K, i.V 658 var dbV []byte 659 dbV, err = tx.GetOne(kv.PlainState, k) 660 if err != nil { 661 return false 662 } 663 if !bytes.Equal(dbV, v) { 664 err = fmt.Errorf("key: %x, has different values: %x != %x", k, v, dbV) 665 return false 666 } 667 checked++ 668 } 669 return true 670 }) 671 return checked, err 672 } 673 func (c *Coherent) evictRoots() { 674 if c.latestStateVersionID <= c.cfg.KeepViews { 675 return 676 } 677 if len(c.roots) < int(c.cfg.KeepViews) { 678 return 679 } 680 to := c.latestStateVersionID - c.cfg.KeepViews 681 toDel := make([]uint64, 0, len(c.roots)) 682 for txID := range c.roots { 683 if txID > to { 684 continue 685 } 686 toDel = append(toDel, txID) 687 } 688 //log.Info("forget old roots", "list", fmt.Sprintf("%d", toDel)) 689 for _, txID := range toDel { 690 delete(c.roots, txID) 691 } 692 } 693 func (c *Coherent) Len() int { 694 c.lock.Lock() 695 defer c.lock.Unlock() 696 if c.latestStateView == nil { 697 return 0 698 } 699 return c.latestStateView.cache.Len() //todo: is it same with cache.len()? 700 } 701 702 // Element is an element of a linked list. 703 type Element struct { 704 // Next and previous pointers in the doubly-linked list of elements. 705 // To simplify the implementation, internally a list l is implemented 706 // as a ring, such that &l.root is both the next element of the last 707 // list element (l.Back()) and the previous element of the first list 708 // element (l.Front()). 709 next, prev *Element 710 711 // The list to which this element belongs. 712 list *List 713 714 // The value stored with this element. 715 K, V []byte 716 } 717 718 func (e *Element) Size() int { return len(e.K) + len(e.V) } 719 720 func Less(a, b *Element) bool { return bytes.Compare(a.K, b.K) < 0 } 721 722 type ThreadSafeEvictionList struct { 723 l *List 724 lock sync.Mutex 725 } 726 727 func (l *ThreadSafeEvictionList) Init() { 728 l.lock.Lock() 729 l.l.Init() 730 l.lock.Unlock() 731 } 732 func (l *ThreadSafeEvictionList) PushFront(e *Element) { 733 l.lock.Lock() 734 l.l.PushFront(e) 735 l.lock.Unlock() 736 } 737 738 func (l *ThreadSafeEvictionList) MoveToFront(e *Element) { 739 l.lock.Lock() 740 l.l.MoveToFront(e) 741 l.lock.Unlock() 742 } 743 744 func (l *ThreadSafeEvictionList) Remove(e *Element) { 745 l.lock.Lock() 746 l.l.Remove(e) 747 l.lock.Unlock() 748 } 749 750 func (l *ThreadSafeEvictionList) Oldest() *Element { 751 l.lock.Lock() 752 e := l.l.Back() 753 l.lock.Unlock() 754 return e 755 } 756 757 func (l *ThreadSafeEvictionList) Len() int { 758 l.lock.Lock() 759 length := l.l.Len() 760 l.lock.Unlock() 761 return length 762 } 763 764 func (l *ThreadSafeEvictionList) Size() int { 765 l.lock.Lock() 766 size := l.l.Size() 767 l.lock.Unlock() 768 return size 769 } 770 771 // ========= copypaste of List implementation from stdlib ======== 772 773 // Next returns the next list element or nil. 774 func (e *Element) Next() *Element { 775 if p := e.next; e.list != nil && p != &e.list.root { 776 return p 777 } 778 return nil 779 } 780 781 // Prev returns the previous list element or nil. 782 func (e *Element) Prev() *Element { 783 if p := e.prev; e.list != nil && p != &e.list.root { 784 return p 785 } 786 return nil 787 } 788 789 // List represents a doubly linked list. 790 // The zero value for List is an empty list ready to use. 791 type List struct { 792 root Element // sentinel list element, only &root, root.prev, and root.next are used 793 len int // current list length excluding (this) sentinel element 794 size int // size of items in list in bytes 795 } 796 797 // Init initializes or clears list l. 798 func (l *List) Init() *List { 799 l.root.next = &l.root 800 l.root.prev = &l.root 801 l.len = 0 802 l.size = 0 803 return l 804 } 805 806 // New returns an initialized list. 807 func NewList() *List { return new(List).Init() } 808 809 // Len returns the number of elements of list l. 810 // The complexity is O(1). 811 func (l *List) Len() int { return l.len } 812 813 // Size returns the size of the elements in the list by bytes 814 func (l *List) Size() int { return l.size } 815 816 // Front returns the first element of list l or nil if the list is empty. 817 func (l *List) Front() *Element { 818 if l.len == 0 { 819 return nil 820 } 821 return l.root.next 822 } 823 824 // Back returns the last element of list l or nil if the list is empty. 825 func (l *List) Back() *Element { 826 if l.len == 0 { 827 return nil 828 } 829 return l.root.prev 830 } 831 832 // lazyInit lazily initializes a zero List value. 833 func (l *List) lazyInit() { 834 if l.root.next == nil { 835 l.Init() 836 } 837 } 838 839 // insert inserts e after at, increments l.len, and returns e. 840 func (l *List) insert(e, at *Element) *Element { 841 e.prev = at 842 e.next = at.next 843 e.prev.next = e 844 e.next.prev = e 845 e.list = l 846 l.len++ 847 l.size += e.Size() 848 return e 849 } 850 851 // insertValue is a convenience wrapper for insert(&Element{Value: v}, at). 852 func (l *List) insertValue(e, at *Element) *Element { 853 return l.insert(e, at) 854 } 855 856 // remove removes e from its list, decrements l.len, and returns e. 857 func (l *List) remove(e *Element) *Element { 858 e.prev.next = e.next 859 e.next.prev = e.prev 860 e.next = nil // avoid memory leaks 861 e.prev = nil // avoid memory leaks 862 e.list = nil 863 l.len-- 864 l.size -= e.Size() 865 return e 866 } 867 868 // move moves e to next to at and returns e. 869 func (l *List) move(e, at *Element) *Element { 870 if e == at { 871 return e 872 } 873 e.prev.next = e.next 874 e.next.prev = e.prev 875 876 e.prev = at 877 e.next = at.next 878 e.prev.next = e 879 e.next.prev = e 880 881 return e 882 } 883 884 // Remove removes e from l if e is an element of list l. 885 // It returns the element value e.Value. 886 // The element must not be nil. 887 func (l *List) Remove(e *Element) ([]byte, []byte) { 888 if e.list == l { 889 // if e.list == l, l must have been initialized when e was inserted 890 // in l or l == nil (e is a zero Element) and l.remove will crash 891 l.remove(e) 892 } 893 return e.K, e.V 894 } 895 896 // PushFront inserts a new element e with value v at the front of list l and returns e. 897 func (l *List) PushFront(e *Element) *Element { 898 l.lazyInit() 899 return l.insertValue(e, &l.root) 900 } 901 902 // PushBack inserts a new element e with value v at the back of list l and returns e. 903 func (l *List) PushBack(e *Element) *Element { 904 l.lazyInit() 905 return l.insertValue(e, l.root.prev) 906 } 907 908 // InsertBefore inserts a new element e with value v immediately before mark and returns e. 909 // If mark is not an element of l, the list is not modified. 910 // The mark must not be nil. 911 func (l *List) InsertBefore(e *Element, mark *Element) *Element { 912 if mark.list != l { 913 return nil 914 } 915 // see comment in List.Remove about initialization of l 916 return l.insertValue(e, mark.prev) 917 } 918 919 // InsertAfter inserts a new element e with value v immediately after mark and returns e. 920 // If mark is not an element of l, the list is not modified. 921 // The mark must not be nil. 922 func (l *List) InsertAfter(e *Element, mark *Element) *Element { 923 if mark.list != l { 924 return nil 925 } 926 // see comment in List.Remove about initialization of l 927 return l.insertValue(e, mark) 928 } 929 930 // MoveToFront moves element e to the front of list l. 931 // If e is not an element of l, the list is not modified. 932 // The element must not be nil. 933 func (l *List) MoveToFront(e *Element) { 934 if e.list != l || l.root.next == e { 935 return 936 } 937 // see comment in List.Remove about initialization of l 938 l.move(e, &l.root) 939 } 940 941 // MoveToBack moves element e to the back of list l. 942 // If e is not an element of l, the list is not modified. 943 // The element must not be nil. 944 func (l *List) MoveToBack(e *Element) { 945 if e.list != l || l.root.prev == e { 946 return 947 } 948 // see comment in List.Remove about initialization of l 949 l.move(e, l.root.prev) 950 } 951 952 // MoveBefore moves element e to its new position before mark. 953 // If e or mark is not an element of l, or e == mark, the list is not modified. 954 // The element and mark must not be nil. 955 func (l *List) MoveBefore(e, mark *Element) { 956 if e.list != l || e == mark || mark.list != l { 957 return 958 } 959 l.move(e, mark.prev) 960 } 961 962 // MoveAfter moves element e to its new position after mark. 963 // If e or mark is not an element of l, or e == mark, the list is not modified. 964 // The element and mark must not be nil. 965 func (l *List) MoveAfter(e, mark *Element) { 966 if e.list != l || e == mark || mark.list != l { 967 return 968 } 969 l.move(e, mark) 970 }