github.com/status-im/status-go@v1.1.0/services/wallet/balance/simple_cache.go (about)

     1  package balance
     2  
     3  import (
     4  	"math"
     5  	"math/big"
     6  )
     7  
     8  func NewSimpleCacher() Cacher {
     9  	return newCacherImpl(newSimpleCache())
    10  }
    11  
    12  // implements cacheIface for plain map internal storage
    13  type mapCache[K comparable, V any] struct {
    14  	cache map[K]V
    15  }
    16  
    17  func (c *mapCache[K, V]) get(key K) V {
    18  	return c.cache[key]
    19  }
    20  
    21  func (c *mapCache[K, V]) set(key K, value V) {
    22  	c.cache[key] = value
    23  }
    24  
    25  func (c *mapCache[K, V]) len() int {
    26  	return len(c.cache)
    27  }
    28  
    29  func (c *mapCache[K, V]) keys() []K {
    30  	keys := make([]K, 0, len(c.cache))
    31  	for k := range c.cache {
    32  		keys = append(keys, k)
    33  	}
    34  	return keys
    35  }
    36  
    37  func (c *mapCache[K, V]) init() {
    38  	c.cache = make(map[K]V)
    39  }
    40  
    41  func (c *mapCache[K, V]) clear() {
    42  	c.cache = make(map[K]V)
    43  }
    44  
    45  // specializes generic cache
    46  type simpleCache struct {
    47  	genericCache[*mapCache[uint64, *big.Int], *mapCache[uint64, *int64], *mapCache[int64, nonceRange]]
    48  }
    49  
    50  func newSimpleCache() *simpleCache {
    51  	return &simpleCache{
    52  		genericCache: genericCache[*mapCache[uint64, *big.Int], *mapCache[uint64, *int64], *mapCache[int64, nonceRange]]{
    53  
    54  			balances:        make(addressChainMap[*mapCache[uint64, *big.Int]]),
    55  			nonces:          make(addressChainMap[*mapCache[uint64, *int64]]),
    56  			nonceRangeCache: *newNonceRangeCache[*mapCache[int64, nonceRange]](),
    57  		},
    58  	}
    59  }
    60  
    61  // Doesn't remove all entries, but keeps max and min to use on next iterations of transfer blocks searching
    62  func (c *simpleCache) Clear() {
    63  	c.rw.Lock()
    64  	defer c.rw.Unlock()
    65  
    66  	for _, chainCache := range c.balances {
    67  		for _, cache := range chainCache {
    68  			if cache.len() == 0 {
    69  				continue
    70  			}
    71  
    72  			var maxBlock uint64 = 0
    73  			var minBlock uint64 = math.MaxUint64
    74  			for _, key := range cache.keys() {
    75  				if key > maxBlock {
    76  					maxBlock = key
    77  				}
    78  				if key < minBlock {
    79  					minBlock = key
    80  				}
    81  			}
    82  			maxBlockValue := cache.get(maxBlock)
    83  			minBlockValue := cache.get(maxBlock)
    84  			cache.clear()
    85  
    86  			if maxBlockValue != nil {
    87  				cache.set(maxBlock, maxBlockValue)
    88  			}
    89  
    90  			if minBlockValue != nil {
    91  				cache.set(minBlock, minBlockValue)
    92  			}
    93  		}
    94  	}
    95  
    96  	for _, chainCache := range c.nonces {
    97  		for _, cache := range chainCache {
    98  			if cache.len() == 0 {
    99  				continue
   100  			}
   101  
   102  			var maxBlock uint64 = 0
   103  			var minBlock uint64 = math.MaxUint64
   104  			for _, key := range cache.keys() {
   105  				if key > maxBlock {
   106  					maxBlock = key
   107  				}
   108  				if key < minBlock {
   109  					minBlock = key
   110  				}
   111  			}
   112  			maxBlockValue := cache.get(maxBlock)
   113  			minBlockValue := cache.get(maxBlock)
   114  			cache.clear()
   115  
   116  			if maxBlockValue != nil {
   117  				cache.set(maxBlock, maxBlockValue)
   118  			}
   119  
   120  			if minBlockValue != nil {
   121  				cache.set(minBlock, minBlockValue)
   122  			}
   123  		}
   124  	}
   125  
   126  	c.nonceRangeCache.clear()
   127  }