Files
EdgeNode/internal/utils/expires/list.go

177 lines
3.3 KiB
Go
Raw Normal View History

2021-01-03 20:18:47 +08:00
package expires
import (
2024-05-11 09:23:54 +08:00
"github.com/TeaOSLab/EdgeNode/internal/utils/zero"
2021-01-03 20:18:47 +08:00
"sync"
)
2022-04-09 18:28:22 +08:00
type ItemMap = map[uint64]zero.Zero
2021-01-03 20:18:47 +08:00
type List struct {
expireMap map[int64]ItemMap // expires timestamp => map[id]ItemMap
2022-04-09 18:28:22 +08:00
itemsMap map[uint64]int64 // itemId => timestamp
2021-01-03 20:18:47 +08:00
2024-03-31 11:47:34 +08:00
mu sync.RWMutex
2022-04-09 18:28:22 +08:00
gcCallback func(itemId uint64)
gcBatchCallback func(itemIds ItemMap)
lastTimestamp int64
2021-01-03 20:18:47 +08:00
}
func NewList() *List {
var list = &List{
2021-01-03 20:18:47 +08:00
expireMap: map[int64]ItemMap{},
2022-04-09 18:28:22 +08:00
itemsMap: map[uint64]int64{},
2021-01-03 20:18:47 +08:00
}
SharedManager.Add(list)
return list
2021-01-03 20:18:47 +08:00
}
2022-04-09 18:28:22 +08:00
func NewSingletonList() *List {
var list = &List{
expireMap: map[int64]ItemMap{},
itemsMap: map[uint64]int64{},
}
return list
}
2021-12-12 11:48:01 +08:00
// Add 添加条目
// 如果条目已经存在,则覆盖
2022-04-09 18:28:22 +08:00
func (this *List) Add(itemId uint64, expiresAt int64) {
2024-03-31 11:47:34 +08:00
this.mu.Lock()
defer this.mu.Unlock()
2021-01-03 20:18:47 +08:00
2022-04-09 18:28:22 +08:00
if this.lastTimestamp == 0 || this.lastTimestamp > expiresAt {
this.lastTimestamp = expiresAt
}
2021-01-03 20:18:47 +08:00
// 是否已经存在
2021-12-12 11:48:01 +08:00
oldExpiresAt, ok := this.itemsMap[itemId]
2021-01-03 20:18:47 +08:00
if ok {
2021-12-12 11:48:01 +08:00
if oldExpiresAt == expiresAt {
return
}
delete(this.expireMap[oldExpiresAt], itemId)
if len(this.expireMap[oldExpiresAt]) == 0 {
delete(this.expireMap, oldExpiresAt)
}
2021-01-03 20:18:47 +08:00
}
2021-07-18 15:51:49 +08:00
expireItemMap, ok := this.expireMap[expiresAt]
2021-01-03 20:18:47 +08:00
if ok {
expireItemMap[itemId] = zero.New()
2021-01-03 20:18:47 +08:00
} else {
this.expireMap[expiresAt] = ItemMap{
itemId: zero.New(),
2021-01-03 20:18:47 +08:00
}
}
2021-07-18 15:51:49 +08:00
this.itemsMap[itemId] = expiresAt
2021-01-03 20:18:47 +08:00
}
2022-04-09 18:28:22 +08:00
func (this *List) Remove(itemId uint64) {
2024-03-31 11:47:34 +08:00
this.mu.Lock()
defer this.mu.Unlock()
2021-01-03 20:18:47 +08:00
this.removeItem(itemId)
}
2022-09-03 09:54:25 +08:00
func (this *List) ExpiresAt(itemId uint64) int64 {
2024-03-31 11:47:34 +08:00
this.mu.RLock()
defer this.mu.RUnlock()
2022-09-03 09:54:25 +08:00
return this.itemsMap[itemId]
}
2022-04-09 18:28:22 +08:00
func (this *List) GC(timestamp int64) ItemMap {
if this.lastTimestamp > timestamp+1 {
return nil
}
2022-01-10 15:38:53 +08:00
var itemMap = this.gcItems(timestamp)
if len(itemMap) == 0 {
2022-04-09 18:28:22 +08:00
return itemMap
2022-01-10 15:38:53 +08:00
}
2021-01-03 20:18:47 +08:00
2022-04-09 18:28:22 +08:00
if this.gcCallback != nil {
for itemId := range itemMap {
2022-04-09 18:28:22 +08:00
this.gcCallback(itemId)
}
2021-01-03 20:18:47 +08:00
}
2022-04-09 18:28:22 +08:00
if this.gcBatchCallback != nil {
this.gcBatchCallback(itemMap)
}
return itemMap
}
func (this *List) Clean() {
2024-03-31 11:47:34 +08:00
this.mu.Lock()
2022-04-09 18:28:22 +08:00
this.itemsMap = map[uint64]int64{}
this.expireMap = map[int64]ItemMap{}
2024-03-31 11:47:34 +08:00
this.mu.Unlock()
2022-04-09 18:28:22 +08:00
}
func (this *List) Count() int {
2024-03-31 11:47:34 +08:00
this.mu.RLock()
2022-04-09 18:28:22 +08:00
var count = len(this.itemsMap)
2024-03-31 11:47:34 +08:00
this.mu.RUnlock()
2022-04-09 18:28:22 +08:00
return count
2021-01-03 20:18:47 +08:00
}
2022-04-09 18:28:22 +08:00
func (this *List) OnGC(callback func(itemId uint64)) *List {
this.gcCallback = callback
2021-12-12 11:48:01 +08:00
return this
2021-01-03 20:18:47 +08:00
}
2022-04-09 18:28:22 +08:00
func (this *List) OnGCBatch(callback func(itemMap ItemMap)) *List {
this.gcBatchCallback = callback
return this
}
2024-03-31 11:47:34 +08:00
func (this *List) ExpireMap() map[int64]ItemMap {
return this.expireMap
}
func (this *List) ItemsMap() map[uint64]int64 {
return this.itemsMap
}
func (this *List) LastTimestamp() int64 {
return this.lastTimestamp
}
2022-04-09 18:28:22 +08:00
func (this *List) removeItem(itemId uint64) {
2021-01-03 20:18:47 +08:00
expiresAt, ok := this.itemsMap[itemId]
if !ok {
return
}
delete(this.itemsMap, itemId)
expireItemMap, ok := this.expireMap[expiresAt]
if ok {
delete(expireItemMap, itemId)
if len(expireItemMap) == 0 {
delete(this.expireMap, expiresAt)
}
}
}
func (this *List) gcItems(timestamp int64) ItemMap {
2024-03-31 11:47:34 +08:00
this.mu.RLock()
2021-01-03 20:18:47 +08:00
expireItemsMap, ok := this.expireMap[timestamp]
2024-03-31 11:47:34 +08:00
this.mu.RUnlock()
2021-01-03 20:18:47 +08:00
if ok {
2024-03-31 11:47:34 +08:00
this.mu.Lock()
2021-01-03 20:18:47 +08:00
for itemId := range expireItemsMap {
delete(this.itemsMap, itemId)
}
delete(this.expireMap, timestamp)
2024-03-31 11:47:34 +08:00
this.mu.Unlock()
2021-01-03 20:18:47 +08:00
}
2024-03-31 11:47:34 +08:00
2021-01-03 20:18:47 +08:00
return expireItemsMap
}