OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / github.com / hashicorp / golang-lru / arc.go
diff --git a/vendor/github.com/hashicorp/golang-lru/arc.go b/vendor/github.com/hashicorp/golang-lru/arc.go
deleted file mode 100644 (file)
index 555225a..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-package lru
-
-import (
-       "sync"
-
-       "github.com/hashicorp/golang-lru/simplelru"
-)
-
-// ARCCache is a thread-safe fixed size Adaptive Replacement Cache (ARC).
-// ARC is an enhancement over the standard LRU cache in that tracks both
-// frequency and recency of use. This avoids a burst in access to new
-// entries from evicting the frequently used older entries. It adds some
-// additional tracking overhead to a standard LRU cache, computationally
-// it is roughly 2x the cost, and the extra memory overhead is linear
-// with the size of the cache. ARC has been patented by IBM, but is
-// similar to the TwoQueueCache (2Q) which requires setting parameters.
-type ARCCache struct {
-       size int // Size is the total capacity of the cache
-       p    int // P is the dynamic preference towards T1 or T2
-
-       t1 simplelru.LRUCache // T1 is the LRU for recently accessed items
-       b1 simplelru.LRUCache // B1 is the LRU for evictions from t1
-
-       t2 simplelru.LRUCache // T2 is the LRU for frequently accessed items
-       b2 simplelru.LRUCache // B2 is the LRU for evictions from t2
-
-       lock sync.RWMutex
-}
-
-// NewARC creates an ARC of the given size
-func NewARC(size int) (*ARCCache, error) {
-       // Create the sub LRUs
-       b1, err := simplelru.NewLRU(size, nil)
-       if err != nil {
-               return nil, err
-       }
-       b2, err := simplelru.NewLRU(size, nil)
-       if err != nil {
-               return nil, err
-       }
-       t1, err := simplelru.NewLRU(size, nil)
-       if err != nil {
-               return nil, err
-       }
-       t2, err := simplelru.NewLRU(size, nil)
-       if err != nil {
-               return nil, err
-       }
-
-       // Initialize the ARC
-       c := &ARCCache{
-               size: size,
-               p:    0,
-               t1:   t1,
-               b1:   b1,
-               t2:   t2,
-               b2:   b2,
-       }
-       return c, nil
-}
-
-// Get looks up a key's value from the cache.
-func (c *ARCCache) Get(key interface{}) (value interface{}, ok bool) {
-       c.lock.Lock()
-       defer c.lock.Unlock()
-
-       // If the value is contained in T1 (recent), then
-       // promote it to T2 (frequent)
-       if val, ok := c.t1.Peek(key); ok {
-               c.t1.Remove(key)
-               c.t2.Add(key, val)
-               return val, ok
-       }
-
-       // Check if the value is contained in T2 (frequent)
-       if val, ok := c.t2.Get(key); ok {
-               return val, ok
-       }
-
-       // No hit
-       return nil, false
-}
-
-// Add adds a value to the cache.
-func (c *ARCCache) Add(key, value interface{}) {
-       c.lock.Lock()
-       defer c.lock.Unlock()
-
-       // Check if the value is contained in T1 (recent), and potentially
-       // promote it to frequent T2
-       if c.t1.Contains(key) {
-               c.t1.Remove(key)
-               c.t2.Add(key, value)
-               return
-       }
-
-       // Check if the value is already in T2 (frequent) and update it
-       if c.t2.Contains(key) {
-               c.t2.Add(key, value)
-               return
-       }
-
-       // Check if this value was recently evicted as part of the
-       // recently used list
-       if c.b1.Contains(key) {
-               // T1 set is too small, increase P appropriately
-               delta := 1
-               b1Len := c.b1.Len()
-               b2Len := c.b2.Len()
-               if b2Len > b1Len {
-                       delta = b2Len / b1Len
-               }
-               if c.p+delta >= c.size {
-                       c.p = c.size
-               } else {
-                       c.p += delta
-               }
-
-               // Potentially need to make room in the cache
-               if c.t1.Len()+c.t2.Len() >= c.size {
-                       c.replace(false)
-               }
-
-               // Remove from B1
-               c.b1.Remove(key)
-
-               // Add the key to the frequently used list
-               c.t2.Add(key, value)
-               return
-       }
-
-       // Check if this value was recently evicted as part of the
-       // frequently used list
-       if c.b2.Contains(key) {
-               // T2 set is too small, decrease P appropriately
-               delta := 1
-               b1Len := c.b1.Len()
-               b2Len := c.b2.Len()
-               if b1Len > b2Len {
-                       delta = b1Len / b2Len
-               }
-               if delta >= c.p {
-                       c.p = 0
-               } else {
-                       c.p -= delta
-               }
-
-               // Potentially need to make room in the cache
-               if c.t1.Len()+c.t2.Len() >= c.size {
-                       c.replace(true)
-               }
-
-               // Remove from B2
-               c.b2.Remove(key)
-
-               // Add the key to the frequently used list
-               c.t2.Add(key, value)
-               return
-       }
-
-       // Potentially need to make room in the cache
-       if c.t1.Len()+c.t2.Len() >= c.size {
-               c.replace(false)
-       }
-
-       // Keep the size of the ghost buffers trim
-       if c.b1.Len() > c.size-c.p {
-               c.b1.RemoveOldest()
-       }
-       if c.b2.Len() > c.p {
-               c.b2.RemoveOldest()
-       }
-
-       // Add to the recently seen list
-       c.t1.Add(key, value)
-       return
-}
-
-// replace is used to adaptively evict from either T1 or T2
-// based on the current learned value of P
-func (c *ARCCache) replace(b2ContainsKey bool) {
-       t1Len := c.t1.Len()
-       if t1Len > 0 && (t1Len > c.p || (t1Len == c.p && b2ContainsKey)) {
-               k, _, ok := c.t1.RemoveOldest()
-               if ok {
-                       c.b1.Add(k, nil)
-               }
-       } else {
-               k, _, ok := c.t2.RemoveOldest()
-               if ok {
-                       c.b2.Add(k, nil)
-               }
-       }
-}
-
-// Len returns the number of cached entries
-func (c *ARCCache) Len() int {
-       c.lock.RLock()
-       defer c.lock.RUnlock()
-       return c.t1.Len() + c.t2.Len()
-}
-
-// Keys returns all the cached keys
-func (c *ARCCache) Keys() []interface{} {
-       c.lock.RLock()
-       defer c.lock.RUnlock()
-       k1 := c.t1.Keys()
-       k2 := c.t2.Keys()
-       return append(k1, k2...)
-}
-
-// Remove is used to purge a key from the cache
-func (c *ARCCache) Remove(key interface{}) {
-       c.lock.Lock()
-       defer c.lock.Unlock()
-       if c.t1.Remove(key) {
-               return
-       }
-       if c.t2.Remove(key) {
-               return
-       }
-       if c.b1.Remove(key) {
-               return
-       }
-       if c.b2.Remove(key) {
-               return
-       }
-}
-
-// Purge is used to clear the cache
-func (c *ARCCache) Purge() {
-       c.lock.Lock()
-       defer c.lock.Unlock()
-       c.t1.Purge()
-       c.t2.Purge()
-       c.b1.Purge()
-       c.b2.Purge()
-}
-
-// Contains is used to check if the cache contains a key
-// without updating recency or frequency.
-func (c *ARCCache) Contains(key interface{}) bool {
-       c.lock.RLock()
-       defer c.lock.RUnlock()
-       return c.t1.Contains(key) || c.t2.Contains(key)
-}
-
-// Peek is used to inspect the cache value of a key
-// without updating recency or frequency.
-func (c *ARCCache) Peek(key interface{}) (value interface{}, ok bool) {
-       c.lock.RLock()
-       defer c.lock.RUnlock()
-       if val, ok := c.t1.Peek(key); ok {
-               return val, ok
-       }
-       return c.t2.Peek(key)
-}