forked from cerc-io/plugeth
all: remove remaining uses of untyped golang-lru (#26194)
This commit is contained in:
+36
-33
@@ -34,11 +34,11 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/edsrzf/mmap-go"
|
||||
lrupkg "github.com/ethereum/go-ethereum/common/lru"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/hashicorp/golang-lru/simplelru"
|
||||
)
|
||||
|
||||
var ErrInvalidDumpMagic = errors.New("invalid dump magic")
|
||||
@@ -165,34 +165,45 @@ func memoryMapAndGenerate(path string, size uint64, lock bool, generator func(bu
|
||||
return memoryMap(path, lock)
|
||||
}
|
||||
|
||||
type cacheOrDataset interface {
|
||||
*cache | *dataset
|
||||
}
|
||||
|
||||
// lru tracks caches or datasets by their last use time, keeping at most N of them.
|
||||
type lru struct {
|
||||
type lru[T cacheOrDataset] struct {
|
||||
what string
|
||||
new func(epoch uint64) interface{}
|
||||
new func(epoch uint64) T
|
||||
mu sync.Mutex
|
||||
// Items are kept in a LRU cache, but there is a special case:
|
||||
// We always keep an item for (highest seen epoch) + 1 as the 'future item'.
|
||||
cache *simplelru.LRU
|
||||
cache lrupkg.BasicLRU[uint64, T]
|
||||
future uint64
|
||||
futureItem interface{}
|
||||
futureItem T
|
||||
}
|
||||
|
||||
// newlru create a new least-recently-used cache for either the verification caches
|
||||
// or the mining datasets.
|
||||
func newlru(what string, maxItems int, new func(epoch uint64) interface{}) *lru {
|
||||
if maxItems <= 0 {
|
||||
maxItems = 1
|
||||
func newlru[T cacheOrDataset](maxItems int, new func(epoch uint64) T) *lru[T] {
|
||||
var what string
|
||||
switch any(T(nil)).(type) {
|
||||
case *cache:
|
||||
what = "cache"
|
||||
case *dataset:
|
||||
what = "dataset"
|
||||
default:
|
||||
panic("unknown type")
|
||||
}
|
||||
return &lru[T]{
|
||||
what: what,
|
||||
new: new,
|
||||
cache: lrupkg.NewBasicLRU[uint64, T](maxItems),
|
||||
}
|
||||
cache, _ := simplelru.NewLRU(maxItems, func(key, value interface{}) {
|
||||
log.Trace("Evicted ethash "+what, "epoch", key)
|
||||
})
|
||||
return &lru{what: what, new: new, cache: cache}
|
||||
}
|
||||
|
||||
// get retrieves or creates an item for the given epoch. The first return value is always
|
||||
// non-nil. The second return value is non-nil if lru thinks that an item will be useful in
|
||||
// the near future.
|
||||
func (lru *lru) get(epoch uint64) (item, future interface{}) {
|
||||
func (lru *lru[T]) get(epoch uint64) (item, future T) {
|
||||
lru.mu.Lock()
|
||||
defer lru.mu.Unlock()
|
||||
|
||||
@@ -226,9 +237,8 @@ type cache struct {
|
||||
once sync.Once // Ensures the cache is generated only once
|
||||
}
|
||||
|
||||
// newCache creates a new ethash verification cache and returns it as a plain Go
|
||||
// interface to be usable in an LRU cache.
|
||||
func newCache(epoch uint64) interface{} {
|
||||
// newCache creates a new ethash verification cache.
|
||||
func newCache(epoch uint64) *cache {
|
||||
return &cache{epoch: epoch}
|
||||
}
|
||||
|
||||
@@ -308,7 +318,7 @@ type dataset struct {
|
||||
|
||||
// newDataset creates a new ethash mining dataset and returns it as a plain Go
|
||||
// interface to be usable in an LRU cache.
|
||||
func newDataset(epoch uint64) interface{} {
|
||||
func newDataset(epoch uint64) *dataset {
|
||||
return &dataset{epoch: epoch}
|
||||
}
|
||||
|
||||
@@ -439,8 +449,8 @@ type Config struct {
|
||||
type Ethash struct {
|
||||
config Config
|
||||
|
||||
caches *lru // In memory caches to avoid regenerating too often
|
||||
datasets *lru // In memory datasets to avoid regenerating too often
|
||||
caches *lru[*cache] // In memory caches to avoid regenerating too often
|
||||
datasets *lru[*dataset] // In memory datasets to avoid regenerating too often
|
||||
|
||||
// Mining related fields
|
||||
rand *rand.Rand // Properly seeded random source for nonces
|
||||
@@ -477,8 +487,8 @@ func New(config Config, notify []string, noverify bool) *Ethash {
|
||||
}
|
||||
ethash := &Ethash{
|
||||
config: config,
|
||||
caches: newlru("cache", config.CachesInMem, newCache),
|
||||
datasets: newlru("dataset", config.DatasetsInMem, newDataset),
|
||||
caches: newlru(config.CachesInMem, newCache),
|
||||
datasets: newlru(config.DatasetsInMem, newDataset),
|
||||
update: make(chan struct{}),
|
||||
hashrate: metrics.NewMeterForced(),
|
||||
}
|
||||
@@ -573,15 +583,13 @@ func (ethash *Ethash) StopRemoteSealer() error {
|
||||
// stored on disk, and finally generating one if none can be found.
|
||||
func (ethash *Ethash) cache(block uint64) *cache {
|
||||
epoch := block / epochLength
|
||||
currentI, futureI := ethash.caches.get(epoch)
|
||||
current := currentI.(*cache)
|
||||
current, future := ethash.caches.get(epoch)
|
||||
|
||||
// Wait for generation finish.
|
||||
current.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.CachesLockMmap, ethash.config.PowMode == ModeTest)
|
||||
|
||||
// If we need a new future cache, now's a good time to regenerate it.
|
||||
if futureI != nil {
|
||||
future := futureI.(*cache)
|
||||
if future != nil {
|
||||
go future.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.CachesLockMmap, ethash.config.PowMode == ModeTest)
|
||||
}
|
||||
return current
|
||||
@@ -596,25 +604,20 @@ func (ethash *Ethash) cache(block uint64) *cache {
|
||||
func (ethash *Ethash) dataset(block uint64, async bool) *dataset {
|
||||
// Retrieve the requested ethash dataset
|
||||
epoch := block / epochLength
|
||||
currentI, futureI := ethash.datasets.get(epoch)
|
||||
current := currentI.(*dataset)
|
||||
current, future := ethash.datasets.get(epoch)
|
||||
|
||||
// If async is specified, generate everything in a background thread
|
||||
if async && !current.generated() {
|
||||
go func() {
|
||||
current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest)
|
||||
|
||||
if futureI != nil {
|
||||
future := futureI.(*dataset)
|
||||
if future != nil {
|
||||
future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest)
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
// Either blocking generation was requested, or already done
|
||||
current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest)
|
||||
|
||||
if futureI != nil {
|
||||
future := futureI.(*dataset)
|
||||
if future != nil {
|
||||
go future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user