2023-10-04 12:00:12 +00:00
|
|
|
package balance
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math"
|
|
|
|
"math/big"
|
|
|
|
)
|
|
|
|
|
|
|
|
func NewSimpleCacher() Cacher {
|
|
|
|
return newCacherImpl(newSimpleCache())
|
|
|
|
}
|
|
|
|
|
|
|
|
// implements cacheIface for plain map internal storage
|
|
|
|
type mapCache[K comparable, V any] struct {
|
2024-01-03 21:57:33 +00:00
|
|
|
cache map[K]V // nolint: structcheck
|
2023-10-04 12:00:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *mapCache[K, V]) get(key K) V {
|
|
|
|
return c.cache[key]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *mapCache[K, V]) set(key K, value V) {
|
|
|
|
c.cache[key] = value
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *mapCache[K, V]) len() int {
|
|
|
|
return len(c.cache)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *mapCache[K, V]) keys() []K {
|
|
|
|
keys := make([]K, 0, len(c.cache))
|
|
|
|
for k := range c.cache {
|
|
|
|
keys = append(keys, k)
|
|
|
|
}
|
|
|
|
return keys
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *mapCache[K, V]) init() {
|
|
|
|
c.cache = make(map[K]V)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *mapCache[K, V]) clear() {
|
|
|
|
c.cache = make(map[K]V)
|
|
|
|
}
|
|
|
|
|
|
|
|
// specializes generic cache
|
|
|
|
type simpleCache struct {
|
|
|
|
genericCache[*mapCache[uint64, *big.Int], *mapCache[uint64, *int64], *mapCache[int64, nonceRange]]
|
|
|
|
}
|
|
|
|
|
|
|
|
func newSimpleCache() *simpleCache {
|
|
|
|
return &simpleCache{
|
|
|
|
genericCache: genericCache[*mapCache[uint64, *big.Int], *mapCache[uint64, *int64], *mapCache[int64, nonceRange]]{
|
|
|
|
|
|
|
|
balances: make(addressChainMap[*mapCache[uint64, *big.Int]]),
|
|
|
|
nonces: make(addressChainMap[*mapCache[uint64, *int64]]),
|
|
|
|
nonceRangeCache: *newNonceRangeCache[*mapCache[int64, nonceRange]](),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Doesn't remove all entries, but keeps max and min to use on next iterations of transfer blocks searching
|
|
|
|
func (c *simpleCache) Clear() {
|
|
|
|
c.rw.Lock()
|
|
|
|
defer c.rw.Unlock()
|
|
|
|
|
|
|
|
for _, chainCache := range c.balances {
|
|
|
|
for _, cache := range chainCache {
|
|
|
|
if cache.len() == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
var maxBlock uint64 = 0
|
|
|
|
var minBlock uint64 = math.MaxUint64
|
|
|
|
for _, key := range cache.keys() {
|
|
|
|
if key > maxBlock {
|
|
|
|
maxBlock = key
|
|
|
|
}
|
|
|
|
if key < minBlock {
|
|
|
|
minBlock = key
|
|
|
|
}
|
|
|
|
}
|
|
|
|
maxBlockValue := cache.get(maxBlock)
|
|
|
|
minBlockValue := cache.get(maxBlock)
|
|
|
|
cache.clear()
|
|
|
|
|
|
|
|
if maxBlockValue != nil {
|
|
|
|
cache.set(maxBlock, maxBlockValue)
|
|
|
|
}
|
|
|
|
|
|
|
|
if minBlockValue != nil {
|
|
|
|
cache.set(minBlock, minBlockValue)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, chainCache := range c.nonces {
|
|
|
|
for _, cache := range chainCache {
|
|
|
|
if cache.len() == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
var maxBlock uint64 = 0
|
|
|
|
var minBlock uint64 = math.MaxUint64
|
|
|
|
for _, key := range cache.keys() {
|
|
|
|
if key > maxBlock {
|
|
|
|
maxBlock = key
|
|
|
|
}
|
|
|
|
if key < minBlock {
|
|
|
|
minBlock = key
|
|
|
|
}
|
|
|
|
}
|
|
|
|
maxBlockValue := cache.get(maxBlock)
|
|
|
|
minBlockValue := cache.get(maxBlock)
|
|
|
|
cache.clear()
|
|
|
|
|
|
|
|
if maxBlockValue != nil {
|
|
|
|
cache.set(maxBlock, maxBlockValue)
|
|
|
|
}
|
|
|
|
|
|
|
|
if minBlockValue != nil {
|
|
|
|
cache.set(minBlock, minBlockValue)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c.nonceRangeCache.clear()
|
|
|
|
}
|