-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmem_cache.go
134 lines (108 loc) · 2.64 KB
/
mem_cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package fcache
import (
"sync"
"github.com/nuczzz/lru"
"sync/atomic"
)
// memCache memory cache.
type memCache struct {
// m map of memory cache.
m map[interface{}]*lru.Node
// needCryptKey crypt key or not.
needCryptKey bool
// lru lru control
lru *lru.LRU
// lock lock of memory cache data.
lock sync.RWMutex
// hitCount hit cache count
hitCount int64
// totalCount total count, contains hit count and missing count
totalCount int64
}
func (mc *memCache) deleteCallBack() func(key interface{}) error {
return func(key interface{}) error {
delete(mc.m, key)
return nil
}
}
func (mc *memCache) addNodeCallback() func(*lru.Node) {
return func(node *lru.Node) {
mc.m[node.Key] = node
}
}
// Set set memory cache with key-value pair, and covered if key already exist.
func (mc *memCache) Set(key string, value []byte, extra ...interface{}) error {
if mc.needCryptKey {
key = MD5(key)
}
mc.lock.Lock()
defer mc.lock.Unlock()
v := CacheValue{Value: value}
if data, ok := mc.m[key]; ok {
return mc.lru.Replace(data, v)
}
// memory cache ignore this error
return mc.lru.AddNewNode(key, v, extra...)
}
// Get get memory cache with key, a error will be return if key is not exist.
func (mc *memCache) Get(key string) (value []byte, extra interface{}, err error) {
if mc.needCryptKey {
key = MD5(key)
}
mc.lock.RLock()
defer mc.lock.RUnlock()
atomic.AddInt64(&mc.totalCount, 1)
if data, ok := mc.m[key]; ok {
// memory cache ignore this error
node, _ := mc.lru.Access(data)
if node == nil {
return nil, nil, nil
}
atomic.AddInt64(&mc.hitCount, 1)
return node.Value.(CacheValue).Value, node.Extra, nil
}
return nil, nil, nil
}
func (mc *memCache) GetHitInfo() (int64, int64) {
mc.lock.RLock()
defer mc.lock.RUnlock()
return atomic.LoadInt64(&mc.hitCount), atomic.LoadInt64(&mc.totalCount)
}
func (mc *memCache) Clear(key string) error {
if mc.needCryptKey {
key = MD5(key)
}
mc.lock.RLock()
defer mc.lock.RUnlock()
if data, ok := mc.m[key]; ok {
return mc.lru.Delete(data)
}
return nil
}
func (mc *memCache) ClearAll() error {
mc.lock.RLock()
defer mc.lock.RUnlock()
var err error
for _, node := range mc.lru.Traversal() {
if err = mc.lru.Delete(node); err != nil {
return err
}
}
return nil
}
func newMemCache(maxSize int64, needCryptKey bool, ttl int64) Cache {
if maxSize <= 0 {
maxSize = DefaultMaxMemCacheSize
}
mc := &memCache{
needCryptKey: needCryptKey,
m: make(map[interface{}]*lru.Node),
}
mc.lru = &lru.LRU{
MaxSize: maxSize,
TTL: ttl,
AddNodeCallBack: mc.addNodeCallback(),
DeleteNodeCallBack: mc.deleteCallBack(),
}
return mc
}