github.com/TeaOSLab/EdgeNode@v1.3.8/internal/caches/list_file_kv.go (about) 1 // Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . 2 3 package caches 4 5 import ( 6 "fmt" 7 "github.com/TeaOSLab/EdgeNode/internal/goman" 8 "github.com/TeaOSLab/EdgeNode/internal/remotelogs" 9 "github.com/TeaOSLab/EdgeNode/internal/utils/fnv" 10 "github.com/iwind/TeaGo/types" 11 "strings" 12 "testing" 13 ) 14 15 const countKVStores = 10 16 17 type KVFileList struct { 18 dir string 19 stores [countKVStores]*KVListFileStore 20 21 onAdd func(item *Item) 22 onRemove func(item *Item) 23 } 24 25 func NewKVFileList(dir string) *KVFileList { 26 dir = strings.TrimSuffix(dir, "/") 27 28 var stores = [countKVStores]*KVListFileStore{} 29 for i := 0; i < countKVStores; i++ { 30 stores[i] = NewKVListFileStore(dir + "/db-" + types.String(i) + ".store") 31 } 32 33 return &KVFileList{ 34 dir: dir, 35 stores: stores, 36 } 37 } 38 39 // Init 初始化 40 func (this *KVFileList) Init() error { 41 remotelogs.Println("CACHE", "loading database from '"+this.dir+"' ...") 42 43 var group = goman.NewTaskGroup() 44 var lastErr error 45 46 for _, store := range this.stores { 47 var storeCopy = store 48 group.Run(func() { 49 err := storeCopy.Open() 50 if err != nil { 51 lastErr = fmt.Errorf("open store '"+storeCopy.Path()+"' failed: %w", err) 52 } 53 }) 54 } 55 group.Wait() 56 57 return lastErr 58 } 59 60 // Reset 重置数据 61 func (this *KVFileList) Reset() error { 62 // do nothing 63 return nil 64 } 65 66 // Add 添加内容 67 func (this *KVFileList) Add(hash string, item *Item) error { 68 err := this.getStore(hash).AddItem(hash, item) 69 if err != nil { 70 return err 71 } 72 73 if this.onAdd != nil { 74 this.onAdd(item) 75 } 76 77 return nil 78 } 79 80 // Exist 检查内容是否存在 81 func (this *KVFileList) Exist(hash string) (bool, int64, error) { 82 return this.getStore(hash).ExistItem(hash) 83 } 84 85 // ExistQuick 快速检查内容是否存在 86 func (this *KVFileList) ExistQuick(hash string) (bool, error) { 87 return this.getStore(hash).ExistQuickItem(hash) 88 } 89 90 // CleanPrefix 清除某个前缀的缓存 91 func (this *KVFileList) CleanPrefix(prefix string) error { 92 var group = goman.NewTaskGroup() 93 var lastErr error 94 for _, store := range this.stores { 95 var storeCopy = store 96 group.Run(func() { 97 err := storeCopy.CleanItemsWithPrefix(prefix) 98 if err != nil { 99 lastErr = err 100 } 101 }) 102 } 103 group.Wait() 104 return lastErr 105 } 106 107 // CleanMatchKey 清除通配符匹配的Key 108 func (this *KVFileList) CleanMatchKey(key string) error { 109 var group = goman.NewTaskGroup() 110 var lastErr error 111 for _, store := range this.stores { 112 var storeCopy = store 113 group.Run(func() { 114 err := storeCopy.CleanItemsWithWildcardKey(key) 115 if err != nil { 116 lastErr = err 117 } 118 }) 119 } 120 group.Wait() 121 return lastErr 122 } 123 124 // CleanMatchPrefix 清除通配符匹配的前缀 125 func (this *KVFileList) CleanMatchPrefix(prefix string) error { 126 var group = goman.NewTaskGroup() 127 var lastErr error 128 for _, store := range this.stores { 129 var storeCopy = store 130 group.Run(func() { 131 err := storeCopy.CleanItemsWithWildcardPrefix(prefix) 132 if err != nil { 133 lastErr = err 134 } 135 }) 136 } 137 group.Wait() 138 return lastErr 139 } 140 141 // Remove 删除内容 142 func (this *KVFileList) Remove(hash string) error { 143 err := this.getStore(hash).RemoveItem(hash) 144 if err != nil { 145 return err 146 } 147 148 if this.onRemove != nil { 149 // when remove file item, no any extra information needed 150 this.onRemove(nil) 151 } 152 153 return nil 154 } 155 156 // Purge 清理过期数据 157 func (this *KVFileList) Purge(count int, callback func(hash string) error) (int, error) { 158 count /= countKVStores 159 if count <= 0 { 160 count = 100 161 } 162 163 var countFound = 0 164 var lastErr error 165 for _, store := range this.stores { 166 purgeCount, err := store.PurgeItems(count, callback) 167 countFound += purgeCount 168 if err != nil { 169 lastErr = err 170 } 171 } 172 173 return countFound, lastErr 174 } 175 176 // PurgeLFU 清理LFU数据 177 func (this *KVFileList) PurgeLFU(count int, callback func(hash string) error) error { 178 count /= countKVStores 179 if count <= 0 { 180 count = 100 181 } 182 183 var lastErr error 184 for _, store := range this.stores { 185 err := store.PurgeLFUItems(count, callback) 186 if err != nil { 187 lastErr = err 188 } 189 } 190 return lastErr 191 } 192 193 // CleanAll 清除所有缓存 194 func (this *KVFileList) CleanAll() error { 195 var group = goman.NewTaskGroup() 196 var lastErr error 197 for _, store := range this.stores { 198 var storeCopy = store 199 group.Run(func() { 200 err := storeCopy.RemoveAllItems() 201 if err != nil { 202 lastErr = err 203 } 204 }) 205 } 206 group.Wait() 207 return lastErr 208 } 209 210 // Stat 统计 211 func (this *KVFileList) Stat(check func(hash string) bool) (*Stat, error) { 212 var stat = &Stat{} 213 214 var group = goman.NewTaskGroup() 215 216 var lastErr error 217 for _, store := range this.stores { 218 var storeCopy = store 219 group.Run(func() { 220 storeStat, err := storeCopy.StatItems() 221 if err != nil { 222 lastErr = err 223 return 224 } 225 226 group.Lock() 227 stat.Size += storeStat.Size 228 stat.ValueSize += storeStat.ValueSize 229 stat.Count += storeStat.Count 230 group.Unlock() 231 }) 232 } 233 234 group.Wait() 235 236 return stat, lastErr 237 } 238 239 // Count 总数量 240 func (this *KVFileList) Count() (int64, error) { 241 var count int64 242 243 var group = goman.NewTaskGroup() 244 245 var lastErr error 246 for _, store := range this.stores { 247 var storeCopy = store 248 group.Run(func() { 249 countStoreItems, err := storeCopy.CountItems() 250 if err != nil { 251 lastErr = err 252 return 253 } 254 255 group.Lock() 256 count += countStoreItems 257 group.Unlock() 258 }) 259 } 260 261 group.Wait() 262 263 return count, lastErr 264 } 265 266 // OnAdd 添加事件 267 func (this *KVFileList) OnAdd(fn func(item *Item)) { 268 this.onAdd = fn 269 } 270 271 // OnRemove 删除事件 272 func (this *KVFileList) OnRemove(fn func(item *Item)) { 273 this.onRemove = fn 274 } 275 276 // Close 关闭 277 func (this *KVFileList) Close() error { 278 var lastErr error 279 var group = goman.NewTaskGroup() 280 for _, store := range this.stores { 281 var storeCopy = store 282 group.Run(func() { 283 err := storeCopy.Close() 284 if err != nil { 285 lastErr = err 286 } 287 }) 288 } 289 group.Wait() 290 return lastErr 291 } 292 293 // IncreaseHit 增加点击量 294 func (this *KVFileList) IncreaseHit(hash string) error { 295 // do nothing 296 return nil 297 } 298 299 func (this *KVFileList) TestInspect(t *testing.T) error { 300 for _, store := range this.stores { 301 err := store.TestInspect(t) 302 if err != nil { 303 return err 304 } 305 } 306 return nil 307 } 308 309 func (this *KVFileList) getStore(hash string) *KVListFileStore { 310 return this.stores[fnv.HashString(hash)%countKVStores] 311 }