diff --git a/go.mod b/go.mod index 41cd8cf48a..d7a7a78141 100644 --- a/go.mod +++ b/go.mod @@ -67,7 +67,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 - github.com/vbauerster/mpb/v8 v8.8.1 + github.com/vbauerster/mpb/v8 v8.8.3 github.com/vishvananda/netlink v1.3.0 go.etcd.io/bbolt v1.3.10 golang.org/x/crypto v0.26.0 diff --git a/go.sum b/go.sum index 746094d91c..85eb9c9a37 100644 --- a/go.sum +++ b/go.sum @@ -512,8 +512,8 @@ github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= -github.com/vbauerster/mpb/v8 v8.8.1 h1:7MtGwKWa9RhThnmUDb7d4Ze6YVw2lCwA60ENsNUxX6k= -github.com/vbauerster/mpb/v8 v8.8.1/go.mod h1:JfCCrtcMsJwP6ZwMn9e5LMnNyp3TVNpUWWkN+nd4EWk= +github.com/vbauerster/mpb/v8 v8.8.3 h1:dTOByGoqwaTJYPubhVz3lO5O6MK553XVgUo33LdnNsQ= +github.com/vbauerster/mpb/v8 v8.8.3/go.mod h1:JfCCrtcMsJwP6ZwMn9e5LMnNyp3TVNpUWWkN+nd4EWk= github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= diff --git a/vendor/github.com/vbauerster/mpb/v8/bar.go b/vendor/github.com/vbauerster/mpb/v8/bar.go index f47c4db4ce..73753f0291 100644 --- a/vendor/github.com/vbauerster/mpb/v8/bar.go +++ b/vendor/github.com/vbauerster/mpb/v8/bar.go @@ -31,28 +31,26 @@ type extenderFunc func(decor.Statistics, ...io.Reader) ([]io.Reader, error) // bState is actual bar's state. type bState struct { - id int - priority int - reqWidth int - shutdown int - total int64 - current int64 - refill int64 - trimSpace bool - aborted bool - triggerComplete bool - rmOnComplete bool - noPop bool - autoRefresh bool - buffers [3]*bytes.Buffer - decorators [2][]decor.Decorator - averageDecorators []decor.AverageDecorator - ewmaDecorators []decor.EwmaDecorator - shutdownListeners []decor.ShutdownListener - filler BarFiller - extender extenderFunc - renderReq chan<- time.Time - waitBar *Bar // key for (*pState).queueBars + id int + priority int + reqWidth int + shutdown int + total int64 + current int64 + refill int64 + trimSpace bool + aborted bool + triggerComplete bool + rmOnComplete bool + noPop bool + autoRefresh bool + buffers [3]*bytes.Buffer + decorators [2][]decor.Decorator + ewmaDecorators []decor.EwmaDecorator + filler BarFiller + extender extenderFunc + renderReq chan<- time.Time + waitBar *Bar // key for (*pState).queueBars } type renderFrame struct { @@ -158,21 +156,25 @@ func (b *Bar) SetRefill(amount int64) { } } -// TraverseDecorators traverses all available decorators and calls cb func on each. +// TraverseDecorators traverses available decorators and calls cb func +// on each in a new goroutine. Decorators implementing decor.Wrapper +// interface are unwrapped first. func (b *Bar) TraverseDecorators(cb func(decor.Decorator)) { - iter := make(chan decor.Decorator) select { case b.operateState <- func(s *bState) { + var wg sync.WaitGroup for _, decorators := range s.decorators { + wg.Add(len(decorators)) for _, d := range decorators { - iter <- d + d := d + go func() { + cb(unwrap(d)) + wg.Done() + }() } } - close(iter) + wg.Wait() }: - for d := range iter { - cb(unwrap(d)) - } case <-b.ctx.Done(): } } @@ -239,31 +241,6 @@ func (b *Bar) SetCurrent(current int64) { } } -// EwmaSetCurrent sets progress' current to an arbitrary value and updates -// EWMA based decorators by dur of a single iteration. -func (b *Bar) EwmaSetCurrent(current int64, iterDur time.Duration) { - if current < 0 { - return - } - result := make(chan *sync.WaitGroup) - select { - case b.operateState <- func(s *bState) { - n := current - s.current - s.current = current - if s.triggerComplete && s.current >= s.total { - s.current = s.total - s.triggerCompletion(b) - } - var wg sync.WaitGroup - s.decoratorEwmaUpdate(n, iterDur, &wg) - result <- &wg - }: - wg := <-result - wg.Wait() - case <-b.ctx.Done(): - } -} - // Increment is a shorthand for b.IncrInt64(1). func (b *Bar) Increment() { b.IncrInt64(1) @@ -301,38 +278,67 @@ func (b *Bar) EwmaIncrBy(n int, iterDur time.Duration) { // EwmaIncrInt64 increments progress by amount of n and updates EWMA based // decorators by dur of a single iteration. func (b *Bar) EwmaIncrInt64(n int64, iterDur time.Duration) { - result := make(chan *sync.WaitGroup) select { case b.operateState <- func(s *bState) { + var wg sync.WaitGroup + wg.Add(len(s.ewmaDecorators)) + for _, d := range s.ewmaDecorators { + d := d + go func() { + d.EwmaUpdate(n, iterDur) + wg.Done() + }() + } s.current += n if s.triggerComplete && s.current >= s.total { s.current = s.total s.triggerCompletion(b) } - var wg sync.WaitGroup - s.decoratorEwmaUpdate(n, iterDur, &wg) - result <- &wg - }: - wg := <-result wg.Wait() + }: case <-b.ctx.Done(): } } -// DecoratorAverageAdjust adjusts all average based decorators. Call -// if you need to adjust start time of all average based decorators -// or after progress resume. -func (b *Bar) DecoratorAverageAdjust(start time.Time) { +// EwmaSetCurrent sets progress' current to an arbitrary value and updates +// EWMA based decorators by dur of a single iteration. +func (b *Bar) EwmaSetCurrent(current int64, iterDur time.Duration) { + if current < 0 { + return + } select { case b.operateState <- func(s *bState) { - for _, d := range s.averageDecorators { - d.AverageAdjust(start) + n := current - s.current + var wg sync.WaitGroup + wg.Add(len(s.ewmaDecorators)) + for _, d := range s.ewmaDecorators { + d := d + go func() { + d.EwmaUpdate(n, iterDur) + wg.Done() + }() } + s.current = current + if s.triggerComplete && s.current >= s.total { + s.current = s.total + s.triggerCompletion(b) + } + wg.Wait() }: case <-b.ctx.Done(): } } +// DecoratorAverageAdjust adjusts decorators implementing decor.AverageDecorator interface. +// Call if there is need to set start time after decorators have been constructed. +func (b *Bar) DecoratorAverageAdjust(start time.Time) { + b.TraverseDecorators(func(d decor.Decorator) { + if d, ok := d.(decor.AverageDecorator); ok { + d.AverageAdjust(start) + } + }) +} + // SetPriority changes bar's order among multiple bars. Zero is highest // priority, i.e. bar will be on top. If you don't need to set priority // dynamically, better use BarPriority option. @@ -396,18 +402,28 @@ func (b *Bar) Wait() { } func (b *Bar) serve(bs *bState) { + decoratorsOnShutdown := func(decorators []decor.Decorator) { + for _, d := range decorators { + if d, ok := unwrap(d).(decor.ShutdownListener); ok { + b.container.bwg.Add(1) + go func() { + d.OnShutdown() + b.container.bwg.Done() + }() + } + } + } for { select { case op := <-b.operateState: op(bs) case <-b.ctx.Done(): - shutdownListeners := bs.shutdownListeners + decoratorsOnShutdown(bs.decorators[0]) + decoratorsOnShutdown(bs.decorators[1]) + // bar can be aborted by canceling parent ctx without calling b.Abort bs.aborted = !bs.completed() b.bs = bs close(b.bsOk) - for _, d := range shutdownListeners { - d.OnShutdown() - } b.container.bwg.Done() return } @@ -549,18 +565,11 @@ func (s *bState) wSyncTable() (table syncTable) { return table } -func (s *bState) sortDecorators(decorators []decor.Decorator) { +func (s *bState) populateEwmaDecorators(decorators []decor.Decorator) { for _, d := range decorators { - d := unwrap(d) - if d, ok := d.(decor.AverageDecorator); ok { - s.averageDecorators = append(s.averageDecorators, d) - } - if d, ok := d.(decor.EwmaDecorator); ok { + if d, ok := unwrap(d).(decor.EwmaDecorator); ok { s.ewmaDecorators = append(s.ewmaDecorators, d) } - if d, ok := d.(decor.ShutdownListener); ok { - s.shutdownListeners = append(s.shutdownListeners, d) - } } } @@ -580,17 +589,6 @@ func (s bState) completed() bool { return s.triggerComplete && s.current == s.total } -func (s bState) decoratorEwmaUpdate(n int64, dur time.Duration, wg *sync.WaitGroup) { - wg.Add(len(s.ewmaDecorators)) - for _, d := range s.ewmaDecorators { - d := d - go func() { - d.EwmaUpdate(n, dur) - wg.Done() - }() - } -} - func (s bState) newStatistics(tw int) decor.Statistics { return decor.Statistics{ AvailableWidth: tw, diff --git a/vendor/github.com/vbauerster/mpb/v8/bar_filler_bar.go b/vendor/github.com/vbauerster/mpb/v8/bar_filler_bar.go index fd6ef0f40d..7a036d9870 100644 --- a/vendor/github.com/vbauerster/mpb/v8/bar_filler_bar.go +++ b/vendor/github.com/vbauerster/mpb/v8/bar_filler_bar.go @@ -50,13 +50,13 @@ type flushSection struct { } type bFiller struct { - components [components]component - meta [components]func(io.Writer, []byte) error - flush func(io.Writer, ...flushSection) error - tipOnComplete bool - tip struct { - frames []component - count uint + components [components]component + meta [components]func(io.Writer, []byte) error + flush func(io.Writer, ...flushSection) error + tip struct { + onComplete bool + count uint + frames []component } } @@ -155,8 +155,7 @@ func (s barStyle) Reverse() BarStyleComposer { func (s barStyle) Build() BarFiller { bf := &bFiller{ - meta: s.metaFuncs, - tipOnComplete: s.tipOnComplete, + meta: s.metaFuncs, } bf.components[iLbound] = component{ width: runewidth.StringWidth(s.style[iLbound]), @@ -178,6 +177,7 @@ func (s barStyle) Build() BarFiller { width: runewidth.StringWidth(s.style[iPadding]), bytes: []byte(s.style[iPadding]), } + bf.tip.onComplete = s.tipOnComplete bf.tip.frames = make([]component, len(s.tipFrames)) for i, t := range s.tipFrames { bf.tip.frames[i] = component{ @@ -236,7 +236,7 @@ func (s *bFiller) Fill(w io.Writer, stat decor.Statistics) error { curWidth := int(internal.PercentageRound(stat.Total, stat.Current, uint(width))) if curWidth != 0 { - if !stat.Completed || s.tipOnComplete { + if !stat.Completed || s.tip.onComplete { tip = s.tip.frames[s.tip.count%uint(len(s.tip.frames))] s.tip.count++ fillCount += tip.width diff --git a/vendor/github.com/vbauerster/mpb/v8/bar_option.go b/vendor/github.com/vbauerster/mpb/v8/bar_option.go index b39628f233..6247a334cc 100644 --- a/vendor/github.com/vbauerster/mpb/v8/bar_option.go +++ b/vendor/github.com/vbauerster/mpb/v8/bar_option.go @@ -24,7 +24,7 @@ func inspect(decorators []decor.Decorator) (dest []decor.Decorator) { func PrependDecorators(decorators ...decor.Decorator) BarOption { decorators = inspect(decorators) return func(s *bState) { - s.sortDecorators(decorators) + s.populateEwmaDecorators(decorators) s.decorators[0] = decorators } } @@ -33,7 +33,7 @@ func PrependDecorators(decorators ...decor.Decorator) BarOption { func AppendDecorators(decorators ...decor.Decorator) BarOption { decorators = inspect(decorators) return func(s *bState) { - s.sortDecorators(decorators) + s.populateEwmaDecorators(decorators) s.decorators[1] = decorators } } diff --git a/vendor/github.com/vbauerster/mpb/v8/decor/eta.go b/vendor/github.com/vbauerster/mpb/v8/decor/eta.go index 38a348a429..bf48d3eef4 100644 --- a/vendor/github.com/vbauerster/mpb/v8/decor/eta.go +++ b/vendor/github.com/vbauerster/mpb/v8/decor/eta.go @@ -44,7 +44,7 @@ func EwmaNormalizedETA(style TimeStyle, age float64, normalizer TimeNormalizer, } else { average = ewma.NewMovingAverage(age) } - return MovingAverageETA(style, NewThreadSafeMovingAverage(average), normalizer, wcc...) + return MovingAverageETA(style, average, normalizer, wcc...) } // MovingAverageETA decorator relies on MovingAverage implementation to calculate its average. @@ -86,7 +86,6 @@ func (d *movingAverageETA) Decor(s Statistics) (string, int) { return d.Format(d.producer(remaining)) } -// EwmaUpdate is called concurrently with (d *movingAverageETA).Decor func (d *movingAverageETA) EwmaUpdate(n int64, dur time.Duration) { if n <= 0 { d.zDur += dur @@ -165,7 +164,10 @@ func MaxTolerateTimeNormalizer(maxTolerate time.Duration) TimeNormalizer { } normalized -= time.Since(lastCall) lastCall = time.Now() - return normalized + if normalized > 0 { + return normalized + } + return remaining }) } @@ -184,7 +186,10 @@ func FixedIntervalTimeNormalizer(updInterval int) TimeNormalizer { count-- normalized -= time.Since(lastCall) lastCall = time.Now() - return normalized + if normalized > 0 { + return normalized + } + return remaining }) } diff --git a/vendor/github.com/vbauerster/mpb/v8/decor/moving_average.go b/vendor/github.com/vbauerster/mpb/v8/decor/moving_average.go index a1be8ada20..165ef1eb56 100644 --- a/vendor/github.com/vbauerster/mpb/v8/decor/moving_average.go +++ b/vendor/github.com/vbauerster/mpb/v8/decor/moving_average.go @@ -70,5 +70,5 @@ func (s *medianWindow) Set(value float64) { // NewMedian is fixed last 3 samples median MovingAverage. func NewMedian() ewma.MovingAverage { - return NewThreadSafeMovingAverage(new(medianWindow)) + return new(medianWindow) } diff --git a/vendor/github.com/vbauerster/mpb/v8/decor/speed.go b/vendor/github.com/vbauerster/mpb/v8/decor/speed.go index 808d6b6903..b643e10fb5 100644 --- a/vendor/github.com/vbauerster/mpb/v8/decor/speed.go +++ b/vendor/github.com/vbauerster/mpb/v8/decor/speed.go @@ -46,7 +46,7 @@ func EwmaSpeed(unit interface{}, format string, age float64, wcc ...WC) Decorato } else { average = ewma.NewMovingAverage(age) } - return MovingAverageSpeed(unit, format, NewThreadSafeMovingAverage(average), wcc...) + return MovingAverageSpeed(unit, format, average, wcc...) } // MovingAverageSpeed decorator relies on MovingAverage implementation @@ -93,7 +93,6 @@ func (d *movingAverageSpeed) Decor(_ Statistics) (string, int) { return d.Format(str) } -// EwmaUpdate is called concurrently with (d *movingAverageSpeed).Decor func (d *movingAverageSpeed) EwmaUpdate(n int64, dur time.Duration) { if n <= 0 { d.zDur += dur diff --git a/vendor/modules.txt b/vendor/modules.txt index 2c46e853f9..2d6417dd7c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1084,7 +1084,7 @@ github.com/ulikunitz/xz/lzma github.com/vbatts/tar-split/archive/tar github.com/vbatts/tar-split/tar/asm github.com/vbatts/tar-split/tar/storage -# github.com/vbauerster/mpb/v8 v8.8.1 +# github.com/vbauerster/mpb/v8 v8.8.3 ## explicit; go 1.17 github.com/vbauerster/mpb/v8 github.com/vbauerster/mpb/v8/cwriter