1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
|
package meter
import (
"sync"
"sync/atomic"
"time"
)
const UnknownTotalSize = 0
type TransferMeterCommand struct {
//nolint:lll
TransferMeterFrequency time.Duration `long:"transfer-meter-frequency" env:"TRANSFER_METER_FREQUENCY" description:"If set to more than 0s it enables an interactive transfer meter"`
}
type UpdateCallback func(written uint64, since time.Duration, done bool)
type meter struct {
count uint64
done, notify chan struct{}
close sync.Once
}
func newMeter() *meter {
return &meter{
done: make(chan struct{}),
notify: make(chan struct{}),
}
}
func (m *meter) start(frequency time.Duration, fn UpdateCallback) {
if frequency < time.Second {
frequency = time.Second
}
started := time.Now()
go func() {
defer close(m.done)
ticker := time.NewTicker(frequency)
defer ticker.Stop()
for {
fn(atomic.LoadUint64(&m.count), time.Since(started), false)
select {
case <-ticker.C:
case <-m.notify:
fn(atomic.LoadUint64(&m.count), time.Since(started), true)
return
}
}
}()
}
func (m *meter) doClose() {
m.close.Do(func() {
// notify we're done
close(m.notify)
// wait for close
<-m.done
})
}
|