github.com/kayoticsully/syncthing@v0.8.9-0.20140724133906-c45a2fdc03f8/model/suppressor.go (about)

     1  // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
     2  // All rights reserved. Use of this source code is governed by an MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package model
     6  
     7  import (
     8  	"os"
     9  	"sync"
    10  	"time"
    11  )
    12  
    13  const (
    14  	MaxChangeHistory = 4
    15  )
    16  
    17  type change struct {
    18  	size int64
    19  	when time.Time
    20  }
    21  
    22  type changeHistory struct {
    23  	changes []change
    24  	next    int64
    25  	prevSup bool
    26  }
    27  
    28  type suppressor struct {
    29  	sync.Mutex
    30  	changes   map[string]changeHistory
    31  	threshold int64 // bytes/s
    32  }
    33  
    34  func (h changeHistory) bandwidth(t time.Time) int64 {
    35  	if len(h.changes) == 0 {
    36  		return 0
    37  	}
    38  
    39  	var t0 = h.changes[0].when
    40  	if t == t0 {
    41  		return 0
    42  	}
    43  
    44  	var bw float64
    45  	for _, c := range h.changes {
    46  		bw += float64(c.size)
    47  	}
    48  	return int64(bw / t.Sub(t0).Seconds())
    49  }
    50  
    51  func (h *changeHistory) append(size int64, t time.Time) {
    52  	c := change{size, t}
    53  	if len(h.changes) == MaxChangeHistory {
    54  		h.changes = h.changes[1:MaxChangeHistory]
    55  	}
    56  	h.changes = append(h.changes, c)
    57  }
    58  
    59  func (s *suppressor) Suppress(name string, fi os.FileInfo) (cur, prev bool) {
    60  	return s.suppress(name, fi.Size(), time.Now())
    61  }
    62  
    63  func (s *suppressor) suppress(name string, size int64, t time.Time) (bool, bool) {
    64  	s.Lock()
    65  
    66  	if s.changes == nil {
    67  		s.changes = make(map[string]changeHistory)
    68  	}
    69  	h := s.changes[name]
    70  	sup := h.bandwidth(t) > s.threshold
    71  	prevSup := h.prevSup
    72  	h.prevSup = sup
    73  	if !sup {
    74  		h.append(size, t)
    75  	}
    76  	s.changes[name] = h
    77  
    78  	s.Unlock()
    79  
    80  	return sup, prevSup
    81  }