-
Notifications
You must be signed in to change notification settings - Fork 2
/
piece.go
138 lines (115 loc) · 2.53 KB
/
piece.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
package ttlcache
import (
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils/expires"
"github.com/iwind/TeaGo/types"
"sync"
"time"
)
type Piece struct {
m map[uint64]*Item
expiresList *expires.List
maxItems int
lastGCTime int64
locker sync.RWMutex
}
func NewPiece(maxItems int) *Piece {
return &Piece{
m: map[uint64]*Item{},
expiresList: expires.NewSingletonList(),
maxItems: maxItems,
}
}
func (this *Piece) Add(key uint64, item *Item) (ok bool) {
this.locker.Lock()
if len(this.m) >= this.maxItems {
this.locker.Unlock()
return
}
this.m[key] = item
this.locker.Unlock()
this.expiresList.Add(key, item.expiredAt)
return true
}
func (this *Piece) IncreaseInt64(key uint64, delta int64, expiredAt int64, extend bool) (result int64) {
this.locker.Lock()
item, ok := this.m[key]
if ok && item.expiredAt > time.Now().Unix() {
result = types.Int64(item.Value) + delta
item.Value = result
if extend {
item.expiredAt = expiredAt
}
this.expiresList.Add(key, expiredAt)
} else {
if len(this.m) < this.maxItems {
result = delta
this.m[key] = &Item{
Value: delta,
expiredAt: expiredAt,
}
this.expiresList.Add(key, expiredAt)
}
}
this.locker.Unlock()
return
}
func (this *Piece) Delete(key uint64) {
this.expiresList.Remove(key)
this.locker.Lock()
delete(this.m, key)
this.locker.Unlock()
}
func (this *Piece) Read(key uint64) (item *Item) {
this.locker.RLock()
item = this.m[key]
if item != nil && item.expiredAt < utils.UnixTime() {
item = nil
}
this.locker.RUnlock()
return
}
func (this *Piece) Count() (count int) {
this.locker.RLock()
count = len(this.m)
this.locker.RUnlock()
return
}
func (this *Piece) GC() {
var currentTime = time.Now().Unix()
if this.lastGCTime == 0 {
this.lastGCTime = currentTime - 3600
}
var min = this.lastGCTime
var max = currentTime
if min > max {
// 过去的时间比现在大,则从这一秒重新开始
min = max
}
for i := min; i <= max; i++ {
var itemMap = this.expiresList.GC(i)
if len(itemMap) > 0 {
this.gcItemMap(itemMap)
}
}
this.lastGCTime = currentTime
}
func (this *Piece) Clean() {
this.locker.Lock()
this.m = map[uint64]*Item{}
this.locker.Unlock()
this.expiresList.Clean()
}
func (this *Piece) Destroy() {
this.locker.Lock()
this.m = nil
this.locker.Unlock()
this.expiresList.Clean()
}
func (this *Piece) gcItemMap(itemMap expires.ItemMap) {
this.locker.Lock()
for key := range itemMap {
delete(this.m, key)
}
this.locker.Unlock()
}