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{} { | |
jcgregorio
2015/10/13 18:40:24
Needs unit tests.
stephana
2015/10/14 14:26:30
Done. I factored out tests from redisutils to be a
| |
101 m.mutex.RLock() | |
102 m.mutex.RUnlock() | |
jcgregorio
2015/10/13 18:40:24
defer m.mutex.RUnlock()
stephana
2015/10/14 14:26:30
Good catch. Fixed.
| |
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 |