|
|
|
@@ -0,0 +1,128 @@ |
|
|
|
package cache |
|
|
|
|
|
|
|
import ( |
|
|
|
"encoding/json" |
|
|
|
"os" |
|
|
|
"path/filepath" |
|
|
|
"strings" |
|
|
|
"sync" |
|
|
|
|
|
|
|
"gitlink.org.cn/cloudream/common/pkgs/logger" |
|
|
|
) |
|
|
|
|
|
|
|
type SyncFilterRuleConfig struct { |
|
|
|
Repo FilterRepoRule `json:"repo"` |
|
|
|
Object FilterObjectRule `json:"object"` |
|
|
|
} |
|
|
|
|
|
|
|
type FilterRepoRule struct { |
|
|
|
BlackListMode bool `json:"blackListMode"` // 是否黑名单模式 |
|
|
|
Names []string `json:"names"` // 匹配模式 |
|
|
|
} |
|
|
|
|
|
|
|
type FilterObjectRule struct { |
|
|
|
BlackListMode bool `json:"blackListMode"` // 是否黑名单模式 |
|
|
|
Exts []string `json:"exts"` // 文件名后缀 |
|
|
|
MinSize int64 `json:"minSize"` |
|
|
|
MaxSize int64 `json:"maxSize"` // 0为不限制大小 |
|
|
|
} |
|
|
|
|
|
|
|
type SyncFilter struct { |
|
|
|
lock *sync.RWMutex |
|
|
|
config SyncFilterRuleConfig |
|
|
|
repoNames map[string]bool |
|
|
|
exts map[string]bool |
|
|
|
} |
|
|
|
|
|
|
|
func NewSyncFilter() *SyncFilter { |
|
|
|
return &SyncFilter{ |
|
|
|
lock: &sync.RWMutex{}, |
|
|
|
config: SyncFilterRuleConfig{}, |
|
|
|
repoNames: make(map[string]bool), |
|
|
|
exts: make(map[string]bool), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (f *SyncFilter) ShouldSync(fullPathComps []string, size int64) bool { |
|
|
|
f.lock.RLock() |
|
|
|
defer f.lock.RUnlock() |
|
|
|
|
|
|
|
return f.shouldSyncUnlocked(fullPathComps, size) |
|
|
|
} |
|
|
|
|
|
|
|
func (f *SyncFilter) shouldSyncUnlocked(fullPathComps []string, size int64) bool { |
|
|
|
// user/repo/objects/pack/pack-xxx.pack 或者 user/repo/objects/xx/xxxxxxxxx |
|
|
|
if len(fullPathComps) < 5 { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
repoName := fullPathComps[1] |
|
|
|
if f.repoNames[repoName] { |
|
|
|
if f.config.Repo.BlackListMode { |
|
|
|
return false |
|
|
|
} |
|
|
|
} else if !f.config.Repo.BlackListMode { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// ext包含"." |
|
|
|
ext := filepath.Ext(fullPathComps[len(fullPathComps)-1]) |
|
|
|
if f.exts[ext] { |
|
|
|
if f.config.Object.BlackListMode { |
|
|
|
return false |
|
|
|
} |
|
|
|
} else if !f.config.Object.BlackListMode { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
if size < f.config.Object.MinSize || (f.config.Object.MaxSize > 0 && size > f.config.Object.MaxSize) { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
if fullPathComps[2] != "objects" { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
if fullPathComps[3] == "pack" { |
|
|
|
// 避免同步临时文件 |
|
|
|
if !strings.HasPrefix(fullPathComps[4], "pack-") { |
|
|
|
return false |
|
|
|
} |
|
|
|
} else if len(fullPathComps[3]) == 2 { |
|
|
|
// 未压缩的objects |
|
|
|
} else { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
return true |
|
|
|
} |
|
|
|
|
|
|
|
func (f *SyncFilter) ReloadConfig(path string) { |
|
|
|
data, err := os.ReadFile(path) |
|
|
|
if err != nil { |
|
|
|
logger.Warnf("loading trace rule config: %v", err) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
cfg := SyncFilterRuleConfig{} |
|
|
|
err = json.Unmarshal(data, &cfg) |
|
|
|
if err != nil { |
|
|
|
logger.Warnf("unmarshal trace rule config: %v", err) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
f.lock.Lock() |
|
|
|
defer f.lock.Unlock() |
|
|
|
|
|
|
|
f.config = cfg |
|
|
|
f.repoNames = make(map[string]bool) |
|
|
|
for _, name := range cfg.Repo.Names { |
|
|
|
f.repoNames[name] = true |
|
|
|
} |
|
|
|
f.exts = make(map[string]bool) |
|
|
|
for _, ext := range cfg.Object.Exts { |
|
|
|
f.exts[ext] = true |
|
|
|
} |
|
|
|
|
|
|
|
logger.Infof("trace rule config reloaded: repoNames=%v, exts=%v, minSize=%d, maxSize=%d", len(f.repoNames), len(f.exts), f.config.Object.MinSize, f.config.Object.MaxSize) |
|
|
|
} |