OLD | NEW |
1 package util | 1 package util |
2 | 2 |
3 import ( | 3 import ( |
4 "encoding/json" | 4 "encoding/json" |
5 "reflect" | 5 "reflect" |
6 "sync" | 6 "sync" |
7 | 7 |
8 "github.com/golang/groupcache/lru" | 8 "github.com/golang/groupcache/lru" |
9 ) | 9 ) |
10 | 10 |
11 // Generic LRUCache interface. | 11 // Generic LRUCache interface. |
12 type LRUCache interface { | 12 type LRUCache interface { |
13 // Add adds a key-value pair to the cache. | 13 // Add adds a key-value pair to the cache. |
14 Add(key, value interface{}) bool | 14 Add(key, value interface{}) bool |
15 | 15 |
16 // Get returns a key value for the given cache. If ok is true | 16 // Get returns a key value for the given cache. If ok is true |
17 // the fetch was succesfull. | 17 // the fetch was succesfull. |
18 Get(key interface{}) (value interface{}, ok bool) | 18 Get(key interface{}) (value interface{}, ok bool) |
19 | 19 |
20 // Len returns the current size of the cache. | 20 // Len returns the current size of the cache. |
21 Len() int | 21 Len() int |
22 | 22 |
23 // Remove removes a key value pair from the cache. | 23 // Remove removes a key value pair from the cache. |
24 Remove(key interface{}) | 24 Remove(key interface{}) |
| 25 |
| 26 // Keys returns all the keys in the LRUCache. |
| 27 Keys() []interface{} |
25 } | 28 } |
26 | 29 |
27 // LRUCodec converts serializes/deserializes an instance of a type to/from | 30 // LRUCodec converts serializes/deserializes an instance of a type to/from |
28 // byte arrays. Encode and Decode have to be the inverse of each other. | 31 // byte arrays. Encode and Decode have to be the inverse of each other. |
29 type LRUCodec interface { | 32 type LRUCodec interface { |
30 // Encode serializes the given value to a byte array (inverse of Decode)
. | 33 // Encode serializes the given value to a byte array (inverse of Decode)
. |
31 Encode(interface{}) ([]byte, error) | 34 Encode(interface{}) ([]byte, error) |
32 | 35 |
33 // Decode deserializes the byte array to an instance of the type that | 36 // Decode deserializes the byte array to an instance of the type that |
34 // was passed to Encode in a prior call. | 37 // was passed to Encode in a prior call. |
35 Decode([]byte) (interface{}, error) | 38 Decode([]byte) (interface{}, error) |
36 } | 39 } |
37 | 40 |
38 type MemLRUCache struct { | 41 type MemLRUCache struct { |
39 cache *lru.Cache | 42 cache *lru.Cache |
| 43 keys map[string]bool |
40 mutex sync.RWMutex | 44 mutex sync.RWMutex |
41 } | 45 } |
42 | 46 |
43 func NewMemLRUCache(maxEntries int) *MemLRUCache { | 47 func NewMemLRUCache(maxEntries int) *MemLRUCache { |
44 » return &MemLRUCache{ | 48 » ret := &MemLRUCache{ |
45 cache: lru.New(maxEntries), | 49 cache: lru.New(maxEntries), |
| 50 keys: map[string]bool{}, |
46 } | 51 } |
| 52 |
| 53 ret.cache.OnEvicted = func(key lru.Key, value interface{}) { |
| 54 delete(ret.keys, getStringKey(key)) |
| 55 } |
| 56 |
| 57 return ret |
| 58 } |
| 59 |
| 60 func getStringKey(key interface{}) string { |
| 61 k := "" |
| 62 switch key := key.(type) { |
| 63 case string: |
| 64 k = key |
| 65 case []byte: |
| 66 if key != nil { |
| 67 k = string(key) |
| 68 } |
| 69 } |
| 70 return k |
47 } | 71 } |
48 | 72 |
49 func (m *MemLRUCache) Add(key, value interface{}) bool { | 73 func (m *MemLRUCache) Add(key, value interface{}) bool { |
50 m.mutex.Lock() | 74 m.mutex.Lock() |
51 defer m.mutex.Unlock() | 75 defer m.mutex.Unlock() |
52 m.cache.Add(key, value) | 76 m.cache.Add(key, value) |
| 77 m.keys[getStringKey(key)] = true |
53 return true | 78 return true |
54 } | 79 } |
55 | 80 |
56 func (m *MemLRUCache) Get(key interface{}) (value interface{}, ok bool) { | 81 func (m *MemLRUCache) Get(key interface{}) (value interface{}, ok bool) { |
57 m.mutex.RLock() | 82 m.mutex.RLock() |
58 m.mutex.RUnlock() | 83 m.mutex.RUnlock() |
59 return m.cache.Get(key) | 84 return m.cache.Get(key) |
60 } | 85 } |
61 | 86 |
62 func (m *MemLRUCache) Len() int { | 87 func (m *MemLRUCache) Len() int { |
63 m.mutex.RLock() | 88 m.mutex.RLock() |
64 m.mutex.RUnlock() | 89 m.mutex.RUnlock() |
65 return m.cache.Len() | 90 return m.cache.Len() |
66 } | 91 } |
67 | 92 |
68 func (m *MemLRUCache) Remove(key interface{}) { | 93 func (m *MemLRUCache) Remove(key interface{}) { |
69 m.mutex.Lock() | 94 m.mutex.Lock() |
70 defer m.mutex.Unlock() | 95 defer m.mutex.Unlock() |
| 96 m.cache.Remove(key) |
| 97 delete(m.keys, getStringKey(key)) |
| 98 } |
| 99 |
| 100 func (m *MemLRUCache) Keys() []interface{} { |
| 101 m.mutex.RLock() |
| 102 defer m.mutex.RUnlock() |
| 103 ret := make([]interface{}, 0, len(m.keys)) |
| 104 for k := range m.keys { |
| 105 ret = append(ret, k) |
| 106 } |
| 107 return ret |
71 } | 108 } |
72 | 109 |
73 type jsonCodec struct { | 110 type jsonCodec struct { |
74 targetType reflect.Type | 111 targetType reflect.Type |
75 isSlice bool | 112 isSlice bool |
76 } | 113 } |
77 | 114 |
78 // JSONCodec implements the LRUCodec interface by serializing and | 115 // JSONCodec implements the LRUCodec interface by serializing and |
79 // deserializing instances of the underlying type of 'instance'. | 116 // deserializing instances of the underlying type of 'instance'. |
80 // Generally it's assumed that 'instance' is a struct, a pointer to | 117 // Generally it's assumed that 'instance' is a struct, a pointer to |
(...skipping 20 matching lines...) Expand all Loading... |
101 ret := reflect.New(j.targetType).Interface() | 138 ret := reflect.New(j.targetType).Interface() |
102 err := json.Unmarshal(byteData, ret) | 139 err := json.Unmarshal(byteData, ret) |
103 if err != nil { | 140 if err != nil { |
104 return nil, err | 141 return nil, err |
105 } else if j.isSlice { | 142 } else if j.isSlice { |
106 return reflect.ValueOf(ret).Elem().Interface(), nil | 143 return reflect.ValueOf(ret).Elem().Interface(), nil |
107 } | 144 } |
108 | 145 |
109 return ret, nil | 146 return ret, nil |
110 } | 147 } |
OLD | NEW |