forked from gramework/gramework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfasthttprouter_cache.go
121 lines (110 loc) · 2.05 KB
/
fasthttprouter_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
package gramework
import (
"runtime"
"sync"
"time"
)
const cacheRecordTTLDelta = 20 * 1000000000
type cache struct {
v map[string]*msc
mu sync.RWMutex
}
// method-specific cache
type msc struct {
v map[string]*cacheRecord
mu sync.RWMutex
}
type cacheRecord struct {
n *node
tsr bool
values map[string]string
lastAccessTime int64
}
func (c *cache) getOrInitMSC(method string) *msc {
c.mu.Lock()
if v, ok := c.v[method]; ok {
c.mu.Unlock()
return v
}
ms := &msc{
v: make(map[string]*cacheRecord, 0),
}
c.v[method] = ms
c.mu.Unlock()
return ms
}
func (c *cache) getMSC(method string) *msc {
c.mu.RLock()
if v, ok := c.v[method]; ok {
c.mu.RUnlock()
return v
}
c.mu.RUnlock()
return nil
}
func (c *cache) Put(path string, n *node, tsr bool, method string) {
msc := c.getOrInitMSC(method)
msc.mu.Lock()
msc.v[path] = &cacheRecord{
n: n,
tsr: tsr,
lastAccessTime: Nanotime(),
}
msc.mu.Unlock()
}
func (c *cache) PutWild(path string, n *node, tsr bool, values map[string]string, method string) {
msc := c.getOrInitMSC(method)
msc.mu.Lock()
msc.v[path] = &cacheRecord{
n: n,
tsr: tsr,
values: values,
lastAccessTime: Nanotime(),
}
msc.mu.Unlock()
}
func (c *cache) Get(path string, method string) (n *cacheRecord, ok bool) {
msc := c.getMSC(method)
if msc == nil {
return nil, false
}
msc.mu.RLock()
n, ok = msc.v[path]
if ok {
n.lastAccessTime = Nanotime()
}
msc.mu.RUnlock()
return
}
func (c *cache) maintain() {
for {
runtime.Gosched()
time.Sleep(30 * time.Second)
skipIter := true
c.mu.RLock()
for _, v := range c.v {
if len(v.v) > 256 {
skipIter = false
break
}
}
if skipIter {
c.mu.RUnlock()
continue
}
for _, msc := range c.v {
if len(msc.v) <= 256 {
continue
}
msc.mu.Lock()
for path := range msc.v {
if Nanotime()-cacheRecordTTLDelta > msc.v[path].lastAccessTime {
msc.v[path].n.hits = 0
delete(c.v, path)
}
}
msc.mu.Unlock()
}
c.mu.RUnlock()
}
}