Vendor in latest containers/(common, storage, image)

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2023-02-28 15:46:49 -05:00
parent db53f38711
commit 76056c6701
55 changed files with 538 additions and 304 deletions

View File

@ -44,7 +44,6 @@ type bState struct {
rmOnComplete bool
noPop bool
autoRefresh bool
manualRefresh bool
aDecorators []decor.Decorator
pDecorators []decor.Decorator
averageDecorators []decor.AverageDecorator
@ -53,7 +52,7 @@ type bState struct {
buffers [3]*bytes.Buffer
filler BarFiller
extender extenderFunc
refreshCh chan time.Time
renderReq chan<- time.Time
waitBar *Bar // key for (*pState).queueBars
}
@ -145,9 +144,7 @@ func (b *Bar) Current() int64 {
// operation for example.
func (b *Bar) SetRefill(amount int64) {
select {
case b.operateState <- func(s *bState) {
s.refill = amount
}:
case b.operateState <- func(s *bState) { s.refill = amount }:
case <-b.done:
}
}
@ -250,7 +247,7 @@ func (b *Bar) EwmaSetCurrent(current int64, iterDur time.Duration) {
select {
case b.operateState <- func(s *bState) {
if n := current - s.current; n > 0 {
s.ewmaUpdate(n, iterDur)
s.decoratorEwmaUpdate(n, iterDur)
}
s.current = current
if s.triggerComplete && s.current >= s.total {
@ -309,7 +306,7 @@ func (b *Bar) EwmaIncrInt64(n int64, iterDur time.Duration) {
}
select {
case b.operateState <- func(s *bState) {
s.ewmaUpdate(n, iterDur)
s.decoratorEwmaUpdate(n, iterDur)
s.current += n
if s.triggerComplete && s.current >= s.total {
s.current = s.total
@ -326,9 +323,7 @@ func (b *Bar) EwmaIncrInt64(n int64, iterDur time.Duration) {
// or after progress resume.
func (b *Bar) DecoratorAverageAdjust(start time.Time) {
select {
case b.operateState <- func(s *bState) {
s.decoratorAverageAdjust(start)
}:
case b.operateState <- func(s *bState) { s.decoratorAverageAdjust(start) }:
case <-b.done:
}
}
@ -457,13 +452,13 @@ func (b *Bar) triggerCompletion(s *bState) {
// Technically this call isn't required, but if refresh rate is set to
// one hour for example and bar completes within a few minutes p.Wait()
// will wait for one hour. This call helps to avoid unnecessary waiting.
go b.tryEarlyRefresh(s.refreshCh)
} else if !s.manualRefresh {
go b.tryEarlyRefresh(s.renderReq)
} else {
b.cancel()
}
}
func (b *Bar) tryEarlyRefresh(refreshCh chan<- time.Time) {
func (b *Bar) tryEarlyRefresh(renderReq chan<- time.Time) {
var anyOtherRunning bool
b.container.traverseBars(func(bar *Bar) bool {
anyOtherRunning = b != bar && bar.IsRunning()
@ -472,7 +467,7 @@ func (b *Bar) tryEarlyRefresh(refreshCh chan<- time.Time) {
if !anyOtherRunning {
for {
select {
case refreshCh <- time.Now():
case renderReq <- time.Now():
case <-b.done:
return
}
@ -593,7 +588,7 @@ func (s *bState) wSyncTable() (table syncTable) {
return table
}
func (s bState) ewmaUpdate(n int64, dur time.Duration) {
func (s bState) decoratorEwmaUpdate(n int64, dur time.Duration) {
var wg sync.WaitGroup
for i := 0; i < len(s.ewmaDecorators); i++ {
switch d := s.ewmaDecorators[i]; i {

View File

@ -11,15 +11,14 @@ import (
type BarOption func(*bState)
func inspect(decorators []decor.Decorator) (dest []decor.Decorator) {
type mergeWrapper interface {
MergeUnwrap() []decor.Decorator
}
for _, decorator := range decorators {
if decorator == nil {
continue
}
if mw, ok := decorator.(mergeWrapper); ok {
dest = append(dest, mw.MergeUnwrap()...)
if d, ok := decorator.(interface {
PlaceHolders() []decor.Decorator
}); ok {
dest = append(dest, d.PlaceHolders()...)
}
dest = append(dest, decorator)
}

View File

@ -41,21 +41,7 @@ func WithRefreshRate(d time.Duration) ContainerOption {
// Refresh will occur upon receive value from provided ch.
func WithManualRefresh(ch <-chan interface{}) ContainerOption {
return func(s *pState) {
s.manualRefresh = true
go func(refreshCh chan<- time.Time, done <-chan struct{}) {
for {
select {
case x := <-ch:
if t, ok := x.(time.Time); ok {
refreshCh <- t
} else {
refreshCh <- time.Now()
}
case <-done:
return
}
}
}(s.refreshCh, s.ctx.Done())
s.manualRC = ch
}
}
@ -65,7 +51,7 @@ func WithManualRefresh(ch <-chan interface{}) ContainerOption {
// rendering will start as soon as provided chan is closed.
func WithRenderDelay(ch <-chan struct{}) ContainerOption {
return func(s *pState) {
s.renderDelay = ch
s.delayRC = ch
}
}

View File

@ -1,5 +1,7 @@
package decor
var _ Decorator = (*any)(nil)
// Any decorator displays text, that can be changed during decorator's
// lifetime via provided DecorFunc.
//

View File

@ -137,7 +137,7 @@ type WC struct {
// FormatMsg formats final message according to WC.W and WC.C.
// Should be called by any Decorator implementation.
func (wc *WC) FormatMsg(msg string) string {
func (wc WC) FormatMsg(msg string) string {
pureWidth := runewidth.StringWidth(msg)
viewWidth := runewidth.StringWidth(stripansi.Strip(msg))
max := wc.W
@ -154,9 +154,10 @@ func (wc *WC) FormatMsg(msg string) string {
// Init initializes width related config.
func (wc *WC) Init() WC {
wc.fill = runewidth.FillLeft
if (wc.C & DidentRight) != 0 {
wc.fill = runewidth.FillRight
} else {
wc.fill = runewidth.FillLeft
}
if (wc.C & DSyncWidth) != 0 {
// it's deliberate choice to override wsync on each Init() call,
@ -167,7 +168,7 @@ func (wc *WC) Init() WC {
}
// Sync is implementation of Synchronizer interface.
func (wc *WC) Sync() (chan int, bool) {
func (wc WC) Sync() (chan int, bool) {
if (wc.C&DSyncWidth) != 0 && wc.wsync == nil {
panic(fmt.Sprintf("%T is not initialized", wc))
}

View File

@ -8,6 +8,13 @@ import (
"github.com/VividCortex/ewma"
)
var (
_ Decorator = (*movingAverageETA)(nil)
_ EwmaDecorator = (*movingAverageETA)(nil)
_ Decorator = (*averageETA)(nil)
_ AverageDecorator = (*averageETA)(nil)
)
// TimeNormalizer interface. Implementors could be passed into
// MovingAverageETA, in order to affect i.e. normalize its output.
type TimeNormalizer interface {

View File

@ -7,6 +7,12 @@ import (
"github.com/mattn/go-runewidth"
)
var (
_ Decorator = (*mergeDecorator)(nil)
_ Wrapper = (*mergeDecorator)(nil)
_ Decorator = (*placeHolderDecorator)(nil)
)
// Merge wraps its decorator argument with intention to sync width
// with several decorators of another bar. Visual example:
//
@ -25,7 +31,7 @@ func Merge(decorator Decorator, placeholders ...WC) Decorator {
md := &mergeDecorator{
Decorator: decorator,
wc: decorator.GetConf(),
placeHolders: make([]*placeHolderDecorator, len(placeholders)),
placeHolders: make([]Decorator, len(placeholders)),
}
decorator.SetConf(WC{})
for i, wc := range placeholders {
@ -40,7 +46,7 @@ func Merge(decorator Decorator, placeholders ...WC) Decorator {
type mergeDecorator struct {
Decorator
wc WC
placeHolders []*placeHolderDecorator
placeHolders []Decorator
}
func (d *mergeDecorator) GetConf() WC {
@ -51,12 +57,8 @@ func (d *mergeDecorator) SetConf(conf WC) {
d.wc = conf.Init()
}
func (d *mergeDecorator) MergeUnwrap() []Decorator {
decorators := make([]Decorator, len(d.placeHolders))
for i, ph := range d.placeHolders {
decorators[i] = ph
}
return decorators
func (d *mergeDecorator) PlaceHolders() []Decorator {
return d.placeHolders
}
func (d *mergeDecorator) Sync() (chan int, bool) {
@ -76,21 +78,21 @@ func (d *mergeDecorator) Decor(s Statistics) string {
cellCount++
}
total := runewidth.StringWidth(d.placeHolders[0].FormatMsg(""))
total := runewidth.StringWidth(d.placeHolders[0].GetConf().FormatMsg(""))
pw := (cellCount - total) / len(d.placeHolders)
rem := (cellCount - total) % len(d.placeHolders)
var diff int
for i := 1; i < len(d.placeHolders); i++ {
ph := d.placeHolders[i]
wc := d.placeHolders[i].GetConf()
width := pw - diff
if (ph.WC.C & DextraSpace) != 0 {
if (wc.C & DextraSpace) != 0 {
width--
if width < 0 {
width = 0
}
}
max := runewidth.StringWidth(ph.FormatMsg(strings.Repeat(" ", width)))
max := runewidth.StringWidth(wc.FormatMsg(strings.Repeat(" ", width)))
total += max
diff = max - pw
}

View File

@ -7,6 +7,12 @@ import (
"github.com/VividCortex/ewma"
)
var (
_ ewma.MovingAverage = (*threadSafeMovingAverage)(nil)
_ ewma.MovingAverage = (*medianWindow)(nil)
_ sort.Interface = (*medianWindow)(nil)
)
type threadSafeMovingAverage struct {
ewma.MovingAverage
mu sync.Mutex

View File

@ -1,5 +1,10 @@
package decor
var (
_ Decorator = (*onAbortWrapper)(nil)
_ Wrapper = (*onAbortWrapper)(nil)
)
// OnAbort returns decorator, which wraps provided decorator with sole
// purpose to display provided message on abort event. It has no effect
// if bar.Abort(drop bool) is called with true argument.

View File

@ -1,5 +1,10 @@
package decor
var (
_ Decorator = (*onCompleteWrapper)(nil)
_ Wrapper = (*onCompleteWrapper)(nil)
)
// OnComplete returns decorator, which wraps provided decorator with
// sole purpose to display provided message on complete event.
//

View File

@ -2,27 +2,35 @@ package decor
import (
"fmt"
"io"
"math"
"time"
"github.com/VividCortex/ewma"
)
var (
_ Decorator = (*movingAverageSpeed)(nil)
_ EwmaDecorator = (*movingAverageSpeed)(nil)
_ Decorator = (*averageSpeed)(nil)
_ AverageDecorator = (*averageSpeed)(nil)
)
// FmtAsSpeed adds "/s" to the end of the input formatter. To be
// used with SizeB1000 or SizeB1024 types, for example:
//
// fmt.Printf("%.1f", FmtAsSpeed(SizeB1024(2048)))
func FmtAsSpeed(input fmt.Formatter) fmt.Formatter {
return &speedFormatter{input}
return speedFormatter{input}
}
type speedFormatter struct {
fmt.Formatter
}
func (self *speedFormatter) Format(st fmt.State, verb rune) {
func (self speedFormatter) Format(st fmt.State, verb rune) {
self.Formatter.Format(st, verb)
_, err := st.Write([]byte("/s"))
_, err := io.WriteString(st, "/s")
if err != nil {
panic(err)
}

View File

@ -1,6 +1,9 @@
package mpb
// A priorityQueue implements heap.Interface
import "container/heap"
var _ heap.Interface = (*priorityQueue)(nil)
type priorityQueue []*Bar
func (pq priorityQueue) Len() int { return len(pq) }

View File

@ -36,7 +36,7 @@ type pState struct {
ctx context.Context
hm heapManager
dropS, dropD chan struct{}
refreshCh chan time.Time
renderReq chan time.Time
idCount int
popPriority int
@ -44,9 +44,9 @@ type pState struct {
refreshRate time.Duration
reqWidth int
popCompleted bool
manualRefresh bool
autoRefresh bool
renderDelay <-chan struct{}
delayRC <-chan struct{}
manualRC <-chan interface{}
shutdownNotifier chan<- interface{}
queueBars map[*Bar]*Bar
output io.Writer
@ -64,13 +64,16 @@ func New(options ...ContainerOption) *Progress {
// context. It's not possible to reuse instance after (*Progress).Wait
// method has been called.
func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress {
if ctx == nil {
ctx = context.Background()
}
ctx, cancel := context.WithCancel(ctx)
s := &pState{
ctx: ctx,
hm: make(heapManager),
dropS: make(chan struct{}),
dropD: make(chan struct{}),
refreshCh: make(chan time.Time),
renderReq: make(chan time.Time),
refreshRate: defaultRefreshRate,
popPriority: math.MinInt32,
queueBars: make(map[*Bar]*Bar),
@ -84,26 +87,32 @@ func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress {
}
}
go s.hm.run()
cw := cwriter.New(s.output)
if (cw.IsTerminal() || s.autoRefresh) && !s.manualRefresh {
s.autoRefresh = true
go s.newTicker(s.renderDelay != nil)
} else {
s.autoRefresh = false
}
p := &Progress{
uwg: s.uwg,
operateState: make(chan func(*pState)),
interceptIO: make(chan func(io.Writer)),
done: ctx.Done(),
cancel: cancel,
}
cw := cwriter.New(s.output)
if s.manualRC != nil {
done := make(chan struct{})
p.done = done
s.autoRefresh = false
go s.manualRefreshListener(done)
} else if cw.IsTerminal() || s.autoRefresh {
done := make(chan struct{})
p.done = done
s.autoRefresh = true
go s.autoRefreshListener(done)
} else {
p.done = ctx.Done()
s.autoRefresh = false
}
p.pwg.Add(1)
go p.serve(s, cw)
go s.hm.run()
return p
}
@ -241,7 +250,7 @@ func (p *Progress) serve(s *pState, cw *cwriter.Writer) {
op(s)
case fn := <-p.interceptIO:
fn(cw)
case <-s.refreshCh:
case <-s.renderReq:
e := render()
if e != nil {
p.cancel() // cancel all bars
@ -267,17 +276,34 @@ func (p *Progress) serve(s *pState, cw *cwriter.Writer) {
}
}
func (s *pState) newTicker(delay bool) {
if delay {
<-s.renderDelay
func (s pState) autoRefreshListener(done chan struct{}) {
if s.delayRC != nil {
<-s.delayRC
}
ticker := time.NewTicker(s.refreshRate)
defer ticker.Stop()
for {
select {
case t := <-ticker.C:
s.refreshCh <- t
s.renderReq <- t
case <-s.ctx.Done():
close(done)
return
}
}
}
func (s pState) manualRefreshListener(done chan struct{}) {
for {
select {
case x := <-s.manualRC:
if t, ok := x.(time.Time); ok {
s.renderReq <- t
} else {
s.renderReq <- time.Now()
}
case <-s.ctx.Done():
close(done)
return
}
}
@ -383,16 +409,15 @@ func (s *pState) flush(cw *cwriter.Writer, height int) error {
return cw.Flush(len(rows) - popCount)
}
func (s *pState) makeBarState(total int64, filler BarFiller, options ...BarOption) *bState {
func (s pState) makeBarState(total int64, filler BarFiller, options ...BarOption) *bState {
bs := &bState{
id: s.idCount,
priority: s.idCount,
reqWidth: s.reqWidth,
total: total,
filler: filler,
refreshCh: s.refreshCh,
autoRefresh: s.autoRefresh,
manualRefresh: s.manualRefresh,
id: s.idCount,
priority: s.idCount,
reqWidth: s.reqWidth,
total: total,
filler: filler,
renderReq: s.renderReq,
autoRefresh: s.autoRefresh,
}
if total > 0 {