From 2ca0e8f9a0f9863555a26e984cde15efff9ef8f8 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Fri, 23 Sep 2016 10:17:51 -0400 Subject: Updating golang dependancies (#4075) --- .../throttled.v2/store/memstore/memstore.go | 127 +++++++++++++++++++++ .../throttled.v2/store/memstore/memstore_test.go | 40 +++++++ 2 files changed, 167 insertions(+) create mode 100644 vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore.go create mode 100644 vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore_test.go (limited to 'vendor/gopkg.in/throttled/throttled.v2/store/memstore') diff --git a/vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore.go b/vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore.go new file mode 100644 index 000000000..5d8fee8b5 --- /dev/null +++ b/vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore.go @@ -0,0 +1,127 @@ +// Package memstore offers an in-memory store implementation for throttled. +package memstore // import "gopkg.in/throttled/throttled.v2/store/memstore" + +import ( + "sync" + "sync/atomic" + "time" + + "github.com/hashicorp/golang-lru" +) + +// MemStore is an in-memory store implementation for throttled. It +// supports evicting the least recently used keys to control memory +// usage. It is stored in memory in the current process and thus +// doesn't share state with other rate limiters. +type MemStore struct { + sync.RWMutex + keys *lru.Cache + m map[string]*int64 +} + +// New initializes a Store. If maxKeys > 0, the number of different +// keys is restricted to the specified amount. In this case, it uses +// an LRU algorithm to evict older keys to make room for newer +// ones. If maxKeys <= 0, there is no limit on the number of keys, +// which may use an unbounded amount of memory. +func New(maxKeys int) (*MemStore, error) { + var m *MemStore + + if maxKeys > 0 { + keys, err := lru.New(maxKeys) + if err != nil { + return nil, err + } + + m = &MemStore{ + keys: keys, + } + } else { + m = &MemStore{ + m: make(map[string]*int64), + } + } + return m, nil +} + +// GetWithTime returns the value of the key if it is in the store or +// -1 if it does not exist. It also returns the current local time on +// the machine. +func (ms *MemStore) GetWithTime(key string) (int64, time.Time, error) { + now := time.Now() + valP, ok := ms.get(key, false) + + if !ok { + return -1, now, nil + } + + return atomic.LoadInt64(valP), now, nil +} + +// SetIfNotExistsWithTTL sets the value of key only if it is not +// already set in the store it returns whether a new value was set. It +// ignores the ttl. +func (ms *MemStore) SetIfNotExistsWithTTL(key string, value int64, _ time.Duration) (bool, error) { + _, ok := ms.get(key, false) + + if ok { + return false, nil + } + + ms.Lock() + defer ms.Unlock() + + _, ok = ms.get(key, true) + + if ok { + return false, nil + } + + // Store a pointer to a new instance so that the caller + // can't mutate the value after setting + v := value + + if ms.keys != nil { + ms.keys.Add(key, &v) + } else { + ms.m[key] = &v + } + + return true, nil +} + +// CompareAndSwapWithTTL atomically compares the value at key to the +// old value. If it matches, it sets it to the new value and returns +// true. Otherwise, it returns false. If the key does not exist in the +// store, it returns false with no error. It ignores the ttl. +func (ms *MemStore) CompareAndSwapWithTTL(key string, old, new int64, _ time.Duration) (bool, error) { + valP, ok := ms.get(key, false) + + if !ok { + return false, nil + } + + return atomic.CompareAndSwapInt64(valP, old, new), nil +} + +func (ms *MemStore) get(key string, locked bool) (*int64, bool) { + var valP *int64 + var ok bool + + if ms.keys != nil { + var valI interface{} + + valI, ok = ms.keys.Get(key) + if ok { + valP = valI.(*int64) + } + } else { + if !locked { + ms.RLock() + defer ms.RUnlock() + } + valP, ok = ms.m[key] + } + + return valP, ok +} diff --git a/vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore_test.go b/vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore_test.go new file mode 100644 index 000000000..ef003d3de --- /dev/null +++ b/vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore_test.go @@ -0,0 +1,40 @@ +package memstore_test + +import ( + "testing" + + "gopkg.in/throttled/throttled.v2/store/memstore" + "gopkg.in/throttled/throttled.v2/store/storetest" +) + +func TestMemStoreLRU(t *testing.T) { + st, err := memstore.New(10) + if err != nil { + t.Fatal(err) + } + storetest.TestGCRAStore(t, st) +} + +func TestMemStoreUnlimited(t *testing.T) { + st, err := memstore.New(10) + if err != nil { + t.Fatal(err) + } + storetest.TestGCRAStore(t, st) +} + +func BenchmarkMemStoreLRU(b *testing.B) { + st, err := memstore.New(10) + if err != nil { + b.Fatal(err) + } + storetest.BenchmarkGCRAStore(b, st) +} + +func BenchmarkMemStoreUnlimited(b *testing.B) { + st, err := memstore.New(0) + if err != nil { + b.Fatal(err) + } + storetest.BenchmarkGCRAStore(b, st) +} -- cgit v1.2.3-1-g7c22