2014-05-14 20:26:55 -07:00
|
|
|
package model
|
2014-03-02 15:58:14 -07:00
|
|
|
|
|
|
|
import (
|
2014-03-08 15:02:01 -07:00
|
|
|
"os"
|
2014-03-02 15:58:14 -07:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
MaxChangeHistory = 4
|
|
|
|
)
|
|
|
|
|
|
|
|
type change struct {
|
|
|
|
size int64
|
|
|
|
when time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
type changeHistory struct {
|
|
|
|
changes []change
|
|
|
|
next int64
|
|
|
|
prevSup bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type suppressor struct {
|
|
|
|
sync.Mutex
|
|
|
|
changes map[string]changeHistory
|
|
|
|
threshold int64 // bytes/s
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h changeHistory) bandwidth(t time.Time) int64 {
|
|
|
|
if len(h.changes) == 0 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
var t0 = h.changes[0].when
|
|
|
|
if t == t0 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
var bw float64
|
|
|
|
for _, c := range h.changes {
|
|
|
|
bw += float64(c.size)
|
|
|
|
}
|
|
|
|
return int64(bw / t.Sub(t0).Seconds())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *changeHistory) append(size int64, t time.Time) {
|
|
|
|
c := change{size, t}
|
|
|
|
if len(h.changes) == MaxChangeHistory {
|
|
|
|
h.changes = h.changes[1:MaxChangeHistory]
|
|
|
|
}
|
|
|
|
h.changes = append(h.changes, c)
|
|
|
|
}
|
|
|
|
|
2014-05-14 20:26:55 -07:00
|
|
|
func (s *suppressor) Suppress(name string, fi os.FileInfo) (cur, prev bool) {
|
|
|
|
return s.suppress(name, fi.Size(), time.Now())
|
2014-03-08 15:02:01 -07:00
|
|
|
}
|
|
|
|
|
2014-03-02 15:58:14 -07:00
|
|
|
func (s *suppressor) suppress(name string, size int64, t time.Time) (bool, bool) {
|
|
|
|
s.Lock()
|
|
|
|
|
|
|
|
if s.changes == nil {
|
|
|
|
s.changes = make(map[string]changeHistory)
|
|
|
|
}
|
|
|
|
h := s.changes[name]
|
|
|
|
sup := h.bandwidth(t) > s.threshold
|
|
|
|
prevSup := h.prevSup
|
|
|
|
h.prevSup = sup
|
|
|
|
if !sup {
|
|
|
|
h.append(size, t)
|
|
|
|
}
|
|
|
|
s.changes[name] = h
|
|
|
|
|
|
|
|
s.Unlock()
|
|
|
|
|
|
|
|
return sup, prevSup
|
|
|
|
}
|