mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
vendor files
This commit is contained in:
44
vendor/k8s.io/apimachinery/pkg/util/cache/BUILD
generated
vendored
Normal file
44
vendor/k8s.io/apimachinery/pkg/util/cache/BUILD
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"cache_test.go",
|
||||
"lruexpirecache_test.go",
|
||||
],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/cache",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/github.com/golang/groupcache/lru:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cache.go",
|
||||
"lruexpirecache.go",
|
||||
],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/cache",
|
||||
deps = ["//vendor/github.com/hashicorp/golang-lru:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
83
vendor/k8s.io/apimachinery/pkg/util/cache/cache.go
generated
vendored
Normal file
83
vendor/k8s.io/apimachinery/pkg/util/cache/cache.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
shardsCount int = 32
|
||||
)
|
||||
|
||||
type Cache []*cacheShard
|
||||
|
||||
func NewCache(maxSize int) Cache {
|
||||
if maxSize < shardsCount {
|
||||
maxSize = shardsCount
|
||||
}
|
||||
cache := make(Cache, shardsCount)
|
||||
for i := 0; i < shardsCount; i++ {
|
||||
cache[i] = &cacheShard{
|
||||
items: make(map[uint64]interface{}),
|
||||
maxSize: maxSize / shardsCount,
|
||||
}
|
||||
}
|
||||
return cache
|
||||
}
|
||||
|
||||
func (c Cache) getShard(index uint64) *cacheShard {
|
||||
return c[index%uint64(shardsCount)]
|
||||
}
|
||||
|
||||
// Returns true if object already existed, false otherwise.
|
||||
func (c *Cache) Add(index uint64, obj interface{}) bool {
|
||||
return c.getShard(index).add(index, obj)
|
||||
}
|
||||
|
||||
func (c *Cache) Get(index uint64) (obj interface{}, found bool) {
|
||||
return c.getShard(index).get(index)
|
||||
}
|
||||
|
||||
type cacheShard struct {
|
||||
items map[uint64]interface{}
|
||||
sync.RWMutex
|
||||
maxSize int
|
||||
}
|
||||
|
||||
// Returns true if object already existed, false otherwise.
|
||||
func (s *cacheShard) add(index uint64, obj interface{}) bool {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
_, isOverwrite := s.items[index]
|
||||
if !isOverwrite && len(s.items) >= s.maxSize {
|
||||
var randomKey uint64
|
||||
for randomKey = range s.items {
|
||||
break
|
||||
}
|
||||
delete(s.items, randomKey)
|
||||
}
|
||||
s.items[index] = obj
|
||||
return isOverwrite
|
||||
}
|
||||
|
||||
func (s *cacheShard) get(index uint64) (obj interface{}, found bool) {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
obj, found = s.items[index]
|
||||
return
|
||||
}
|
90
vendor/k8s.io/apimachinery/pkg/util/cache/cache_test.go
generated
vendored
Normal file
90
vendor/k8s.io/apimachinery/pkg/util/cache/cache_test.go
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
maxTestCacheSize int = shardsCount * 2
|
||||
)
|
||||
|
||||
func ExpectEntry(t *testing.T, cache Cache, index uint64, expectedValue interface{}) bool {
|
||||
elem, found := cache.Get(index)
|
||||
if !found {
|
||||
t.Errorf("Expected to find entry with key %d", index)
|
||||
return false
|
||||
} else if elem != expectedValue {
|
||||
t.Errorf("Expected to find %v, got %v", expectedValue, elem)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func TestBasic(t *testing.T) {
|
||||
cache := NewCache(maxTestCacheSize)
|
||||
cache.Add(1, "xxx")
|
||||
ExpectEntry(t, cache, 1, "xxx")
|
||||
}
|
||||
|
||||
func TestOverflow(t *testing.T) {
|
||||
cache := NewCache(maxTestCacheSize)
|
||||
for i := 0; i < maxTestCacheSize+1; i++ {
|
||||
cache.Add(uint64(i), "xxx")
|
||||
}
|
||||
foundIndexes := make([]uint64, 0)
|
||||
for i := 0; i < maxTestCacheSize+1; i++ {
|
||||
_, found := cache.Get(uint64(i))
|
||||
if found {
|
||||
foundIndexes = append(foundIndexes, uint64(i))
|
||||
}
|
||||
}
|
||||
if len(foundIndexes) != maxTestCacheSize {
|
||||
t.Errorf("Expect to find %d elements, got %d %v", maxTestCacheSize, len(foundIndexes), foundIndexes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOverwrite(t *testing.T) {
|
||||
cache := NewCache(maxTestCacheSize)
|
||||
cache.Add(1, "xxx")
|
||||
ExpectEntry(t, cache, 1, "xxx")
|
||||
cache.Add(1, "yyy")
|
||||
ExpectEntry(t, cache, 1, "yyy")
|
||||
}
|
||||
|
||||
// TestEvict this test will fail sporatically depending on what add()
|
||||
// selects for the randomKey to be evicted. Ensure that randomKey
|
||||
// is never the key we most recently added. Since the chance of failure
|
||||
// on each evict is 50%, if we do it 7 times, it should catch the problem
|
||||
// if it exists >99% of the time.
|
||||
func TestEvict(t *testing.T) {
|
||||
cache := NewCache(shardsCount)
|
||||
var found bool
|
||||
for retry := 0; retry < 7; retry++ {
|
||||
cache.Add(uint64(shardsCount), "xxx")
|
||||
found = ExpectEntry(t, cache, uint64(shardsCount), "xxx")
|
||||
if !found {
|
||||
break
|
||||
}
|
||||
cache.Add(0, "xxx")
|
||||
found = ExpectEntry(t, cache, 0, "xxx")
|
||||
if !found {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
102
vendor/k8s.io/apimachinery/pkg/util/cache/lruexpirecache.go
generated
vendored
Normal file
102
vendor/k8s.io/apimachinery/pkg/util/cache/lruexpirecache.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// Clock defines an interface for obtaining the current time
|
||||
type Clock interface {
|
||||
Now() time.Time
|
||||
}
|
||||
|
||||
// realClock implements the Clock interface by calling time.Now()
|
||||
type realClock struct{}
|
||||
|
||||
func (realClock) Now() time.Time { return time.Now() }
|
||||
|
||||
// LRUExpireCache is a cache that ensures the mostly recently accessed keys are returned with
|
||||
// a ttl beyond which keys are forcibly expired.
|
||||
type LRUExpireCache struct {
|
||||
// clock is used to obtain the current time
|
||||
clock Clock
|
||||
|
||||
cache *lru.Cache
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// NewLRUExpireCache creates an expiring cache with the given size
|
||||
func NewLRUExpireCache(maxSize int) *LRUExpireCache {
|
||||
return NewLRUExpireCacheWithClock(maxSize, realClock{})
|
||||
}
|
||||
|
||||
// NewLRUExpireCacheWithClock creates an expiring cache with the given size, using the specified clock to obtain the current time.
|
||||
func NewLRUExpireCacheWithClock(maxSize int, clock Clock) *LRUExpireCache {
|
||||
cache, err := lru.New(maxSize)
|
||||
if err != nil {
|
||||
// if called with an invalid size
|
||||
panic(err)
|
||||
}
|
||||
return &LRUExpireCache{clock: clock, cache: cache}
|
||||
}
|
||||
|
||||
type cacheEntry struct {
|
||||
value interface{}
|
||||
expireTime time.Time
|
||||
}
|
||||
|
||||
// Add adds the value to the cache at key with the specified maximum duration.
|
||||
func (c *LRUExpireCache) Add(key interface{}, value interface{}, ttl time.Duration) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
c.cache.Add(key, &cacheEntry{value, c.clock.Now().Add(ttl)})
|
||||
}
|
||||
|
||||
// Get returns the value at the specified key from the cache if it exists and is not
|
||||
// expired, or returns false.
|
||||
func (c *LRUExpireCache) Get(key interface{}) (interface{}, bool) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
e, ok := c.cache.Get(key)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if c.clock.Now().After(e.(*cacheEntry).expireTime) {
|
||||
c.cache.Remove(key)
|
||||
return nil, false
|
||||
}
|
||||
return e.(*cacheEntry).value, true
|
||||
}
|
||||
|
||||
// Remove removes the specified key from the cache if it exists
|
||||
func (c *LRUExpireCache) Remove(key interface{}) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
c.cache.Remove(key)
|
||||
}
|
||||
|
||||
// Keys returns all the keys in the cache, even if they are expired. Subsequent calls to
|
||||
// get may return not found. It returns all keys from oldest to newest.
|
||||
func (c *LRUExpireCache) Keys() []interface{} {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
return c.cache.Keys()
|
||||
}
|
68
vendor/k8s.io/apimachinery/pkg/util/cache/lruexpirecache_test.go
generated
vendored
Normal file
68
vendor/k8s.io/apimachinery/pkg/util/cache/lruexpirecache_test.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
|
||||
"github.com/golang/groupcache/lru"
|
||||
)
|
||||
|
||||
func expectEntry(t *testing.T, c *LRUExpireCache, key lru.Key, value interface{}) {
|
||||
result, ok := c.Get(key)
|
||||
if !ok || result != value {
|
||||
t.Errorf("Expected cache[%v]: %v, got %v", key, value, result)
|
||||
}
|
||||
}
|
||||
|
||||
func expectNotEntry(t *testing.T, c *LRUExpireCache, key lru.Key) {
|
||||
if result, ok := c.Get(key); ok {
|
||||
t.Errorf("Expected cache[%v] to be empty, got %v", key, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimpleGet(t *testing.T) {
|
||||
c := NewLRUExpireCache(10)
|
||||
c.Add("long-lived", "12345", 10*time.Hour)
|
||||
expectEntry(t, c, "long-lived", "12345")
|
||||
}
|
||||
|
||||
func TestExpiredGet(t *testing.T) {
|
||||
fakeClock := clock.NewFakeClock(time.Now())
|
||||
c := NewLRUExpireCacheWithClock(10, fakeClock)
|
||||
c.Add("short-lived", "12345", 1*time.Millisecond)
|
||||
// ensure the entry expired
|
||||
fakeClock.Step(2 * time.Millisecond)
|
||||
expectNotEntry(t, c, "short-lived")
|
||||
}
|
||||
|
||||
func TestLRUOverflow(t *testing.T) {
|
||||
c := NewLRUExpireCache(4)
|
||||
c.Add("elem1", "1", 10*time.Hour)
|
||||
c.Add("elem2", "2", 10*time.Hour)
|
||||
c.Add("elem3", "3", 10*time.Hour)
|
||||
c.Add("elem4", "4", 10*time.Hour)
|
||||
c.Add("elem5", "5", 10*time.Hour)
|
||||
expectNotEntry(t, c, "elem1")
|
||||
expectEntry(t, c, "elem2", "2")
|
||||
expectEntry(t, c, "elem3", "3")
|
||||
expectEntry(t, c, "elem4", "4")
|
||||
expectEntry(t, c, "elem5", "5")
|
||||
}
|
Reference in New Issue
Block a user