github.com/TeaOSLab/EdgeNode@v1.3.8/internal/caches/manager.go (about) 1 package caches 2 3 import ( 4 "fmt" 5 "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" 6 "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared" 7 teaconst "github.com/TeaOSLab/EdgeNode/internal/const" 8 "github.com/TeaOSLab/EdgeNode/internal/events" 9 "github.com/TeaOSLab/EdgeNode/internal/remotelogs" 10 memutils "github.com/TeaOSLab/EdgeNode/internal/utils/mem" 11 "github.com/iwind/TeaGo/lists" 12 "github.com/iwind/TeaGo/types" 13 "golang.org/x/sys/unix" 14 "strconv" 15 "sync" 16 ) 17 18 var SharedManager = NewManager() 19 20 func init() { 21 if !teaconst.IsMain { 22 return 23 } 24 25 events.OnClose(func() { 26 remotelogs.Println("CACHE", "quiting cache manager") 27 SharedManager.UpdatePolicies([]*serverconfigs.HTTPCachePolicy{}) 28 }) 29 } 30 31 // Manager 缓存策略管理器 32 type Manager struct { 33 // 全局配置 34 MaxDiskCapacity *shared.SizeCapacity 35 MainDiskDir string 36 SubDiskDirs []*serverconfigs.CacheDir 37 MaxMemoryCapacity *shared.SizeCapacity 38 39 CountFileStorages int 40 CountMemoryStorages int 41 42 policyMap map[int64]*serverconfigs.HTTPCachePolicy // policyId => []*Policy 43 storageMap map[int64]StorageInterface // policyId => *Storage 44 locker sync.RWMutex 45 } 46 47 // NewManager 获取管理器对象 48 func NewManager() *Manager { 49 var m = &Manager{ 50 policyMap: map[int64]*serverconfigs.HTTPCachePolicy{}, 51 storageMap: map[int64]StorageInterface{}, 52 } 53 54 return m 55 } 56 57 // UpdatePolicies 重新设置策略 58 func (this *Manager) UpdatePolicies(newPolicies []*serverconfigs.HTTPCachePolicy) { 59 this.locker.Lock() 60 defer this.locker.Unlock() 61 62 var newPolicyIds = []int64{} 63 for _, policy := range newPolicies { 64 // 使用节点单独的缓存目录 65 policy.UpdateDiskDir(this.MainDiskDir, this.SubDiskDirs) 66 67 newPolicyIds = append(newPolicyIds, policy.Id) 68 } 69 70 // 停止旧有的 71 for _, oldPolicy := range this.policyMap { 72 if !lists.ContainsInt64(newPolicyIds, oldPolicy.Id) { 73 remotelogs.Println("CACHE", "remove policy "+strconv.FormatInt(oldPolicy.Id, 10)) 74 delete(this.policyMap, oldPolicy.Id) 75 storage, ok := this.storageMap[oldPolicy.Id] 76 if ok { 77 storage.Stop() 78 delete(this.storageMap, oldPolicy.Id) 79 } 80 } 81 } 82 83 // 启动新的 84 for _, newPolicy := range newPolicies { 85 _, ok := this.policyMap[newPolicy.Id] 86 if !ok { 87 remotelogs.Println("CACHE", "add policy "+strconv.FormatInt(newPolicy.Id, 10)) 88 } 89 90 // 初始化 91 err := newPolicy.Init() 92 if err != nil { 93 remotelogs.Error("CACHE", "UpdatePolicies: init policy error: "+err.Error()) 94 continue 95 } 96 this.policyMap[newPolicy.Id] = newPolicy 97 } 98 99 // 启动存储管理 100 for _, policy := range this.policyMap { 101 storage, ok := this.storageMap[policy.Id] 102 if !ok { 103 storage = this.NewStorageWithPolicy(policy) 104 if storage == nil { 105 remotelogs.Error("CACHE", "can not find storage type '"+policy.Type+"'") 106 continue 107 } 108 err := storage.Init() 109 if err != nil { 110 remotelogs.Error("CACHE", "UpdatePolicies: init storage failed: "+err.Error()) 111 continue 112 } 113 this.storageMap[policy.Id] = storage 114 } else { 115 // 检查policy是否有变化 116 if !storage.Policy().IsSame(policy) { 117 // 检查是否可以直接修改 118 if storage.CanUpdatePolicy(policy) { 119 err := policy.Init() 120 if err != nil { 121 remotelogs.Error("CACHE", "reload policy '"+types.String(policy.Id)+"' failed: init policy failed: "+err.Error()) 122 continue 123 } 124 remotelogs.Println("CACHE", "reload policy '"+types.String(policy.Id)+"'") 125 storage.UpdatePolicy(policy) 126 continue 127 } 128 129 remotelogs.Println("CACHE", "restart policy '"+types.String(policy.Id)+"'") 130 131 // 停止老的 132 storage.Stop() 133 delete(this.storageMap, policy.Id) 134 135 // 启动新的 136 storage = this.NewStorageWithPolicy(policy) 137 if storage == nil { 138 remotelogs.Error("CACHE", "can not find storage type '"+policy.Type+"'") 139 continue 140 } 141 err := storage.Init() 142 if err != nil { 143 remotelogs.Error("CACHE", "UpdatePolicies: init storage failed: "+err.Error()) 144 continue 145 } 146 this.storageMap[policy.Id] = storage 147 } 148 } 149 } 150 151 this.CountFileStorages = 0 152 this.CountMemoryStorages = 0 153 for _, storage := range this.storageMap { 154 _, isFileStorage := storage.(*FileStorage) 155 this.CountMemoryStorages++ 156 if isFileStorage { 157 this.CountFileStorages++ 158 } 159 } 160 } 161 162 // FindPolicy 获取Policy信息 163 func (this *Manager) FindPolicy(policyId int64) *serverconfigs.HTTPCachePolicy { 164 this.locker.RLock() 165 defer this.locker.RUnlock() 166 167 return this.policyMap[policyId] 168 } 169 170 // FindStorageWithPolicy 根据策略ID查找存储 171 func (this *Manager) FindStorageWithPolicy(policyId int64) StorageInterface { 172 this.locker.RLock() 173 defer this.locker.RUnlock() 174 175 return this.storageMap[policyId] 176 } 177 178 // NewStorageWithPolicy 根据策略获取存储对象 179 func (this *Manager) NewStorageWithPolicy(policy *serverconfigs.HTTPCachePolicy) StorageInterface { 180 switch policy.Type { 181 case serverconfigs.CachePolicyStorageFile: 182 return NewFileStorage(policy) 183 case serverconfigs.CachePolicyStorageMemory: 184 return NewMemoryStorage(policy, nil) 185 } 186 return nil 187 } 188 189 // StorageMap 获取已有的存储对象 190 func (this *Manager) StorageMap() map[int64]StorageInterface { 191 return this.storageMap 192 } 193 194 // TotalDiskSize 消耗的磁盘尺寸 195 func (this *Manager) TotalDiskSize() int64 { 196 this.locker.RLock() 197 defer this.locker.RUnlock() 198 199 var total = int64(0) 200 var sidMap = map[string]bool{} // partition sid => bool 201 for _, storage := range this.storageMap { 202 // 这里不能直接用 storage.TotalDiskSize() 相加,因为多个缓存策略缓存目录可能处在同一个分区目录下 203 fileStorage, ok := storage.(*FileStorage) 204 if ok { 205 var options = fileStorage.options // copy 206 if options != nil { 207 var dir = options.Dir // copy 208 if len(dir) == 0 { 209 continue 210 } 211 var stat = &unix.Statfs_t{} 212 err := unix.Statfs(dir, stat) 213 if err != nil { 214 continue 215 } 216 var sid = fmt.Sprintf("%d_%d", stat.Fsid.Val[0], stat.Fsid.Val[1]) 217 if sidMap[sid] { 218 continue 219 } 220 sidMap[sid] = true 221 total += int64(stat.Blocks-stat.Bfree) * int64(stat.Bsize) // we add extra int64() for darwin 222 } 223 } 224 } 225 226 if total < 0 { 227 total = 0 228 } 229 230 return total 231 } 232 233 // TotalMemorySize 消耗的内存尺寸 234 func (this *Manager) TotalMemorySize() int64 { 235 this.locker.RLock() 236 defer this.locker.RUnlock() 237 238 total := int64(0) 239 for _, storage := range this.storageMap { 240 total += storage.TotalMemorySize() 241 } 242 return total 243 } 244 245 // FindAllCachePaths 所有缓存路径 246 func (this *Manager) FindAllCachePaths() []string { 247 this.locker.Lock() 248 defer this.locker.Unlock() 249 250 var result = []string{} 251 for _, policy := range this.policyMap { 252 if policy.Type == serverconfigs.CachePolicyStorageFile { 253 if policy.Options != nil { 254 dir, ok := policy.Options["dir"] 255 if ok { 256 var dirString = types.String(dir) 257 if len(dirString) > 0 { 258 result = append(result, dirString) 259 } 260 } 261 } 262 } 263 } 264 return result 265 } 266 267 // FindAllStorages 读取所有缓存存储 268 func (this *Manager) FindAllStorages() []StorageInterface { 269 this.locker.Lock() 270 defer this.locker.Unlock() 271 272 var storages = []StorageInterface{} 273 for _, storage := range this.storageMap { 274 storages = append(storages, storage) 275 } 276 return storages 277 } 278 279 // ScanGarbageCaches 清理目录中“失联”的缓存文件 280 func (this *Manager) ScanGarbageCaches(callback func(path string) error) error { 281 var storages = this.FindAllStorages() 282 for _, storage := range storages { 283 fileStorage, ok := storage.(*FileStorage) 284 if !ok { 285 continue 286 } 287 err := fileStorage.ScanGarbageCaches(callback) 288 if err != nil { 289 return err 290 } 291 } 292 return nil 293 } 294 295 // MaxSystemMemoryBytesPerStorage 计算单个策略能使用的系统最大内存 296 func (this *Manager) MaxSystemMemoryBytesPerStorage() int64 { 297 var count = this.CountMemoryStorages 298 if count < 1 { 299 count = 1 300 } 301 302 var resultBytes = int64(memutils.SystemMemoryBytes()) / 3 / int64(count) // 1/3 of the system memory 303 if resultBytes < 1<<30 { 304 resultBytes = 1 << 30 305 } 306 return resultBytes 307 }