diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 439ecbe26..c98199335 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - go: [ '1.17.x', '1.18.x', '1.19.x' ] + go: [ '1.18.x', '1.19.x' ] steps: - name: Setup go uses: actions/setup-go@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 83c8d474b..1b4acbb08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Changelog for NeoFS Node - `golang.org/x/term` to `v0.3.0` - `google.golang.org/grpc` to `v1.51.0` - `github.com/nats-io/nats.go` to `v1.22.1` +- Minimum go version to v1.18 ### Updating from v0.35.0 diff --git a/Makefile b/Makefile index 2133e1fef..f54d8767f 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 HUB_IMAGE ?= truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" -GO_VERSION ?= 1.17 +GO_VERSION ?= 1.19 LINT_VERSION ?= 1.50.0 ARCH = amd64 diff --git a/README.md b/README.md index 1ed919467..862c9c419 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ The latest version of neofs-node works with neofs-contract # Building -To make all binaries you need Go 1.17+ and `make`: +To make all binaries you need Go 1.18+ and `make`: ``` make all ``` diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index 407253e40..1cc28702d 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -12,35 +12,35 @@ import ( cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "github.com/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/TrueCloudLab/frostfs-sdk-go/user" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" ) -type netValueReader func(interface{}) (interface{}, error) +type netValueReader[K any, V any] func(K) (V, error) -type valueWithTime struct { - v interface{} +type valueWithTime[V any] struct { + v V t time.Time // cached error in order to not repeat failed request for some time e error } // entity that provides TTL cache interface. -type ttlNetCache struct { +type ttlNetCache[K comparable, V any] struct { ttl time.Duration sz int - cache *lru.Cache + cache *lru.Cache[K, *valueWithTime[V]] - netRdr netValueReader + netRdr netValueReader[K, V] } // complicates netValueReader with TTL caching mechanism. -func newNetworkTTLCache(sz int, ttl time.Duration, netRdr netValueReader) *ttlNetCache { - cache, err := lru.New(sz) +func newNetworkTTLCache[K comparable, V any](sz int, ttl time.Duration, netRdr netValueReader[K, V]) *ttlNetCache[K, V] { + cache, err := lru.New[K, *valueWithTime[V]](sz) fatalOnErr(err) - return &ttlNetCache{ + return &ttlNetCache[K, V]{ ttl: ttl, sz: sz, cache: cache, @@ -53,47 +53,45 @@ func newNetworkTTLCache(sz int, ttl time.Duration, netRdr netValueReader) *ttlNe // updates the value from the network on cache miss or by TTL. // // returned value should not be modified. -func (c *ttlNetCache) get(key interface{}) (interface{}, error) { +func (c *ttlNetCache[K, V]) get(key K) (V, error) { val, ok := c.cache.Peek(key) if ok { - valWithTime := val.(*valueWithTime) - - if time.Since(valWithTime.t) < c.ttl { - return valWithTime.v, valWithTime.e + if time.Since(val.t) < c.ttl { + return val.v, val.e } c.cache.Remove(key) } - val, err := c.netRdr(key) + v, err := c.netRdr(key) - c.set(key, val, err) + c.set(key, v, err) - return val, err + return v, err } -func (c *ttlNetCache) set(k, v interface{}, e error) { - c.cache.Add(k, &valueWithTime{ +func (c *ttlNetCache[K, V]) set(k K, v V, e error) { + c.cache.Add(k, &valueWithTime[V]{ v: v, t: time.Now(), e: e, }) } -func (c *ttlNetCache) remove(key interface{}) { +func (c *ttlNetCache[K, V]) remove(key K) { c.cache.Remove(key) } // entity that provides LRU cache interface. type lruNetCache struct { - cache *lru.Cache + cache *lru.Cache[uint64, *netmapSDK.NetMap] - netRdr netValueReader + netRdr netValueReader[uint64, *netmapSDK.NetMap] } // newNetworkLRUCache returns wrapper over netValueReader with LRU cache. -func newNetworkLRUCache(sz int, netRdr netValueReader) *lruNetCache { - cache, err := lru.New(sz) +func newNetworkLRUCache(sz int, netRdr netValueReader[uint64, *netmapSDK.NetMap]) *lruNetCache { + cache, err := lru.New[uint64, *netmapSDK.NetMap](sz) fatalOnErr(err) return &lruNetCache{ @@ -107,7 +105,7 @@ func newNetworkLRUCache(sz int, netRdr netValueReader) *lruNetCache { // updates the value from the network on cache miss. // // returned value should not be modified. -func (c *lruNetCache) get(key interface{}) (interface{}, error) { +func (c *lruNetCache) get(key uint64) (*netmapSDK.NetMap, error) { val, ok := c.cache.Get(key) if ok { return val, nil @@ -125,73 +123,53 @@ func (c *lruNetCache) get(key interface{}) (interface{}, error) { // wrapper over TTL cache of values read from the network // that implements container storage. -type ttlContainerStorage ttlNetCache +type ttlContainerStorage struct { + *ttlNetCache[cid.ID, *container.Container] +} -func newCachedContainerStorage(v container.Source, ttl time.Duration) *ttlContainerStorage { +func newCachedContainerStorage(v container.Source, ttl time.Duration) ttlContainerStorage { const containerCacheSize = 100 - lruCnrCache := newNetworkTTLCache(containerCacheSize, ttl, func(key interface{}) (interface{}, error) { - var id cid.ID - - err := id.DecodeString(key.(string)) - if err != nil { - return nil, err - } - + lruCnrCache := newNetworkTTLCache[cid.ID, *container.Container](containerCacheSize, ttl, func(id cid.ID) (*container.Container, error) { return v.Get(id) }) - return (*ttlContainerStorage)(lruCnrCache) + return ttlContainerStorage{lruCnrCache} } -func (s *ttlContainerStorage) handleRemoval(cnr cid.ID) { - (*ttlNetCache)(s).set(cnr.EncodeToString(), nil, apistatus.ContainerNotFound{}) +func (s ttlContainerStorage) handleRemoval(cnr cid.ID) { + s.set(cnr, nil, apistatus.ContainerNotFound{}) } // Get returns container value from the cache. If value is missing in the cache // or expired, then it returns value from side chain and updates the cache. -func (s *ttlContainerStorage) Get(cnr cid.ID) (*container.Container, error) { - val, err := (*ttlNetCache)(s).get(cnr.EncodeToString()) - if err != nil { - return nil, err - } - - return val.(*container.Container), nil +func (s ttlContainerStorage) Get(cnr cid.ID) (*container.Container, error) { + return s.get(cnr) } -type ttlEACLStorage ttlNetCache +type ttlEACLStorage struct { + *ttlNetCache[cid.ID, *container.EACL] +} -func newCachedEACLStorage(v container.EACLSource, ttl time.Duration) *ttlEACLStorage { +func newCachedEACLStorage(v container.EACLSource, ttl time.Duration) ttlEACLStorage { const eaclCacheSize = 100 - lruCnrCache := newNetworkTTLCache(eaclCacheSize, ttl, func(key interface{}) (interface{}, error) { - var id cid.ID - - err := id.DecodeString(key.(string)) - if err != nil { - return nil, err - } - + lruCnrCache := newNetworkTTLCache(eaclCacheSize, ttl, func(id cid.ID) (*container.EACL, error) { return v.GetEACL(id) }) - return (*ttlEACLStorage)(lruCnrCache) + return ttlEACLStorage{lruCnrCache} } // GetEACL returns eACL value from the cache. If value is missing in the cache // or expired, then it returns value from side chain and updates cache. -func (s *ttlEACLStorage) GetEACL(cnr cid.ID) (*container.EACL, error) { - val, err := (*ttlNetCache)(s).get(cnr.EncodeToString()) - if err != nil { - return nil, err - } - - return val.(*container.EACL), nil +func (s ttlEACLStorage) GetEACL(cnr cid.ID) (*container.EACL, error) { + return s.get(cnr) } // InvalidateEACL removes cached eACL value. -func (s *ttlEACLStorage) InvalidateEACL(cnr cid.ID) { - (*ttlNetCache)(s).remove(cnr.EncodeToString()) +func (s ttlEACLStorage) InvalidateEACL(cnr cid.ID) { + s.remove(cnr) } type lruNetmapSource struct { @@ -203,8 +181,8 @@ type lruNetmapSource struct { func newCachedNetmapStorage(s netmap.State, v netmap.Source) netmap.Source { const netmapCacheSize = 10 - lruNetmapCache := newNetworkLRUCache(netmapCacheSize, func(key interface{}) (interface{}, error) { - return v.GetNetMapByEpoch(key.(uint64)) + lruNetmapCache := newNetworkLRUCache(netmapCacheSize, func(key uint64) (*netmapSDK.NetMap, error) { + return v.GetNetMapByEpoch(key) }) return &lruNetmapSource{ @@ -227,7 +205,7 @@ func (s *lruNetmapSource) getNetMapByEpoch(epoch uint64) (*netmapSDK.NetMap, err return nil, err } - return val.(*netmapSDK.NetMap), nil + return val, nil } func (s *lruNetmapSource) Epoch() (uint64, error) { @@ -236,7 +214,9 @@ func (s *lruNetmapSource) Epoch() (uint64, error) { // wrapper over TTL cache of values read from the network // that implements container lister. -type ttlContainerLister ttlNetCache +type ttlContainerLister struct { + *ttlNetCache[string, *cacheItemContainerList] +} // value type for ttlNetCache used by ttlContainerLister. type cacheItemContainerList struct { @@ -246,14 +226,11 @@ type cacheItemContainerList struct { list []cid.ID } -func newCachedContainerLister(c *cntClient.Client, ttl time.Duration) *ttlContainerLister { +func newCachedContainerLister(c *cntClient.Client, ttl time.Duration) ttlContainerLister { const containerListerCacheSize = 100 - lruCnrListerCache := newNetworkTTLCache(containerListerCacheSize, ttl, func(key interface{}) (interface{}, error) { - var ( - id *user.ID - strID = key.(string) - ) + lruCnrListerCache := newNetworkTTLCache(containerListerCacheSize, ttl, func(strID string) (*cacheItemContainerList, error) { + var id *user.ID if strID != "" { id = new(user.ID) @@ -274,28 +251,24 @@ func newCachedContainerLister(c *cntClient.Client, ttl time.Duration) *ttlContai }, nil }) - return (*ttlContainerLister)(lruCnrListerCache) + return ttlContainerLister{lruCnrListerCache} } // List returns list of container IDs from the cache. If list is missing in the // cache or expired, then it returns container IDs from side chain and updates // the cache. -func (s *ttlContainerLister) List(id *user.ID) ([]cid.ID, error) { +func (s ttlContainerLister) List(id *user.ID) ([]cid.ID, error) { var str string if id != nil { str = id.EncodeToString() } - val, err := (*ttlNetCache)(s).get(str) + item, err := s.get(str) if err != nil { return nil, err } - // panic on typecast below is OK since developer must be careful, - // runtime can do nothing with wrong type occurrence - item := val.(*cacheItemContainerList) - item.mtx.RLock() res := make([]cid.ID, len(item.list)) copy(res, item.list) @@ -314,16 +287,14 @@ func (s *ttlContainerLister) List(id *user.ID) ([]cid.ID, error) { func (s *ttlContainerLister) update(owner user.ID, cnr cid.ID, add bool) { strOwner := owner.EncodeToString() - val, ok := (*ttlNetCache)(s).cache.Get(strOwner) + val, ok := s.cache.Get(strOwner) if !ok { // we could cache the single cnr but in this case we will disperse // with the Sidechain a lot return } - // panic on typecast below is OK since developer must be careful, - // runtime can do nothing with wrong type occurrence - item := val.(*valueWithTime).v.(*cacheItemContainerList) + item := val.v item.mtx.Lock() { @@ -349,9 +320,11 @@ func (s *ttlContainerLister) update(owner user.ID, cnr cid.ID, add bool) { item.mtx.Unlock() } -type cachedIRFetcher ttlNetCache +type cachedIRFetcher struct { + *ttlNetCache[struct{}, [][]byte] +} -func newCachedIRFetcher(f interface{ InnerRingKeys() ([][]byte, error) }) *cachedIRFetcher { +func newCachedIRFetcher(f interface{ InnerRingKeys() ([][]byte, error) }) cachedIRFetcher { const ( irFetcherCacheSize = 1 // we intend to store only one value @@ -364,25 +337,25 @@ func newCachedIRFetcher(f interface{ InnerRingKeys() ([][]byte, error) }) *cache irFetcherCacheTTL = 30 * time.Second ) - irFetcherCache := newNetworkTTLCache(irFetcherCacheSize, irFetcherCacheTTL, - func(key interface{}) (interface{}, error) { + irFetcherCache := newNetworkTTLCache[struct{}, [][]byte](irFetcherCacheSize, irFetcherCacheTTL, + func(_ struct{}) ([][]byte, error) { return f.InnerRingKeys() }, ) - return (*cachedIRFetcher)(irFetcherCache) + return cachedIRFetcher{irFetcherCache} } // InnerRingKeys returns cached list of Inner Ring keys. If keys are missing in // the cache or expired, then it returns keys from side chain and updates // the cache. -func (f *cachedIRFetcher) InnerRingKeys() ([][]byte, error) { - val, err := (*ttlNetCache)(f).get("") +func (f cachedIRFetcher) InnerRingKeys() ([][]byte, error) { + val, err := f.get(struct{}{}) if err != nil { return nil, err } - return val.([][]byte), nil + return val, nil } type ttlMaxObjectSizeCache struct { diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index d39d49899..5c74eb139 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -657,8 +657,8 @@ type morphContainerWriter struct { neoClient *cntClient.Client cacheEnabled bool - eacls *ttlEACLStorage - lists *ttlContainerLister + eacls ttlEACLStorage + lists ttlContainerLister } func (m morphContainerWriter) Put(cnr containerCore.Container) (*cid.ID, error) { diff --git a/go.mod b/go.mod index 23ec405a8..b7758b927 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/TrueCloudLab/frostfs-node -go 1.17 +go 1.18 require ( github.com/TrueCloudLab/frostfs-api-go/v2 v2.0.0-20221212144048-1351b6656d68 @@ -13,7 +13,7 @@ require ( github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/google/go-github/v39 v39.2.0 github.com/google/uuid v1.3.0 - github.com/hashicorp/golang-lru v0.5.4 + github.com/hashicorp/golang-lru/v2 v2.0.1 github.com/klauspost/compress v1.15.13 github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 @@ -54,6 +54,7 @@ require ( github.com/golang/snappy v0.0.3 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect diff --git a/go.sum b/go.sum index 582d41a50..1d85e41cb 100644 Binary files a/go.sum and b/go.sum differ diff --git a/pkg/innerring/processors/neofs/process_assets.go b/pkg/innerring/processors/neofs/process_assets.go index 2fdd55ad6..aa752035e 100644 --- a/pkg/innerring/processors/neofs/process_assets.go +++ b/pkg/innerring/processors/neofs/process_assets.go @@ -42,10 +42,10 @@ func (np *Processor) processDeposit(deposit *frostfsEvent.Deposit) { defer np.mintEmitLock.Unlock() val, ok := np.mintEmitCache.Get(receiver.String()) - if ok && val.(uint64)+np.mintEmitThreshold >= curEpoch { + if ok && val+np.mintEmitThreshold >= curEpoch { np.log.Warn("double mint emission declined", zap.String("receiver", receiver.String()), - zap.Uint64("last_emission", val.(uint64)), + zap.Uint64("last_emission", val), zap.Uint64("current_epoch", curEpoch)) return diff --git a/pkg/innerring/processors/neofs/processor.go b/pkg/innerring/processors/neofs/processor.go index 8435a9315..54c782539 100644 --- a/pkg/innerring/processors/neofs/processor.go +++ b/pkg/innerring/processors/neofs/processor.go @@ -12,7 +12,7 @@ import ( "github.com/TrueCloudLab/frostfs-node/pkg/morph/event" frostfsEvent "github.com/TrueCloudLab/frostfs-node/pkg/morph/event/neofs" "github.com/TrueCloudLab/frostfs-node/pkg/util/logger" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" @@ -47,7 +47,7 @@ type ( alphabetState AlphabetState converter PrecisionConverter mintEmitLock *sync.Mutex - mintEmitCache *lru.Cache + mintEmitCache *lru.Cache[string, uint64] mintEmitThreshold uint64 mintEmitValue fixedn.Fixed8 gasBalanceThreshold int64 @@ -105,7 +105,7 @@ func New(p *Params) (*Processor, error) { return nil, fmt.Errorf("ir/frostfs: can't create worker pool: %w", err) } - lruCache, err := lru.New(p.MintEmitCacheSize) + lruCache, err := lru.New[string, uint64](p.MintEmitCacheSize) if err != nil { return nil, fmt.Errorf("ir/frostfs: can't create LRU cache for gas emission: %w", err) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 9b9b4b8b1..27ae81546 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -13,7 +13,7 @@ import ( "github.com/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/TrueCloudLab/hrw" - "github.com/hashicorp/golang-lru/simplelru" + "github.com/hashicorp/golang-lru/v2/simplelru" "go.uber.org/zap" ) @@ -61,7 +61,7 @@ type Blobovniczas struct { cfg // cache of opened filled Blobovniczas - opened *simplelru.LRU + opened *simplelru.LRU[string, *blobovnicza.Blobovnicza] // lruMtx protects opened cache. // It isn't RWMutex because `Get` calls must // lock this mutex on write, as LRU info is updated. @@ -97,21 +97,20 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { opts[i](&blz.cfg) } - cache, err := simplelru.NewLRU(blz.openedCacheSize, func(key interface{}, value interface{}) { - p := key.(string) + cache, err := simplelru.NewLRU[string, *blobovnicza.Blobovnicza](blz.openedCacheSize, func(p string, value *blobovnicza.Blobovnicza) { lvlPath := filepath.Dir(p) if b, ok := blz.active[lvlPath]; ok && b.ind == u64FromHexString(filepath.Base(p)) { // This branch is taken if we have recently updated active blobovnicza and remove // it from opened cache. return - } else if err := value.(*blobovnicza.Blobovnicza).Close(); err != nil { + } else if err := value.Close(); err != nil { blz.log.Error("could not close Blobovnicza", - zap.String("id", key.(string)), + zap.String("id", p), zap.String("error", err.Error()), ) } else { blz.log.Debug("blobovnicza successfully closed on evict", - zap.String("id", key.(string)), + zap.String("id", p), ) } }) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index 1cae8643a..1c8a5e85b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -57,11 +57,10 @@ func (b *Blobovniczas) Close() error { b.opened.Remove(p) } for _, k := range b.opened.Keys() { - v, _ := b.opened.Get(k) - blz := v.(*blobovnicza.Blobovnicza) + blz, _ := b.opened.Get(k) if err := blz.Close(); err != nil { b.log.Debug("could not close active blobovnicza", - zap.String("path", k.(string)), + zap.String("path", k), zap.String("error", err.Error()), ) } @@ -86,7 +85,7 @@ func (b *Blobovniczas) openBlobovnicza(p string) (*blobovnicza.Blobovnicza, erro b.lruMtx.Unlock() if ok { // blobovnicza should be opened in cache - return v.(*blobovnicza.Blobovnicza), nil + return v, nil } lvlPath := filepath.Dir(p) @@ -105,7 +104,7 @@ func (b *Blobovniczas) openBlobovnicza(p string) (*blobovnicza.Blobovnicza, erro v, ok = b.opened.Get(p) if ok { - return v.(*blobovnicza.Blobovnicza), nil + return v, nil } blz, err := b.openBlobovniczaNoCache(p) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 25e0dcb47..01e8b044f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -80,7 +80,7 @@ func (b *Blobovniczas) deleteObjectFromLevel(prm blobovnicza.DeletePrm, blzPath v, ok := b.opened.Get(blzPath) b.lruMtx.Unlock() if ok { - if res, err := b.deleteObject(v.(*blobovnicza.Blobovnicza), prm, dp); err == nil { + if res, err := b.deleteObject(v, prm, dp); err == nil { return res, err } else if !blobovnicza.IsErrNotFound(err) { b.log.Debug("could not remove object from opened blobovnicza", diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index b98c14450..3c7998f97 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -72,7 +72,7 @@ func (b *Blobovniczas) getObjectFromLevel(prm blobovnicza.GetPrm, blzPath string v, ok := b.opened.Get(blzPath) b.lruMtx.Unlock() if ok { - if res, err := b.getObject(v.(*blobovnicza.Blobovnicza), prm); err == nil { + if res, err := b.getObject(v, prm); err == nil { return res, err } else if !blobovnicza.IsErrNotFound(err) { b.log.Debug("could not read object from opened blobovnicza", diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 1ead1d1e4..4eab32157 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -76,7 +76,7 @@ func (b *Blobovniczas) getRangeFromLevel(prm common.GetRangePrm, blzPath string, v, ok := b.opened.Get(blzPath) b.lruMtx.Unlock() if ok { - res, err := b.getObjectRange(v.(*blobovnicza.Blobovnicza), prm) + res, err := b.getObjectRange(v, prm) switch { case err == nil, isErrOutOfRange(err): diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index bb65a612a..4a9724f4d 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -11,8 +11,8 @@ import ( "github.com/TrueCloudLab/frostfs-node/pkg/util" apistatus "github.com/TrueCloudLab/frostfs-sdk-go/client/status" oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id" - lru "github.com/hashicorp/golang-lru" - "github.com/hashicorp/golang-lru/simplelru" + lru "github.com/hashicorp/golang-lru/v2" + "github.com/hashicorp/golang-lru/v2/simplelru" "go.etcd.io/bbolt" "go.uber.org/zap" ) @@ -23,7 +23,7 @@ type store struct { maxFlushedMarksCount int maxRemoveBatchSize int - flushed simplelru.LRUCache + flushed simplelru.LRUCache[string, bool] db *bbolt.DB dbKeysToRemove []string @@ -69,7 +69,7 @@ func (c *cache) openStore(readOnly bool) error { // Write-cache can be opened multiple times during `SetMode`. // flushed map must not be re-created in this case. if c.flushed == nil { - c.flushed, _ = lru.NewWithEvict(c.maxFlushedMarksCount, c.removeFlushed) + c.flushed, _ = lru.NewWithEvict[string, bool](c.maxFlushedMarksCount, c.removeFlushed) } return nil } @@ -78,12 +78,12 @@ func (c *cache) openStore(readOnly bool) error { // To minimize interference with the client operations, the actual removal // is done in batches. // It is not thread-safe and is used only as an evict callback to LRU cache. -func (c *cache) removeFlushed(key, value interface{}) { - fromDatabase := value.(bool) +func (c *cache) removeFlushed(key string, value bool) { + fromDatabase := value if fromDatabase { - c.dbKeysToRemove = append(c.dbKeysToRemove, key.(string)) + c.dbKeysToRemove = append(c.dbKeysToRemove, key) } else { - c.fsKeysToRemove = append(c.fsKeysToRemove, key.(string)) + c.fsKeysToRemove = append(c.fsKeysToRemove, key) } if len(c.dbKeysToRemove)+len(c.fsKeysToRemove) >= c.maxRemoveBatchSize { diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index e2684bfe0..fbe416f15 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -9,7 +9,7 @@ import ( "time" "github.com/TrueCloudLab/frostfs-node/pkg/util/logger" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -96,7 +96,7 @@ type cache struct { nnsHash *util.Uint160 gKey *keys.PublicKey - txHeights *lru.Cache + txHeights *lru.Cache[util.Uint256, uint32] } func (c cache) nns() *util.Uint160 { diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index 7cdb2e0e1..5adc1c2fc 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -8,7 +8,7 @@ import ( "time" "github.com/TrueCloudLab/frostfs-node/pkg/util/logger" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/rpcclient" @@ -185,7 +185,7 @@ func newActor(ws *rpcclient.WSClient, acc *wallet.Account, cfg cfg) (*actor.Acto } func newClientCache() cache { - c, _ := lru.New(100) // returns error only if size is negative + c, _ := lru.New[util.Uint256, uint32](100) // returns error only if size is negative return cache{ m: &sync.RWMutex{}, txHeights: c, diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 8f20dcb81..334fcda9d 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -892,7 +892,7 @@ func (c *Client) CalculateNonceAndVUB(hash util.Uint256) (nonce uint32, vub uint func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) { if rh, ok := c.cache.txHeights.Get(h); ok { - return rh.(uint32), nil + return rh, nil } height, err := c.client.GetTransactionHeight(h) if err != nil { diff --git a/pkg/services/object_manager/placement/netmap.go b/pkg/services/object_manager/placement/netmap.go index c2d908be2..eb2a0f2f1 100644 --- a/pkg/services/object_manager/placement/netmap.go +++ b/pkg/services/object_manager/placement/netmap.go @@ -9,7 +9,7 @@ import ( cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "github.com/TrueCloudLab/frostfs-sdk-go/netmap" oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/hashicorp/golang-lru/simplelru" + "github.com/hashicorp/golang-lru/v2/simplelru" ) type netMapBuilder struct { @@ -19,7 +19,7 @@ type netMapBuilder struct { lastNm *netmapSDK.NetMap // containerCache caches container nodes by ID. It is used to skip `GetContainerNodes` invocation if // neither netmap nor container has changed. - containerCache simplelru.LRUCache + containerCache simplelru.LRUCache[string, [][]netmapSDK.NodeInfo] } type netMapSrc struct { @@ -32,7 +32,7 @@ type netMapSrc struct { const defaultContainerCacheSize = 10 func NewNetworkMapBuilder(nm *netmapSDK.NetMap) Builder { - cache, _ := simplelru.NewLRU(defaultContainerCacheSize, nil) // no error + cache, _ := simplelru.NewLRU[string, [][]netmapSDK.NodeInfo](defaultContainerCacheSize, nil) // no error return &netMapBuilder{ nmSrc: &netMapSrc{nm: nm}, containerCache: cache, @@ -40,7 +40,7 @@ func NewNetworkMapBuilder(nm *netmapSDK.NetMap) Builder { } func NewNetworkMapSourceBuilder(nmSrc netmap.Source) Builder { - cache, _ := simplelru.NewLRU(defaultContainerCacheSize, nil) // no error + cache, _ := simplelru.NewLRU[string, [][]netmapSDK.NodeInfo](defaultContainerCacheSize, nil) // no error return &netMapBuilder{ nmSrc: nmSrc, containerCache: cache, @@ -65,8 +65,7 @@ func (b *netMapBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, p netmapSDK.Plac raw, ok := b.containerCache.Get(string(binCnr)) b.mtx.Unlock() if ok { - cn := raw.([][]netmapSDK.NodeInfo) - return BuildObjectPlacement(nm, cn, obj) + return BuildObjectPlacement(nm, raw, obj) } } else { b.containerCache.Purge() diff --git a/pkg/services/object_manager/tombstone/checker.go b/pkg/services/object_manager/tombstone/checker.go index ea2acb408..f062f0c3c 100644 --- a/pkg/services/object_manager/tombstone/checker.go +++ b/pkg/services/object_manager/tombstone/checker.go @@ -8,7 +8,7 @@ import ( "github.com/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/TrueCloudLab/frostfs-sdk-go/object" oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "go.uber.org/zap" ) @@ -31,7 +31,7 @@ type Source interface { // `ExpirationChecker{}` declarations leads to undefined behaviour // and may lead to panics. type ExpirationChecker struct { - cache *lru.Cache + cache *lru.Cache[string, uint64] log *logger.Logger @@ -51,7 +51,7 @@ func (g *ExpirationChecker) IsTombstoneAvailable(ctx context.Context, a oid.Addr expEpoch, ok := g.cache.Get(addrStr) if ok { - return expEpoch.(uint64) > epoch + return expEpoch > epoch } ts, err := g.tsSource.Tombstone(ctx, a, epoch) diff --git a/pkg/services/object_manager/tombstone/constructor.go b/pkg/services/object_manager/tombstone/constructor.go index e61b561ea..cc0b664b0 100644 --- a/pkg/services/object_manager/tombstone/constructor.go +++ b/pkg/services/object_manager/tombstone/constructor.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/TrueCloudLab/frostfs-node/pkg/util/logger" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "go.uber.org/zap" ) @@ -48,7 +48,7 @@ func NewChecker(oo ...Option) *ExpirationChecker { panicOnNil(cfg.tsSource, "Tombstone source") - cache, err := lru.New(cfg.cacheSize) + cache, err := lru.New[string, uint64](cfg.cacheSize) if err != nil { panic(fmt.Errorf("could not create LRU cache with %d size: %w", cfg.cacheSize, err)) } diff --git a/pkg/services/policer/policer.go b/pkg/services/policer/policer.go index 2245ab792..e556e7959 100644 --- a/pkg/services/policer/policer.go +++ b/pkg/services/policer/policer.go @@ -12,7 +12,7 @@ import ( "github.com/TrueCloudLab/frostfs-node/pkg/services/replicator" "github.com/TrueCloudLab/frostfs-node/pkg/util/logger" oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id" - lru "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru/v2" "github.com/panjf2000/ants/v2" "go.uber.org/zap" ) @@ -53,7 +53,7 @@ func (oiw *objectsInWork) add(addr oid.Address) { type Policer struct { *cfg - cache *lru.Cache + cache *lru.Cache[oid.Address, time.Time] objsInWork *objectsInWork } @@ -115,7 +115,7 @@ func New(opts ...Option) *Policer { c.log = &logger.Logger{Logger: c.log.With(zap.String("component", "Object Policer"))} - cache, err := lru.New(int(c.cacheSize)) + cache, err := lru.New[oid.Address, time.Time](int(c.cacheSize)) if err != nil { panic(err) } diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index 042bc20c9..eeb9fe491 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -56,7 +56,7 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { err = p.taskPool.Submit(func() { v, ok := p.cache.Get(addr.Address) - if ok && time.Since(v.(time.Time)) < p.evictDuration { + if ok && time.Since(v) < p.evictDuration { return } diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index 8e2d19620..52f3c6471 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -9,7 +9,7 @@ import ( "time" "github.com/TrueCloudLab/frostfs-node/pkg/network" - "github.com/hashicorp/golang-lru/simplelru" + "github.com/hashicorp/golang-lru/v2/simplelru" "google.golang.org/grpc" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/credentials/insecure" @@ -17,7 +17,7 @@ import ( type clientCache struct { sync.Mutex - simplelru.LRU + simplelru.LRU[string, cacheItem] } type cacheItem struct { @@ -34,8 +34,8 @@ const ( var errRecentlyFailed = errors.New("client has recently failed") func (c *clientCache) init() { - l, _ := simplelru.NewLRU(defaultClientCacheSize, func(key, value interface{}) { - _ = value.(*grpc.ClientConn).Close() + l, _ := simplelru.NewLRU[string, cacheItem](defaultClientCacheSize, func(_ string, value cacheItem) { + _ = value.cc.Close() }) c.LRU = *l } @@ -46,7 +46,7 @@ func (c *clientCache) get(ctx context.Context, netmapAddr string) (TreeServiceCl c.Unlock() if ok { - item := ccInt.(cacheItem) + item := ccInt if item.cc == nil { if d := time.Since(item.lastTry); d < defaultReconnectInterval { return nil, fmt.Errorf("%w: %s till the next reconnection to %s", diff --git a/pkg/services/tree/container.go b/pkg/services/tree/container.go index 462c906aa..98ec2903e 100644 --- a/pkg/services/tree/container.go +++ b/pkg/services/tree/container.go @@ -10,17 +10,17 @@ import ( "github.com/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" cidSDK "github.com/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "github.com/TrueCloudLab/frostfs-sdk-go/netmap" - "github.com/hashicorp/golang-lru/simplelru" + "github.com/hashicorp/golang-lru/v2/simplelru" ) type containerCache struct { sync.Mutex nm *netmapSDK.NetMap - lru *simplelru.LRU + lru *simplelru.LRU[string, containerCacheItem] } func (c *containerCache) init(size int) { - c.lru, _ = simplelru.NewLRU(size, nil) // no error, size is positive + c.lru, _ = simplelru.NewLRU[string, containerCacheItem](size, nil) // no error, size is positive } type containerCacheItem struct { @@ -48,8 +48,7 @@ func (s *Service) getContainerNodes(cid cidSDK.ID) ([]netmapSDK.NodeInfo, int, e s.containerCache.Lock() if s.containerCache.nm != nm { s.containerCache.lru.Purge() - } else if v, ok := s.containerCache.lru.Get(cidStr); ok { - item := v.(containerCacheItem) + } else if item, ok := s.containerCache.lru.Get(cidStr); ok { if item.cnr == cnr { s.containerCache.Unlock() return item.nodes, item.local, nil