-
Notifications
You must be signed in to change notification settings - Fork 53
/
utils.go
127 lines (110 loc) · 3.02 KB
/
utils.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
package zcache
type ActionKind int
func (k ActionKind) String() string {
switch k {
case GET:
return "GET"
case SET:
return "SET"
case DELETE:
return "DELETE"
default:
return "UNKNOWN"
}
}
const (
SET ActionKind = iota + 1
GET
DELETE
)
type handler func(action ActionKind, key string, valuePtr uintptr)
// Callback set callback function for cache
func (l *FastCache) Callback(h handler) {
old := l.callback
l.callback = func(action ActionKind, key string, valuePtr uintptr) {
old(action, key, valuePtr)
h(action, key, valuePtr)
}
}
var p, n = uint16(0), uint16(1)
type (
value struct {
value *interface{}
byteValue []byte
}
node struct {
key string
value value
expireAt int64
isDelete bool
}
lruCache struct {
hashmap map[string]uint16
dlList [][2]uint16
nodes []node
last uint16
}
)
func (c *lruCache) put(k string, i *interface{}, b []byte, expireAt int64) int {
if x, ok := c.hashmap[k]; ok {
c.nodes[x-1].value.value, c.nodes[x-1].value.byteValue, c.nodes[x-1].expireAt, c.nodes[x-1].isDelete = i, b, expireAt, false
c.adjust(x, p, n)
return 0
}
if c.last == uint16(cap(c.nodes)) {
tail := &c.nodes[c.dlList[0][p]-1]
delete(c.hashmap, (*tail).key)
c.hashmap[k], (*tail).key, (*tail).value.value, (*tail).value.byteValue, (*tail).expireAt, (*tail).isDelete = c.dlList[0][p], k, i, b, expireAt, false
c.adjust(c.dlList[0][p], p, n)
return 1
}
c.last++
if len(c.hashmap) <= 0 {
c.dlList[0][p] = c.last
} else {
c.dlList[c.dlList[0][n]][p] = c.last
}
c.nodes[c.last-1].key, c.nodes[c.last-1].value.value, c.nodes[c.last-1].value.byteValue, c.nodes[c.last-1].expireAt, c.nodes[c.last-1].isDelete, c.dlList[c.last], c.hashmap[k], c.dlList[0][n] = k, i, b, expireAt, false, [2]uint16{0, c.dlList[0][n]}, c.last, c.last
return 1
}
func (c *lruCache) get(k string) (*node, int) {
if x, ok := c.hashmap[k]; ok {
c.adjust(x, p, n)
return &c.nodes[x-1], 1
}
return nil, 0
}
func (c *lruCache) delete(k string) (_ *node, _ int, e int64) {
if x, ok := c.hashmap[k]; ok && !c.nodes[x-1].isDelete {
c.nodes[x-1].expireAt, c.nodes[x-1].isDelete, e = 0, true, c.nodes[x-1].expireAt
c.adjust(x, n, p)
return &c.nodes[x-1], 1, e
}
return nil, 0, 0
}
func (c *lruCache) forEach(walker func(key string, iface interface{}) bool) {
for idx := c.dlList[0][n]; idx != 0; idx = c.dlList[idx][n] {
if !c.nodes[idx-1].isDelete {
if c.nodes[idx-1].value.byteValue != nil {
if !walker(c.nodes[idx-1].key, c.nodes[idx-1].value.byteValue) {
return
}
} else {
if !walker(c.nodes[idx-1].key, *c.nodes[idx-1].value.value) {
return
}
}
}
}
}
func (c *lruCache) adjust(idx, f, t uint16) {
if c.dlList[idx][f] != 0 {
c.dlList[c.dlList[idx][t]][f], c.dlList[c.dlList[idx][f]][t], c.dlList[idx][f], c.dlList[idx][t], c.dlList[c.dlList[0][t]][f], c.dlList[0][t] = c.dlList[idx][f], c.dlList[idx][t], 0, c.dlList[0][t], idx, idx
}
}
func hasher(s string) (hash int32) {
for i := 0; i < len(s); i++ {
hash = hash*131 + int32(s[i])
}
return hash
}