// Copyright (C) 2022 Marius Schellenberger package fs import ( "errors" "math" "sync/atomic" "github.com/go-logr/logr" ) var InvalidMaxQuota = errors.New("invalid max quota") type Quota struct { log logr.Logger fs *FS max int64 cur int64 } func NewQuota(max int64, fs *FS, log logr.Logger) (q *Quota, err error) { if max <= 0 { err = InvalidMaxQuota return } q = &Quota{log: log, fs: fs, max: max} return } func (q *Quota) Init() { for _, v := range q.fs.md { q.cur += v.Chunks.Size() } q.log.Info("quota usage", "current", q.cur, "max", q.max) } func (q *Quota) cleanup() { if !q.fs.mu.TryLock() { return } q.log.Info("quota usage", "current", q.cur, "max", q.max) defer q.fs.mu.Unlock() atime := int64(math.MaxInt64) var m *Metadata for _, v := range q.fs.md { if v.Atime != 0 && v.f != nil && v.Atime < atime { atime = v.Atime m = v } } if m != nil { log := q.log.WithValues("file", m.name) log.Info("deleting oldest file") err := m.Delete() if err != nil { q.log.Error(err, "error deleting oldest file") return } atomic.AddInt64(&q.cur, -m.Size) } } func (q *Quota) Add(n int) { if q.max < atomic.AddInt64(&q.cur, int64(n)) { q.cleanup() } }