-
Notifications
You must be signed in to change notification settings - Fork 17
/
entry.go
157 lines (140 loc) · 2.93 KB
/
entry.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package internal
import "sync/atomic"
const (
NEW int8 = iota
REMOVE
UPDATE
)
type ReadBufItem[K comparable, V any] struct {
entry *Entry[K, V]
hash uint64
}
type WriteBufItem[K comparable, V any] struct {
entry *Entry[K, V]
costChange int64
code int8
rechedule bool
}
type MetaData[K comparable, V any] struct {
prev *Entry[K, V]
next *Entry[K, V]
wheelPrev *Entry[K, V]
wheelNext *Entry[K, V]
root bool
list uint8 // used in slru, probation or protected
}
type Entry[K comparable, V any] struct {
key K
value V
meta MetaData[K, V]
cost atomic.Int64
expire atomic.Int64
frequency atomic.Int32
removed bool
deque bool
}
func NewEntry[K comparable, V any](key K, value V, cost int64, expire int64) *Entry[K, V] {
entry := &Entry[K, V]{
key: key,
value: value,
}
entry.cost.Store(cost)
if expire > 0 {
entry.expire.Store(expire)
}
return entry
}
func (e *Entry[K, V]) Next(listType uint8) *Entry[K, V] {
switch listType {
case LIST_PROBATION, LIST_PROTECTED:
if p := e.meta.next; !p.meta.root {
return e.meta.next
}
return nil
case WHEEL_LIST:
if p := e.meta.wheelNext; !p.meta.root {
return e.meta.wheelNext
}
return nil
}
return nil
}
func (e *Entry[K, V]) Prev(listType uint8) *Entry[K, V] {
switch listType {
case LIST_PROBATION, LIST_PROTECTED:
if p := e.meta.prev; !p.meta.root {
return e.meta.prev
}
return nil
case WHEEL_LIST:
if p := e.meta.wheelPrev; !p.meta.root {
return e.meta.wheelPrev
}
return nil
}
return nil
}
func (e *Entry[K, V]) prev(listType uint8) *Entry[K, V] {
switch listType {
case LIST_PROBATION, LIST_PROTECTED:
return e.meta.prev
case WHEEL_LIST:
return e.meta.wheelPrev
}
return nil
}
func (e *Entry[K, V]) next(listType uint8) *Entry[K, V] {
switch listType {
case LIST_PROBATION, LIST_PROTECTED:
return e.meta.next
case WHEEL_LIST:
return e.meta.wheelNext
}
return nil
}
func (e *Entry[K, V]) setPrev(entry *Entry[K, V], listType uint8) {
switch listType {
case LIST_PROBATION, LIST_PROTECTED:
e.meta.prev = entry
case WHEEL_LIST:
e.meta.wheelPrev = entry
}
}
func (e *Entry[K, V]) setNext(entry *Entry[K, V], listType uint8) {
switch listType {
case LIST_PROBATION, LIST_PROTECTED:
e.meta.next = entry
case WHEEL_LIST:
e.meta.wheelNext = entry
}
}
func (e *Entry[K, V]) pentry() *Pentry[K, V] {
return &Pentry[K, V]{
Key: e.key,
Value: e.value,
Cost: e.cost.Load(),
Expire: e.expire.Load(),
Frequency: e.frequency.Load(),
Removed: e.removed,
}
}
// entry for persistence
type Pentry[K comparable, V any] struct {
Key K
Value V
Cost int64
Expire int64
Frequency int32
Removed bool
}
func (e *Pentry[K, V]) entry() *Entry[K, V] {
en := &Entry[K, V]{
key: e.Key,
value: e.Value,
removed: e.Removed,
}
en.cost.Store(e.Cost)
en.frequency.Store(e.Frequency)
en.expire.Store(e.Expire)
return en
}