mirror of https://github.com/knative/pkg.git
Bump github.com/hashicorp/golang-lru from 0.5.4 to 1.0.2 (#2804)
* Bump github.com/hashicorp/golang-lru from 0.5.4 to 1.0.2 Bumps [github.com/hashicorp/golang-lru](https://github.com/hashicorp/golang-lru) from 0.5.4 to 1.0.2. - [Release notes](https://github.com/hashicorp/golang-lru/releases) - [Commits](https://github.com/hashicorp/golang-lru/compare/v0.5.4...v1.0.2) --- updated-dependencies: - dependency-name: github.com/hashicorp/golang-lru dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Run ./hack/update-codegen.sh --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
d36cc5925a
commit
2ad39e9393
2
go.mod
2
go.mod
|
@ -21,7 +21,7 @@ require (
|
||||||
github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3
|
github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/hashicorp/golang-lru v0.5.4
|
github.com/hashicorp/golang-lru v1.0.2
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
github.com/openzipkin/zipkin-go v0.4.1
|
github.com/openzipkin/zipkin-go v0.4.1
|
||||||
github.com/prometheus/client_golang v1.16.0
|
github.com/prometheus/client_golang v1.16.0
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -238,8 +238,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjd
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- megacheck
|
||||||
|
- revive
|
||||||
|
- govet
|
||||||
|
- unconvert
|
||||||
|
- megacheck
|
||||||
|
- gas
|
||||||
|
- gocyclo
|
||||||
|
- dupl
|
||||||
|
- misspell
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- typecheck
|
||||||
|
- ineffassign
|
||||||
|
- stylecheck
|
||||||
|
- exportloopref
|
||||||
|
- gocritic
|
||||||
|
- nakedret
|
||||||
|
- gosimple
|
||||||
|
- prealloc
|
||||||
|
fast: false
|
||||||
|
disable-all: true
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
exclude-use-default: false
|
|
@ -44,7 +44,7 @@ func New2Q(size int) (*TwoQueueCache, error) {
|
||||||
|
|
||||||
// New2QParams creates a new TwoQueueCache using the provided
|
// New2QParams creates a new TwoQueueCache using the provided
|
||||||
// parameter values.
|
// parameter values.
|
||||||
func New2QParams(size int, recentRatio float64, ghostRatio float64) (*TwoQueueCache, error) {
|
func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, fmt.Errorf("invalid size")
|
return nil, fmt.Errorf("invalid size")
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,6 @@ func (c *TwoQueueCache) Add(key, value interface{}) {
|
||||||
// Add to the recently seen list
|
// Add to the recently seen list
|
||||||
c.ensureSpace(false)
|
c.ensureSpace(false)
|
||||||
c.recent.Add(key, value)
|
c.recent.Add(key, value)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureSpace is used to ensure we have space in the cache
|
// ensureSpace is used to ensure we have space in the cache
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
Copyright (c) 2014 HashiCorp, Inc.
|
||||||
|
|
||||||
Mozilla Public License, version 2.0
|
Mozilla Public License, version 2.0
|
||||||
|
|
||||||
1. Definitions
|
1. Definitions
|
||||||
|
|
|
@ -1,25 +1,7 @@
|
||||||
golang-lru
|
golang-lru
|
||||||
==========
|
==========
|
||||||
|
|
||||||
This provides the `lru` package which implements a fixed-size
|
Please upgrade to github.com/hashicorp/golang-lru/v2 for all new code as v1 will
|
||||||
thread safe LRU cache. It is based on the cache in Groupcache.
|
not be updated anymore. The v2 version supports generics and is faster; old code
|
||||||
|
can specify a specific tag, e.g. github.com/hashicorp/golang-lru/v1.0.2 for
|
||||||
Documentation
|
backwards compatibility.
|
||||||
=============
|
|
||||||
|
|
||||||
Full docs are available on [Godoc](http://godoc.org/github.com/hashicorp/golang-lru)
|
|
||||||
|
|
||||||
Example
|
|
||||||
=======
|
|
||||||
|
|
||||||
Using the LRU is very simple:
|
|
||||||
|
|
||||||
```go
|
|
||||||
l, _ := New(128)
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
l.Add(i, nil)
|
|
||||||
}
|
|
||||||
if l.Len() != 128 {
|
|
||||||
panic(fmt.Sprintf("bad len: %v", l.Len()))
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
@ -173,7 +173,6 @@ func (c *ARCCache) Add(key, value interface{}) {
|
||||||
|
|
||||||
// Add to the recently seen list
|
// Add to the recently seen list
|
||||||
c.t1.Add(key, value)
|
c.t1.Add(key, value)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace is used to adaptively evict from either T1 or T2
|
// replace is used to adaptively evict from either T1 or T2
|
||||||
|
|
|
@ -6,10 +6,17 @@ import (
|
||||||
"github.com/hashicorp/golang-lru/simplelru"
|
"github.com/hashicorp/golang-lru/simplelru"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultEvictedBufferSize defines the default buffer size to store evicted key/val
|
||||||
|
DefaultEvictedBufferSize = 16
|
||||||
|
)
|
||||||
|
|
||||||
// Cache is a thread-safe fixed size LRU cache.
|
// Cache is a thread-safe fixed size LRU cache.
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
lru simplelru.LRUCache
|
lru *simplelru.LRU
|
||||||
lock sync.RWMutex
|
evictedKeys, evictedVals []interface{}
|
||||||
|
onEvictedCB func(k, v interface{})
|
||||||
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates an LRU of the given size.
|
// New creates an LRU of the given size.
|
||||||
|
@ -19,30 +26,63 @@ func New(size int) (*Cache, error) {
|
||||||
|
|
||||||
// NewWithEvict constructs a fixed size cache with the given eviction
|
// NewWithEvict constructs a fixed size cache with the given eviction
|
||||||
// callback.
|
// callback.
|
||||||
func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
|
func NewWithEvict(size int, onEvicted func(key, value interface{})) (c *Cache, err error) {
|
||||||
lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted))
|
// create a cache with default settings
|
||||||
if err != nil {
|
c = &Cache{
|
||||||
return nil, err
|
onEvictedCB: onEvicted,
|
||||||
}
|
}
|
||||||
c := &Cache{
|
if onEvicted != nil {
|
||||||
lru: lru,
|
c.initEvictBuffers()
|
||||||
|
onEvicted = c.onEvicted
|
||||||
}
|
}
|
||||||
return c, nil
|
c.lru, err = simplelru.NewLRU(size, onEvicted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cache) initEvictBuffers() {
|
||||||
|
c.evictedKeys = make([]interface{}, 0, DefaultEvictedBufferSize)
|
||||||
|
c.evictedVals = make([]interface{}, 0, DefaultEvictedBufferSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// onEvicted save evicted key/val and sent in externally registered callback
|
||||||
|
// outside of critical section
|
||||||
|
func (c *Cache) onEvicted(k, v interface{}) {
|
||||||
|
c.evictedKeys = append(c.evictedKeys, k)
|
||||||
|
c.evictedVals = append(c.evictedVals, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purge is used to completely clear the cache.
|
// Purge is used to completely clear the cache.
|
||||||
func (c *Cache) Purge() {
|
func (c *Cache) Purge() {
|
||||||
|
var ks, vs []interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
c.lru.Purge()
|
c.lru.Purge()
|
||||||
|
if c.onEvictedCB != nil && len(c.evictedKeys) > 0 {
|
||||||
|
ks, vs = c.evictedKeys, c.evictedVals
|
||||||
|
c.initEvictBuffers()
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
// invoke callback outside of critical section
|
||||||
|
if c.onEvictedCB != nil {
|
||||||
|
for i := 0; i < len(ks); i++ {
|
||||||
|
c.onEvictedCB(ks[i], vs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a value to the cache. Returns true if an eviction occurred.
|
// Add adds a value to the cache. Returns true if an eviction occurred.
|
||||||
func (c *Cache) Add(key, value interface{}) (evicted bool) {
|
func (c *Cache) Add(key, value interface{}) (evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
return evicted
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get looks up a key's value from the cache.
|
// Get looks up a key's value from the cache.
|
||||||
|
@ -75,13 +115,21 @@ func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||||
// Returns whether found and whether an eviction occurred.
|
// Returns whether found and whether an eviction occurred.
|
||||||
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
if c.lru.Contains(key) {
|
if c.lru.Contains(key) {
|
||||||
|
c.lock.Unlock()
|
||||||
return true, false
|
return true, false
|
||||||
}
|
}
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return false, evicted
|
return false, evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,47 +137,80 @@ func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||||
// Returns whether found and whether an eviction occurred.
|
// Returns whether found and whether an eviction occurred.
|
||||||
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
|
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
previous, ok = c.lru.Peek(key)
|
previous, ok = c.lru.Peek(key)
|
||||||
if ok {
|
if ok {
|
||||||
|
c.lock.Unlock()
|
||||||
return previous, true, false
|
return previous, true, false
|
||||||
}
|
}
|
||||||
|
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return nil, false, evicted
|
return nil, false, evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the provided key from the cache.
|
// Remove removes the provided key from the cache.
|
||||||
func (c *Cache) Remove(key interface{}) (present bool) {
|
func (c *Cache) Remove(key interface{}) (present bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
present = c.lru.Remove(key)
|
present = c.lru.Remove(key)
|
||||||
|
if c.onEvictedCB != nil && present {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && present {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize changes the cache size.
|
// Resize changes the cache size.
|
||||||
func (c *Cache) Resize(size int) (evicted int) {
|
func (c *Cache) Resize(size int) (evicted int) {
|
||||||
|
var ks, vs []interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
evicted = c.lru.Resize(size)
|
evicted = c.lru.Resize(size)
|
||||||
|
if c.onEvictedCB != nil && evicted > 0 {
|
||||||
|
ks, vs = c.evictedKeys, c.evictedVals
|
||||||
|
c.initEvictBuffers()
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted > 0 {
|
||||||
|
for i := 0; i < len(ks); i++ {
|
||||||
|
c.onEvictedCB(ks[i], vs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
return evicted
|
return evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
func (c *Cache) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *Cache) RemoveOldest() (key, value interface{}, ok bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
key, value, ok = c.lru.RemoveOldest()
|
key, value, ok = c.lru.RemoveOldest()
|
||||||
|
if c.onEvictedCB != nil && ok {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && ok {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
// GetOldest returns the oldest entry
|
||||||
func (c *Cache) GetOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *Cache) GetOldest() (key, value interface{}, ok bool) {
|
||||||
c.lock.Lock()
|
c.lock.RLock()
|
||||||
key, value, ok = c.lru.GetOldest()
|
key, value, ok = c.lru.GetOldest()
|
||||||
c.lock.Unlock()
|
c.lock.RUnlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ type entry struct {
|
||||||
// NewLRU constructs an LRU of the given size
|
// NewLRU constructs an LRU of the given size
|
||||||
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
|
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, errors.New("Must provide a positive size")
|
return nil, errors.New("must provide a positive size")
|
||||||
}
|
}
|
||||||
c := &LRU{
|
c := &LRU{
|
||||||
size: size,
|
size: size,
|
||||||
|
@ -109,7 +109,7 @@ func (c *LRU) Remove(key interface{}) (present bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *LRU) RemoveOldest() (key, value interface{}, ok bool) {
|
||||||
ent := c.evictList.Back()
|
ent := c.evictList.Back()
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
c.removeElement(ent)
|
c.removeElement(ent)
|
||||||
|
@ -120,7 +120,7 @@ func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
// GetOldest returns the oldest entry
|
||||||
func (c *LRU) GetOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *LRU) GetOldest() (key, value interface{}, ok bool) {
|
||||||
ent := c.evictList.Back()
|
ent := c.evictList.Back()
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
kv := ent.Value.(*entry)
|
kv := ent.Value.(*entry)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// Package simplelru provides simple LRU implementation based on build-in container/list.
|
||||||
package simplelru
|
package simplelru
|
||||||
|
|
||||||
// LRUCache is the interface for simple LRU cache.
|
// LRUCache is the interface for simple LRU cache.
|
||||||
|
@ -34,6 +35,6 @@ type LRUCache interface {
|
||||||
// Clears all cache entries.
|
// Clears all cache entries.
|
||||||
Purge()
|
Purge()
|
||||||
|
|
||||||
// Resizes cache, returning number evicted
|
// Resizes cache, returning number evicted
|
||||||
Resize(int) int
|
Resize(int) int
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package lru
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getRand(tb testing.TB) int64 {
|
||||||
|
out, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
|
||||||
|
if err != nil {
|
||||||
|
tb.Fatal(err)
|
||||||
|
}
|
||||||
|
return out.Int64()
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- megacheck
|
||||||
|
- revive
|
||||||
|
- govet
|
||||||
|
- unconvert
|
||||||
|
- megacheck
|
||||||
|
- gas
|
||||||
|
- gocyclo
|
||||||
|
- dupl
|
||||||
|
- misspell
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- typecheck
|
||||||
|
- ineffassign
|
||||||
|
- stylecheck
|
||||||
|
- exportloopref
|
||||||
|
- gocritic
|
||||||
|
- nakedret
|
||||||
|
- gosimple
|
||||||
|
- prealloc
|
||||||
|
fast: false
|
||||||
|
disable-all: true
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
exclude-use-default: false
|
|
@ -44,7 +44,7 @@ func New2Q(size int) (*TwoQueueCache, error) {
|
||||||
|
|
||||||
// New2QParams creates a new TwoQueueCache using the provided
|
// New2QParams creates a new TwoQueueCache using the provided
|
||||||
// parameter values.
|
// parameter values.
|
||||||
func New2QParams(size int, recentRatio float64, ghostRatio float64) (*TwoQueueCache, error) {
|
func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, fmt.Errorf("invalid size")
|
return nil, fmt.Errorf("invalid size")
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,6 @@ func (c *TwoQueueCache) Add(key, value interface{}) {
|
||||||
// Add to the recently seen list
|
// Add to the recently seen list
|
||||||
c.ensureSpace(false)
|
c.ensureSpace(false)
|
||||||
c.recent.Add(key, value)
|
c.recent.Add(key, value)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureSpace is used to ensure we have space in the cache
|
// ensureSpace is used to ensure we have space in the cache
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
Copyright (c) 2014 HashiCorp, Inc.
|
||||||
|
|
||||||
Mozilla Public License, version 2.0
|
Mozilla Public License, version 2.0
|
||||||
|
|
||||||
1. Definitions
|
1. Definitions
|
||||||
|
|
|
@ -1,25 +1,7 @@
|
||||||
golang-lru
|
golang-lru
|
||||||
==========
|
==========
|
||||||
|
|
||||||
This provides the `lru` package which implements a fixed-size
|
Please upgrade to github.com/hashicorp/golang-lru/v2 for all new code as v1 will
|
||||||
thread safe LRU cache. It is based on the cache in Groupcache.
|
not be updated anymore. The v2 version supports generics and is faster; old code
|
||||||
|
can specify a specific tag, e.g. github.com/hashicorp/golang-lru/v1.0.2 for
|
||||||
Documentation
|
backwards compatibility.
|
||||||
=============
|
|
||||||
|
|
||||||
Full docs are available on [Godoc](http://godoc.org/github.com/hashicorp/golang-lru)
|
|
||||||
|
|
||||||
Example
|
|
||||||
=======
|
|
||||||
|
|
||||||
Using the LRU is very simple:
|
|
||||||
|
|
||||||
```go
|
|
||||||
l, _ := New(128)
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
l.Add(i, nil)
|
|
||||||
}
|
|
||||||
if l.Len() != 128 {
|
|
||||||
panic(fmt.Sprintf("bad len: %v", l.Len()))
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
@ -173,7 +173,6 @@ func (c *ARCCache) Add(key, value interface{}) {
|
||||||
|
|
||||||
// Add to the recently seen list
|
// Add to the recently seen list
|
||||||
c.t1.Add(key, value)
|
c.t1.Add(key, value)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace is used to adaptively evict from either T1 or T2
|
// replace is used to adaptively evict from either T1 or T2
|
||||||
|
|
|
@ -6,10 +6,17 @@ import (
|
||||||
"github.com/hashicorp/golang-lru/simplelru"
|
"github.com/hashicorp/golang-lru/simplelru"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultEvictedBufferSize defines the default buffer size to store evicted key/val
|
||||||
|
DefaultEvictedBufferSize = 16
|
||||||
|
)
|
||||||
|
|
||||||
// Cache is a thread-safe fixed size LRU cache.
|
// Cache is a thread-safe fixed size LRU cache.
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
lru simplelru.LRUCache
|
lru *simplelru.LRU
|
||||||
lock sync.RWMutex
|
evictedKeys, evictedVals []interface{}
|
||||||
|
onEvictedCB func(k, v interface{})
|
||||||
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates an LRU of the given size.
|
// New creates an LRU of the given size.
|
||||||
|
@ -19,30 +26,63 @@ func New(size int) (*Cache, error) {
|
||||||
|
|
||||||
// NewWithEvict constructs a fixed size cache with the given eviction
|
// NewWithEvict constructs a fixed size cache with the given eviction
|
||||||
// callback.
|
// callback.
|
||||||
func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
|
func NewWithEvict(size int, onEvicted func(key, value interface{})) (c *Cache, err error) {
|
||||||
lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted))
|
// create a cache with default settings
|
||||||
if err != nil {
|
c = &Cache{
|
||||||
return nil, err
|
onEvictedCB: onEvicted,
|
||||||
}
|
}
|
||||||
c := &Cache{
|
if onEvicted != nil {
|
||||||
lru: lru,
|
c.initEvictBuffers()
|
||||||
|
onEvicted = c.onEvicted
|
||||||
}
|
}
|
||||||
return c, nil
|
c.lru, err = simplelru.NewLRU(size, onEvicted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cache) initEvictBuffers() {
|
||||||
|
c.evictedKeys = make([]interface{}, 0, DefaultEvictedBufferSize)
|
||||||
|
c.evictedVals = make([]interface{}, 0, DefaultEvictedBufferSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// onEvicted save evicted key/val and sent in externally registered callback
|
||||||
|
// outside of critical section
|
||||||
|
func (c *Cache) onEvicted(k, v interface{}) {
|
||||||
|
c.evictedKeys = append(c.evictedKeys, k)
|
||||||
|
c.evictedVals = append(c.evictedVals, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purge is used to completely clear the cache.
|
// Purge is used to completely clear the cache.
|
||||||
func (c *Cache) Purge() {
|
func (c *Cache) Purge() {
|
||||||
|
var ks, vs []interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
c.lru.Purge()
|
c.lru.Purge()
|
||||||
|
if c.onEvictedCB != nil && len(c.evictedKeys) > 0 {
|
||||||
|
ks, vs = c.evictedKeys, c.evictedVals
|
||||||
|
c.initEvictBuffers()
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
// invoke callback outside of critical section
|
||||||
|
if c.onEvictedCB != nil {
|
||||||
|
for i := 0; i < len(ks); i++ {
|
||||||
|
c.onEvictedCB(ks[i], vs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a value to the cache. Returns true if an eviction occurred.
|
// Add adds a value to the cache. Returns true if an eviction occurred.
|
||||||
func (c *Cache) Add(key, value interface{}) (evicted bool) {
|
func (c *Cache) Add(key, value interface{}) (evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
return evicted
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get looks up a key's value from the cache.
|
// Get looks up a key's value from the cache.
|
||||||
|
@ -75,13 +115,21 @@ func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||||
// Returns whether found and whether an eviction occurred.
|
// Returns whether found and whether an eviction occurred.
|
||||||
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
if c.lru.Contains(key) {
|
if c.lru.Contains(key) {
|
||||||
|
c.lock.Unlock()
|
||||||
return true, false
|
return true, false
|
||||||
}
|
}
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return false, evicted
|
return false, evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,47 +137,80 @@ func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||||
// Returns whether found and whether an eviction occurred.
|
// Returns whether found and whether an eviction occurred.
|
||||||
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
|
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
previous, ok = c.lru.Peek(key)
|
previous, ok = c.lru.Peek(key)
|
||||||
if ok {
|
if ok {
|
||||||
|
c.lock.Unlock()
|
||||||
return previous, true, false
|
return previous, true, false
|
||||||
}
|
}
|
||||||
|
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return nil, false, evicted
|
return nil, false, evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the provided key from the cache.
|
// Remove removes the provided key from the cache.
|
||||||
func (c *Cache) Remove(key interface{}) (present bool) {
|
func (c *Cache) Remove(key interface{}) (present bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
present = c.lru.Remove(key)
|
present = c.lru.Remove(key)
|
||||||
|
if c.onEvictedCB != nil && present {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && present {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize changes the cache size.
|
// Resize changes the cache size.
|
||||||
func (c *Cache) Resize(size int) (evicted int) {
|
func (c *Cache) Resize(size int) (evicted int) {
|
||||||
|
var ks, vs []interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
evicted = c.lru.Resize(size)
|
evicted = c.lru.Resize(size)
|
||||||
|
if c.onEvictedCB != nil && evicted > 0 {
|
||||||
|
ks, vs = c.evictedKeys, c.evictedVals
|
||||||
|
c.initEvictBuffers()
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted > 0 {
|
||||||
|
for i := 0; i < len(ks); i++ {
|
||||||
|
c.onEvictedCB(ks[i], vs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
return evicted
|
return evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
func (c *Cache) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *Cache) RemoveOldest() (key, value interface{}, ok bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
key, value, ok = c.lru.RemoveOldest()
|
key, value, ok = c.lru.RemoveOldest()
|
||||||
|
if c.onEvictedCB != nil && ok {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && ok {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
// GetOldest returns the oldest entry
|
||||||
func (c *Cache) GetOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *Cache) GetOldest() (key, value interface{}, ok bool) {
|
||||||
c.lock.Lock()
|
c.lock.RLock()
|
||||||
key, value, ok = c.lru.GetOldest()
|
key, value, ok = c.lru.GetOldest()
|
||||||
c.lock.Unlock()
|
c.lock.RUnlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ type entry struct {
|
||||||
// NewLRU constructs an LRU of the given size
|
// NewLRU constructs an LRU of the given size
|
||||||
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
|
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, errors.New("Must provide a positive size")
|
return nil, errors.New("must provide a positive size")
|
||||||
}
|
}
|
||||||
c := &LRU{
|
c := &LRU{
|
||||||
size: size,
|
size: size,
|
||||||
|
@ -109,7 +109,7 @@ func (c *LRU) Remove(key interface{}) (present bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *LRU) RemoveOldest() (key, value interface{}, ok bool) {
|
||||||
ent := c.evictList.Back()
|
ent := c.evictList.Back()
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
c.removeElement(ent)
|
c.removeElement(ent)
|
||||||
|
@ -120,7 +120,7 @@ func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
// GetOldest returns the oldest entry
|
||||||
func (c *LRU) GetOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *LRU) GetOldest() (key, value interface{}, ok bool) {
|
||||||
ent := c.evictList.Back()
|
ent := c.evictList.Back()
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
kv := ent.Value.(*entry)
|
kv := ent.Value.(*entry)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// Package simplelru provides simple LRU implementation based on build-in container/list.
|
||||||
package simplelru
|
package simplelru
|
||||||
|
|
||||||
// LRUCache is the interface for simple LRU cache.
|
// LRUCache is the interface for simple LRU cache.
|
||||||
|
@ -34,6 +35,6 @@ type LRUCache interface {
|
||||||
// Clears all cache entries.
|
// Clears all cache entries.
|
||||||
Purge()
|
Purge()
|
||||||
|
|
||||||
// Resizes cache, returning number evicted
|
// Resizes cache, returning number evicted
|
||||||
Resize(int) int
|
Resize(int) int
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package lru
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getRand(tb testing.TB) int64 {
|
||||||
|
out, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
|
||||||
|
if err != nil {
|
||||||
|
tb.Fatal(err)
|
||||||
|
}
|
||||||
|
return out.Int64()
|
||||||
|
}
|
|
@ -188,7 +188,7 @@ github.com/gorilla/websocket
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
|
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/runtime
|
github.com/grpc-ecosystem/grpc-gateway/v2/runtime
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/utilities
|
github.com/grpc-ecosystem/grpc-gateway/v2/utilities
|
||||||
# github.com/hashicorp/golang-lru v0.5.4
|
# github.com/hashicorp/golang-lru v1.0.2
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/hashicorp/golang-lru
|
github.com/hashicorp/golang-lru
|
||||||
github.com/hashicorp/golang-lru/simplelru
|
github.com/hashicorp/golang-lru/simplelru
|
||||||
|
|
Loading…
Reference in New Issue