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  }