summaryrefslogtreecommitdiffstats
path: root/vendor/gopkg.in/throttled/throttled.v2/store/memstore
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2016-09-23 10:17:51 -0400
committerGitHub <noreply@github.com>2016-09-23 10:17:51 -0400
commit2ca0e8f9a0f9863555a26e984cde15efff9ef8f8 (patch)
treedaae1ee67b14a3d0a84424f2a304885d9e75ce2b /vendor/gopkg.in/throttled/throttled.v2/store/memstore
parent6d62d65b2dc85855aabea036cbd44f6059e19d13 (diff)
downloadchat-2ca0e8f9a0f9863555a26e984cde15efff9ef8f8.tar.gz
chat-2ca0e8f9a0f9863555a26e984cde15efff9ef8f8.tar.bz2
chat-2ca0e8f9a0f9863555a26e984cde15efff9ef8f8.zip
Updating golang dependancies (#4075)
Diffstat (limited to 'vendor/gopkg.in/throttled/throttled.v2/store/memstore')
-rw-r--r--vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore.go127
-rw-r--r--vendor/gopkg.in/throttled/throttled.v2/store/memstore/memstore_test.go40
2 files changed, 167 insertions, 0 deletions
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)
+}