// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . //go:build plus package mmap import ( "github.com/TeaOSLab/EdgeNode/internal/utils/fnv" fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs" "github.com/TeaOSLab/EdgeNode/internal/utils/zero" "sync" ) // TODO 当缓存文件更新时在mmap map中删除对应mmap,以便于及时更新?修改inotify相关代码? const mmapMuShards = 32 const enableShareMode = false // 暂时不启用,需要更多时间的测试 var mmapMaps = [mmapMuShards]map[string]map[*SharedMMAP]zero.Zero{} // [{ filename => { mmap => Zero } }, ...] var mmapMapMu = [mmapMuShards]*sync.RWMutex{} func init() { for i := 0; i < mmapMuShards; i++ { mmapMaps[i] = map[string]map[*SharedMMAP]zero.Zero{} mmapMapMu[i] = &sync.RWMutex{} } } func OpenSharedMMAP(filename string) (*SharedMMAP, error) { var mod = fnv.HashString(filename) % mmapMuShards var mu = mmapMapMu[mod] var m *SharedMMAP var mmapMap map[string]map[*SharedMMAP]zero.Zero if enableShareMode { mu.RLock() mmapMap = mmapMaps[mod] bucket, ok := mmapMap[filename] if ok && len(bucket) > 0 { for firstM := range bucket { m = firstM break } } mu.RUnlock() if m != nil && m.AddRef() { return m, nil } } fp, err := fsutils.Open(filename) if err != nil { return nil, err } stat, err := fp.Stat() if err != nil { _ = fp.Close() return nil, err } reader, err := OpenFile(fp, stat.Size()) if err != nil { return nil, err } m = NewSharedMMAP(filename, stat, reader, mod) if enableShareMode { mu.Lock() if mmapMap[filename] == nil { mmapMap[filename] = map[*SharedMMAP]zero.Zero{ m: {}, } } else { mmapMap[filename][m] = zero.Zero{} } mu.Unlock() } return m, nil } func CountSharedMMAP() int { var count int for i := 0; i < mmapMuShards; i++ { mmapMapMu[i].RLock() for _, bucket := range mmapMaps[i] { count += len(bucket) } mmapMapMu[i].RUnlock() } return count }