Files
EdgeNode/internal/caches/list_file_hash_map_sqlite.go

184 lines
3.6 KiB
Go
Raw Normal View History

2024-05-17 18:30:33 +08:00
// Copyright 2022 GoEdge goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
2022-08-20 11:47:57 +08:00
package caches
import (
2024-03-28 17:17:34 +08:00
memutils "github.com/TeaOSLab/EdgeNode/internal/utils/mem"
2024-05-11 09:23:54 +08:00
"github.com/TeaOSLab/EdgeNode/internal/utils/zero"
2022-08-22 09:44:09 +08:00
"math/big"
2022-08-20 11:47:57 +08:00
"sync"
)
2023-10-16 11:48:38 +08:00
const HashMapSharding = 31
2023-10-05 17:40:27 +08:00
2023-10-16 11:48:38 +08:00
var bigIntPool = sync.Pool{
New: func() any {
return big.NewInt(0)
},
}
2023-10-05 17:40:27 +08:00
// SQLiteFileListHashMap 文件Hash列表
type SQLiteFileListHashMap struct {
2023-10-05 17:40:27 +08:00
m []map[uint64]zero.Zero
lockers []*sync.RWMutex
isAvailable bool
isReady bool
2022-08-20 11:47:57 +08:00
}
func NewSQLiteFileListHashMap() *SQLiteFileListHashMap {
2023-10-05 17:40:27 +08:00
var m = make([]map[uint64]zero.Zero, HashMapSharding)
var lockers = make([]*sync.RWMutex, HashMapSharding)
for i := 0; i < HashMapSharding; i++ {
m[i] = map[uint64]zero.Zero{}
lockers[i] = &sync.RWMutex{}
}
return &SQLiteFileListHashMap{
2023-10-05 17:40:27 +08:00
m: m,
lockers: lockers,
isAvailable: false,
isReady: false,
2022-08-20 11:47:57 +08:00
}
}
func (this *SQLiteFileListHashMap) Load(db *SQLiteFileListDB) error {
// 如果系统内存过小,我们不缓存
2024-03-28 17:17:34 +08:00
if memutils.SystemMemoryGB() < 3 {
return nil
}
this.isAvailable = true
2022-08-20 11:47:57 +08:00
var lastId int64
var maxLoops = 50_000
2022-08-20 11:47:57 +08:00
for {
hashList, maxId, err := db.ListHashes(lastId)
if err != nil {
return err
}
if len(hashList) == 0 {
break
}
2022-08-22 09:44:09 +08:00
this.AddHashes(hashList)
2022-08-20 11:47:57 +08:00
lastId = maxId
2023-10-16 11:48:38 +08:00
maxLoops--
if maxLoops <= 0 {
break
}
2022-08-20 11:47:57 +08:00
}
this.isReady = true
return nil
}
func (this *SQLiteFileListHashMap) Add(hash string) {
if !this.isAvailable {
return
}
2023-10-05 17:40:27 +08:00
hashInt, index := this.bigInt(hash)
this.lockers[index].Lock()
this.m[index][hashInt] = zero.New()
this.lockers[index].Unlock()
2022-08-22 09:44:09 +08:00
}
func (this *SQLiteFileListHashMap) AddHashes(hashes []string) {
2022-08-22 09:44:09 +08:00
if !this.isAvailable {
return
}
for _, hash := range hashes {
2023-10-05 17:40:27 +08:00
hashInt, index := this.bigInt(hash)
this.lockers[index].Lock()
this.m[index][hashInt] = zero.New()
this.lockers[index].Unlock()
2022-08-22 09:44:09 +08:00
}
2022-08-20 11:47:57 +08:00
}
func (this *SQLiteFileListHashMap) Delete(hash string) {
if !this.isAvailable {
return
}
2023-10-05 17:40:27 +08:00
hashInt, index := this.bigInt(hash)
this.lockers[index].Lock()
delete(this.m[index], hashInt)
this.lockers[index].Unlock()
2022-08-20 11:47:57 +08:00
}
func (this *SQLiteFileListHashMap) Exist(hash string) bool {
if !this.isAvailable {
return true
}
2022-08-20 11:47:57 +08:00
if !this.isReady {
// 只有完全Ready时才能判断是否为false
return true
}
2023-10-05 17:40:27 +08:00
hashInt, index := this.bigInt(hash)
this.lockers[index].RLock()
_, ok := this.m[index][hashInt]
this.lockers[index].RUnlock()
2022-08-20 11:47:57 +08:00
return ok
}
func (this *SQLiteFileListHashMap) Clean() {
2023-10-05 17:40:27 +08:00
for i := 0; i < HashMapSharding; i++ {
this.lockers[i].Lock()
}
// 这里不能简单清空 this.m ,避免导致别的数据无法写入 map 而产生 panic
for i := 0; i < HashMapSharding; i++ {
this.m[i] = map[uint64]zero.Zero{}
}
2023-10-05 17:40:27 +08:00
for i := HashMapSharding - 1; i >= 0; i-- {
this.lockers[i].Unlock()
}
2022-08-20 11:47:57 +08:00
}
func (this *SQLiteFileListHashMap) IsReady() bool {
2022-08-20 11:47:57 +08:00
return this.isReady
}
2022-08-22 09:44:09 +08:00
func (this *SQLiteFileListHashMap) Len() int {
2023-10-05 17:40:27 +08:00
for i := 0; i < HashMapSharding; i++ {
this.lockers[i].Lock()
}
var count = 0
for _, shard := range this.m {
count += len(shard)
}
for i := HashMapSharding - 1; i >= 0; i-- {
this.lockers[i].Unlock()
}
return count
2022-09-07 11:34:26 +08:00
}
func (this *SQLiteFileListHashMap) SetIsAvailable(isAvailable bool) {
2023-10-01 19:48:35 +08:00
this.isAvailable = isAvailable
}
func (this *SQLiteFileListHashMap) SetIsReady(isReady bool) {
2023-10-05 17:40:27 +08:00
this.isReady = isReady
}
func (this *SQLiteFileListHashMap) bigInt(hash string) (hashInt uint64, index int) {
2023-10-05 17:40:27 +08:00
var bigInt = bigIntPool.Get().(*big.Int)
2022-08-22 09:44:09 +08:00
bigInt.SetString(hash, 16)
2023-10-05 17:40:27 +08:00
hashInt = bigInt.Uint64()
bigIntPool.Put(bigInt)
index = int(hashInt % HashMapSharding)
return
2022-08-22 09:44:09 +08:00
}