diff --git a/go.mod b/go.mod index 9aa33579..73bcbee7 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,6 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/viper v1.17.0 github.com/ugorji/go/codec v1.2.11 - github.com/vbauerster/mpb/v5 v5.4.0 github.com/vbauerster/mpb/v8 v8.6.2 github.com/xanzy/go-gitlab v0.93.1 github.com/xhit/go-simple-mail v2.2.2+incompatible diff --git a/logger/interface_test.go b/logger/interface_test.go index 32c255fb..86bb3123 100644 --- a/logger/interface_test.go +++ b/logger/interface_test.go @@ -194,7 +194,7 @@ var _ = Describe("Logger", func() { }(sub) log.SetFields(logfld.New(GetContext).Add("logger", "main")) - sem := libsem.NewSemaphoreWithContext(context.Background(), 0) + sem := libsem.New(context.Background(), 0, false) defer sem.DeferMain() for i := 0; i < 25; i++ { diff --git a/progress/bar.go b/progress/bar.go deleted file mode 100644 index afe19325..00000000 --- a/progress/bar.go +++ /dev/null @@ -1,256 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2020 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -package progress - -import ( - "sync/atomic" - "time" - - liberr "github.com/nabbar/golib/errors" - libsem "github.com/nabbar/golib/semaphore" - libmpb "github.com/vbauerster/mpb/v5" -) - -type bar struct { - i *atomic.Value - s libsem.Sem - t int64 - b *atomic.Value - u bool - w bool - d bool -} - -func newBar(b *libmpb.Bar, s libsem.Sem, total int64, isModeUnic bool) Bar { - mpbBar := new(atomic.Value) - mpbBar.Store(b) - - return &bar{ - u: total > 0, - t: total, - b: mpbBar, - s: s, - w: isModeUnic, - i: new(atomic.Value), - d: false, - } -} - -func (b *bar) storeTime(ts time.Time) { - if b.i == nil { - b.i = new(atomic.Value) - } - - b.i.Store(ts) -} - -func (b *bar) loadTime() time.Time { - if b.i == nil { - b.i = new(atomic.Value) - } - - if i := b.i.Load(); i == nil { - return libsem.EmptyTime() - } else if ts, ok := i.(time.Time); !ok { - return libsem.EmptyTime() - } else { - return ts - } -} - -func (b *bar) storeBar(mpbBar *libmpb.Bar) { - if b.b == nil { - b.b = new(atomic.Value) - } - - b.b.Store(mpbBar) -} - -func (b *bar) loadBar() *libmpb.Bar { - if b.b == nil { - b.b = new(atomic.Value) - } - - if i := b.b.Load(); i == nil { - return nil - } else if mpbBar, ok := i.(*libmpb.Bar); !ok { - return nil - } else { - return mpbBar - } -} - -func (b bar) GetBarMPB() *libmpb.Bar { - return b.loadBar() -} - -func (b bar) Current() int64 { - if mpgBar := b.loadBar(); mpgBar == nil { - return 0 - } else { - return mpgBar.Current() - } -} - -func (b bar) Completed() bool { - if mpgBar := b.loadBar(); mpgBar == nil { - return false - } else { - return mpgBar.Completed() - } -} - -func (b *bar) Increment(n int) { - if n > 0 { - var mpgBar *libmpb.Bar - - if mpgBar = b.loadBar(); mpgBar == nil { - panic(ErrorBarNotInitialized.Error(nil)) - } - - mpgBar.IncrBy(n) - - if b.loadTime() == libsem.EmptyTime() { - b.storeTime(time.Now()) - mpgBar.DecoratorEwmaUpdate(time.Since(b.loadTime())) - } - - b.storeBar(mpgBar) - } -} - -func (b *bar) Increment64(n int64) { - if n > 0 { - var mpgBar *libmpb.Bar - - if mpgBar = b.loadBar(); mpgBar == nil { - panic(ErrorBarNotInitialized.Error(nil)) - } - - mpgBar.IncrInt64(n) - - if b.loadTime() == libsem.EmptyTime() { - b.storeTime(time.Now()) - mpgBar.DecoratorEwmaUpdate(time.Since(b.loadTime())) - } - - b.storeBar(mpgBar) - } -} - -func (b *bar) ResetDefined(current int64) { - var mpgBar *libmpb.Bar - - if mpgBar = b.loadBar(); mpgBar == nil { - return - } else if current >= b.t { - mpgBar.SetTotal(b.t, true) - mpgBar.SetRefill(b.t) - } else { - mpgBar.SetTotal(b.t, false) - mpgBar.SetRefill(current) - } - - b.storeBar(mpgBar) -} - -func (b *bar) Reset(total, current int64) { - b.u = total > 0 - b.t = total - b.ResetDefined(current) -} - -func (b *bar) Done() { - var mpgBar *libmpb.Bar - - if mpgBar = b.loadBar(); mpgBar == nil { - return - } - - mpgBar.SetRefill(b.t) - mpgBar.SetTotal(b.t, true) - b.storeBar(mpgBar) -} - -func (b *bar) NewWorker() liberr.Error { - var mpgBar *libmpb.Bar - - if !b.u { - b.t++ - if mpgBar = b.loadBar(); mpgBar == nil { - return ErrorBarNotInitialized.Error(nil) - } else { - mpgBar.SetTotal(b.t, false) - b.storeBar(mpgBar) - } - } - - if !b.w { - return b.s.NewWorker() - } - - return nil -} - -func (b *bar) NewWorkerTry() bool { - if !b.w { - return b.s.NewWorkerTry() - } - - return false -} - -func (b *bar) DeferWorker() { - b.Increment(1) - b.s.DeferWorker() -} - -func (b *bar) DeferMain() { - var mpgBar *libmpb.Bar - - if mpgBar = b.loadBar(); mpgBar == nil { - return - } else { - mpgBar.Abort(b.d) - b.storeBar(mpgBar) - } - - if !b.w { - b.s.DeferMain() - } -} - -func (b *bar) DropOnDefer(flag bool) { - b.d = flag -} - -func (b *bar) WaitAll() liberr.Error { - if !b.w { - return b.s.WaitAll() - } - - return nil -} diff --git a/progress/error.go b/progress/error.go deleted file mode 100644 index b7571769..00000000 --- a/progress/error.go +++ /dev/null @@ -1,63 +0,0 @@ -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package progress - -import ( - "fmt" - - liberr "github.com/nabbar/golib/errors" -) - -const ( - ErrorParamEmpty liberr.CodeError = iota + liberr.MinPkgNutsDB - ErrorParamMissing - ErrorParamMismatching - ErrorBarNotInitialized -) - -func init() { - if liberr.ExistInMapMessage(ErrorParamEmpty) { - panic(fmt.Errorf("error code collision with package golib/progress")) - } - liberr.RegisterIdFctMessage(ErrorParamEmpty, getMessage) -} - -func getMessage(code liberr.CodeError) (message string) { - switch code { - case ErrorParamEmpty: - return "at least on given parameters is empty" - case ErrorParamMissing: - return "at least on given parameters is missing" - case ErrorParamMismatching: - return "at least on given parameters is mismatching awaiting type" - case ErrorBarNotInitialized: - return "progress bar not initialized" - } - - return liberr.NullMessage -} diff --git a/progress/interface.go b/progress/interface.go deleted file mode 100644 index d0d2bf03..00000000 --- a/progress/interface.go +++ /dev/null @@ -1,102 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2020 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -package progress - -import ( - "context" - - libsem "github.com/nabbar/golib/semaphore" - libmpb "github.com/vbauerster/mpb/v5" -) - -/* - https://github.com/vbauerster/mpb -*/ - -var ( - defaultStyle = "[=>-]<+" - defaultMessageDone = "done" -) - -func SetDefaultStyle(style string) { - defaultStyle = style -} - -func SetDefaultMessageDone(message string) { - defaultMessageDone = message -} - -func GetDefaultStyle() string { - return defaultStyle -} - -func GetDefaultMessageDone() string { - return defaultMessageDone -} - -type Bar interface { - libsem.SemBar - - DropOnDefer(flag bool) - GetBarMPB() *libmpb.Bar -} - -type ProgressBar interface { - libsem.Sem - - GetMPB() *libmpb.Progress - SetMaxThread(maxSimultaneous int) - SetContext(ctx context.Context) - - MainProcessInit() - - NewBar(total int64, options ...libmpb.BarOption) Bar - - NewBarETA(name string, total int64, job string, parent Bar) Bar - NewBarCounter(name string, total int64, job string, parent Bar) Bar - NewBarKBits(name string, total int64, job string, parent Bar) Bar - - NewBarSimpleETA(name string, total int64) Bar - NewBarSimpleCounter(name string, total int64) Bar - NewBarSimpleKBits(name string, total int64) Bar -} - -func NewProgressBar(options ...libmpb.ContainerOption) ProgressBar { - return NewProgressBarWithContext(context.Background(), options...) -} - -func NewProgressBarWithContext(ctx context.Context, options ...libmpb.ContainerOption) ProgressBar { - if ctx == nil { - ctx = context.Background() - } - - return &progressBar{ - mpb: libmpb.New(options...), - ctx: ctx, - sem: nil, - sMaxSimul: libsem.GetMaxSimultaneous(), - } -} diff --git a/progress/progress.go b/progress/progress.go deleted file mode 100644 index cd79311e..00000000 --- a/progress/progress.go +++ /dev/null @@ -1,224 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2020 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -package progress - -import ( - "context" - - "github.com/nabbar/golib/errors" - "github.com/nabbar/golib/semaphore" - "github.com/vbauerster/mpb/v5" - "github.com/vbauerster/mpb/v5/decor" -) - -type progressBar struct { - mpb *mpb.Progress - ctx context.Context - sMaxSimul int - sem semaphore.Sem -} - -func (p *progressBar) GetMPB() *mpb.Progress { - return p.mpb -} - -func (p *progressBar) SetMaxThread(maxSimultaneous int) { - p.sMaxSimul = maxSimultaneous -} - -func (p *progressBar) MainProcessInit() { - p.sem = p.semaphore() -} - -func (p *progressBar) WaitAll() errors.Error { - if p.sem != nil { - return p.sem.WaitAll() - } - return nil -} - -func (p *progressBar) NewWorker() errors.Error { - if p.sem != nil { - return p.sem.NewWorker() - } - return nil -} - -func (p *progressBar) NewWorkerTry() bool { - if p.sem != nil { - return p.sem.NewWorkerTry() - } - return false -} - -func (p *progressBar) DeferWorker() { - if p.sem != nil { - p.sem.DeferWorker() - } -} - -func (p *progressBar) DeferMain() { - if p.sem != nil { - p.sem.DeferMain() - } -} - -func (p *progressBar) semaphore() semaphore.Sem { - return semaphore.NewSemaphoreWithContext(p.ctx, p.sMaxSimul) -} - -func (p *progressBar) NewBar(total int64, options ...mpb.BarOption) Bar { - return newBar( - p.mpb.AddBar(0, options...), - p.semaphore(), - total, - p.sem != nil, - ) -} - -func (p *progressBar) NewBarSimpleETA(name string, total int64) Bar { - return p.NewBarETA(name, total, "", nil) -} - -func (p *progressBar) NewBarSimpleCounter(name string, total int64) Bar { - return p.NewBarCounter(name, total, "", nil) -} - -func (p *progressBar) NewBarSimpleKBits(name string, total int64) Bar { - return p.NewBarKBits(name, total, "", nil) -} - -func (p *progressBar) NewBarETA(name string, total int64, job string, parent Bar) Bar { - if parent != nil && job != "" { - return newBar(p.addBarJob(total, name, job, nil, nil, parent.GetBarMPB()), p.semaphore(), total, p.sem != nil) - } else { - return newBar(p.addBarSimple(total, name, nil, nil), p.semaphore(), total, p.sem != nil) - } -} - -func (p *progressBar) NewBarCounter(name string, total int64, job string, parent Bar) Bar { - d := decor.CountersNoUnit("[%d / %d] ", decor.WCSyncWidth) - if parent != nil && job != "" { - return newBar(p.addBarJob(total, name, job, d, nil, parent.GetBarMPB()), p.semaphore(), total, p.sem != nil) - } else { - return newBar(p.addBarSimple(total, name, d, nil), p.semaphore(), total, p.sem != nil) - } -} - -func (p *progressBar) NewBarKBits(name string, total int64, job string, parent Bar) Bar { - //nolint #gomnd - d := decor.Counters(decor.UnitKiB, "% .2f / % .2f", decor.WC{W: 20, C: decor.DextraSpace}) - a := []decor.Decorator{ - //nolint #gomnd - decor.Percentage(decor.WC{W: 5, C: 0}), - decor.Name(" | "), - //nolint #gomnd - decor.EwmaSpeed(decor.UnitKiB, "% .2f", 60), - } - - if parent != nil && job != "" { - return newBar(p.addBarJob(total, name, job, d, a, parent.GetBarMPB()), p.semaphore(), total, p.sem != nil) - } else { - return newBar(p.addBarSimple(total, name, d, a), p.semaphore(), total, p.sem != nil) - } -} - -func (p *progressBar) addBarSimple(total int64, name string, counter decor.Decorator, pct []decor.Decorator) *mpb.Bar { - pr := make([]decor.Decorator, 0) - // display our name with one space on the right - pr = append(pr, decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight})) - if counter != nil { - // use counter (no ETA) - pr = append(pr, counter) - } - //nolint #gomnd - pr = append(pr, decor.Name(" ", decor.WC{W: 3, C: decor.DidentRight | decor.DextraSpace})) - // replace ETA decorator with "done" message, OnComplete event - pr = append(pr, decor.OnComplete( - // nolint: gomnd - decor.AverageETA(decor.ET_STYLE_GO, decor.WC{W: len(defaultMessageDone) + 1, C: 0}), defaultMessageDone, - )) - - if pct == nil { - pct = make([]decor.Decorator, 0) - //nolint #gomnd - pct = append(pct, decor.Percentage(decor.WC{W: 5, C: 0})) - } - - return p.mpb.AddBar(total, - mpb.BarStyle(defaultStyle), - mpb.BarFillerClearOnComplete(), - mpb.PrependDecorators(pr...), - mpb.AppendDecorators(pct...), - ) -} - -func (p *progressBar) addBarJob(total int64, name, job string, counter decor.Decorator, pct []decor.Decorator, bar *mpb.Bar) *mpb.Bar { - pr := make([]decor.Decorator, 0) - // display our name with one space on the right - pr = append(pr, decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight})) - // display our job task with one space on the right - pr = append(pr, decor.Name(job, decor.WC{W: len(job) + 1, C: decor.DidentRight | decor.DextraSpace})) - if counter != nil { - // use counter (no ETA) - pr = append(pr, counter) - } - //nolint #gomnd - pr = append(pr, decor.Name(" ", decor.WC{W: 3, C: decor.DidentRight | decor.DextraSpace})) - if bar != nil { - pr = append(pr, decor.OnComplete( - // replace ETA decorator with "done" message, OnComplete event - decor.AverageETA(decor.ET_STYLE_GO, decor.WC{W: len(defaultMessageDone) + 1, C: 0}), defaultMessageDone, - )) - } - - if pct == nil { - pct = make([]decor.Decorator, 0) - //nolint #gomnd - pct = append(pct, decor.Percentage(decor.WC{W: 5, C: 0})) - } - - if bar == nil { - return p.mpb.AddBar(total, - mpb.BarStyle(defaultStyle), - mpb.BarFillerClearOnComplete(), - mpb.PrependDecorators(pr...), - mpb.AppendDecorators(pct...), - ) - } else { - return p.mpb.AddBar(total, - mpb.BarStyle(defaultStyle), - mpb.BarQueueAfter(bar), - mpb.BarFillerClearOnComplete(), - mpb.PrependDecorators(pr...), - mpb.AppendDecorators(pct...), - ) - } -} - -func (p *progressBar) SetContext(ctx context.Context) { - p.ctx = ctx -} diff --git a/prometheus/pool.go b/prometheus/pool.go index 324149b9..21304a27 100644 --- a/prometheus/pool.go +++ b/prometheus/pool.go @@ -76,10 +76,10 @@ func (m *prom) Collect(ctx context.Context) { func (m *prom) CollectMetrics(ctx context.Context, name ...string) { var ( ok bool - s libsem.Sem + s libsem.Semaphore ) - s = libsem.NewSemaphoreWithContext(ctx, 0) + s = libsem.New(ctx, 0, false) defer s.DeferMain() if _, ok = ctx.(*ginsdk.Context); ok { @@ -91,7 +91,7 @@ func (m *prom) CollectMetrics(ctx context.Context, name ...string) { _ = s.WaitAll() } -func (m *prom) runCollect(ctx context.Context, sem libsem.Sem) prmpol.FuncWalk { +func (m *prom) runCollect(ctx context.Context, sem libsem.Semaphore) prmpol.FuncWalk { return func(pool prmpol.MetricPool, key string, val libmet.Metric) bool { if e := sem.NewWorker(); e != nil { return false diff --git a/semaphore/bar/bar.go b/semaphore/bar/bar.go new file mode 100644 index 00000000..5ff84b8d --- /dev/null +++ b/semaphore/bar/bar.go @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package bar + +func (o *bar) Inc(n int) { + o.Inc64(int64(n)) +} + +func (o *bar) Dec(n int) { + o.Inc64(int64(n)) +} + +func (o *bar) Inc64(n int64) { + if !o.isMPB() { + return + } + + o.b.IncrInt64(n) + o.b.EwmaSetCurrent(o.b.Current(), o.getDur()) +} + +func (o *bar) Dec64(n int64) { + o.Inc64(n) +} + +func (o *bar) Reset(tot, current int64) { + o.m.Store(tot) + + if !o.isMPB() { + return + } + + o.b.SetTotal(tot, false) + o.b.SetCurrent(current) +} + +func (o *bar) Complete() { + if !o.isMPB() { + return + } + + o.b.SetTotal(o.m.Load(), true) + o.b.EnableTriggerComplete() +} + +func (o *bar) Completed() bool { + if !o.isMPB() { + return true + } + + return o.b.Completed() || o.b.Aborted() +} + +func (o *bar) Current() int64 { + if !o.isMPB() { + return o.m.Load() + } + + return o.b.Current() +} + +func (o *bar) Total() int64 { + return o.m.Load() +} diff --git a/semaphore/bar/context.go b/semaphore/bar/context.go new file mode 100644 index 00000000..b58c4fb3 --- /dev/null +++ b/semaphore/bar/context.go @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package bar + +import "time" + +func (o *bar) Deadline() (deadline time.Time, ok bool) { + return o.x.Deadline() +} + +func (o *bar) Done() <-chan struct{} { + return o.x.Done() +} + +func (o *bar) Err() error { + return o.x.Err() +} + +func (o *bar) Value(key any) any { + return o.x.Value(key) +} diff --git a/semaphore/bar/interface.go b/semaphore/bar/interface.go new file mode 100644 index 00000000..bfc96bb6 --- /dev/null +++ b/semaphore/bar/interface.go @@ -0,0 +1,67 @@ +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package bar + +import ( + "context" + "sync/atomic" + "time" + + semtps "github.com/nabbar/golib/semaphore/types" + sdkmpb "github.com/vbauerster/mpb/v8" + goxsem "golang.org/x/sync/semaphore" +) + +func New(sem semtps.SemPgb, tot int64, drop bool, opts ...sdkmpb.BarOption) semtps.SemBar { + x, c := context.WithCancel(sem) + + if drop { + opts = append(opts, sdkmpb.BarRemoveOnComplete()) + } + + var b *sdkmpb.Bar + if m := sem.GetMPB(); m != nil { + b = m.AddBar(tot, opts...) + } + + ts := new(atomic.Value) + ts.Store(time.Now()) + + mx := new(atomic.Int64) + mx.Store(tot) + + return &bar{ + c: c, + x: x, + s: goxsem.NewWeighted(sem.Wheigted()), + n: sem.Wheigted(), + d: drop, + b: b, + m: mx, + t: ts, + } +} diff --git a/semaphore/bar/model.go b/semaphore/bar/model.go new file mode 100644 index 00000000..15c2ff59 --- /dev/null +++ b/semaphore/bar/model.go @@ -0,0 +1,72 @@ +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package bar + +import ( + "context" + "sync/atomic" + "time" + + "github.com/vbauerster/mpb/v8" + "golang.org/x/sync/semaphore" +) + +type bar struct { + c context.CancelFunc + x context.Context + + s *semaphore.Weighted + n int64 + d bool + + b *mpb.Bar + m *atomic.Int64 + t *atomic.Value +} + +func (o *bar) isMPB() bool { + return o.b != nil +} + +func (o *bar) GetMPB() *mpb.Bar { + return o.b +} + +func (o *bar) getDur() time.Duration { + i := o.t.Load() + o.t.Store(time.Now()) + + if i == nil { + return time.Millisecond + } else if t, k := i.(time.Time); !k { + return time.Millisecond + } else if t.IsZero() { + return time.Millisecond + } else { + return time.Since(t) + } +} diff --git a/semaphore/bar/semaphore.go b/semaphore/bar/semaphore.go new file mode 100644 index 00000000..e0f067e6 --- /dev/null +++ b/semaphore/bar/semaphore.go @@ -0,0 +1,60 @@ +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package bar + +func (o *bar) NewWorker() error { + return o.s.Acquire(o.x, 1) +} + +func (o *bar) NewWorkerTry() bool { + return o.s.TryAcquire(1) +} + +func (o *bar) DeferWorker() { + o.s.Release(1) +} + +func (o *bar) DeferMain() { + if o.isMPB() { + o.Complete() + if !o.Completed() { + o.b.Abort(o.d) + } + } + + if o.c != nil { + o.c() + } +} + +func (o *bar) WaitAll() error { + return o.s.Acquire(o.x, o.n) +} + +func (o *bar) Wheigted() int64 { + return o.n +} diff --git a/semaphore/context.go b/semaphore/context.go index 738c1f0f..65dae3b6 100644 --- a/semaphore/context.go +++ b/semaphore/context.go @@ -1,49 +1,45 @@ /* - * MIT License + * MIT License * - * Copyright (c) 2020 Nicolas JUHEL + * Copyright (c) 2019 Nicolas JUHEL * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. * */ package semaphore -import ( - "context" - "time" -) +import "time" -func NewContext(parent context.Context, timeout time.Duration, deadline time.Time) (ctx context.Context, cancel context.CancelFunc) { - if parent == nil { - parent = context.Background() - } +func (o *sem) Deadline() (deadline time.Time, ok bool) { + return o.Deadline() +} - if timeout > 0 { - return context.WithTimeout(parent, timeout) - } else if deadline.Unix() > 0 { - return context.WithDeadline(parent, deadline) - } +func (o *sem) Done() <-chan struct{} { + return o.x.Done() +} - return context.WithCancel(parent) +func (o *sem) Err() error { + return o.x.Err() } -func EmptyTime() time.Time { - return time.Time{} +func (o *sem) Value(key any) any { + return o.x.Value(key) } diff --git a/semaphore/interface.go b/semaphore/interface.go index d6432749..bd4ba300 100644 --- a/semaphore/interface.go +++ b/semaphore/interface.go @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * + * */ package semaphore @@ -28,59 +29,48 @@ package semaphore import ( "context" "runtime" - "sync/atomic" - liberr "github.com/nabbar/golib/errors" + semtps "github.com/nabbar/golib/semaphore/types" + "github.com/vbauerster/mpb/v8" "golang.org/x/sync/semaphore" ) -type SemBar interface { - Sem - - Current() int64 - Completed() bool - Reset(total, current int64) - ResetDefined(current int64) - Done() - - Increment(n int) - Increment64(n int64) -} - -type FuncContext func() context.Context - -type Sem interface { - NewWorker() liberr.Error - NewWorkerTry() bool - DeferWorker() - DeferMain() - - WaitAll() liberr.Error +type Semaphore interface { + context.Context + semtps.Sem + semtps.Progress } -func GetMaxSimultaneous() int { +func MaxSimultaneous() int { return runtime.GOMAXPROCS(0) } -/* -Deprecated: func without context will be deprecated -*/ -func NewSemaphore(maxSimultaneous int) Sem { - return NewSemaphoreWithContext(context.Background(), maxSimultaneous) +func SetSimultaneous(n int) int64 { + m := MaxSimultaneous() + if n < 1 { + return int64(m) + } else if m < n { + return int64(m) + } else { + return int64(n) + } } -func NewSemaphoreWithContext(ctx context.Context, maxSimultaneous int) Sem { - if maxSimultaneous < 1 { - maxSimultaneous = GetMaxSimultaneous() - } +func New(ctx context.Context, nbrSimultaneous int, progress bool, opt ...mpb.ContainerOption) Semaphore { + nbr := SetSimultaneous(nbrSimultaneous) + ctx, cnl := context.WithCancel(ctx) + + var m *mpb.Progress - x, c := NewContext(ctx, 0, EmptyTime()) + if progress { + m = mpb.New(opt...) + } return &sem{ - d: new(atomic.Value), - i: int64(maxSimultaneous), - s: semaphore.NewWeighted(int64(maxSimultaneous)), - x: x, - c: c, + c: cnl, + x: ctx, + s: semaphore.NewWeighted(nbr), + n: nbr, + m: m, } } diff --git a/semaphore/error.go b/semaphore/model.go similarity index 61% rename from semaphore/error.go rename to semaphore/model.go index d52e3402..15f55587 100644 --- a/semaphore/error.go +++ b/semaphore/model.go @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2020 Nicolas JUHEL + * Copyright (c) 2019 Nicolas JUHEL * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,33 +27,18 @@ package semaphore import ( - "fmt" + "context" - liberr "github.com/nabbar/golib/errors" + "github.com/vbauerster/mpb/v8" + "golang.org/x/sync/semaphore" ) -const ( - ErrorParamEmpty liberr.CodeError = iota + liberr.MinPkgSemaphore - ErrorWorkerNew - ErrorWorkerWaitAll -) - -func init() { - if liberr.ExistInMapMessage(ErrorParamEmpty) { - panic(fmt.Errorf("error code collision with package golib/semaphore")) - } - liberr.RegisterIdFctMessage(ErrorParamEmpty, getMessage) -} +type sem struct { + c context.CancelFunc + x context.Context -func getMessage(code liberr.CodeError) (message string) { - switch code { - case ErrorParamEmpty: - return "given parameters is empty" - case ErrorWorkerNew: - return "error on acquire one new semaphore worker" - case ErrorWorkerWaitAll: - return "error on acquire to wait all pending thread" - } + s *semaphore.Weighted + n int64 - return liberr.NullMessage + m *mpb.Progress } diff --git a/semaphore/progress.go b/semaphore/progress.go new file mode 100644 index 00000000..a712c373 --- /dev/null +++ b/semaphore/progress.go @@ -0,0 +1,118 @@ +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package semaphore + +import ( + sembar "github.com/nabbar/golib/semaphore/bar" + semtps "github.com/nabbar/golib/semaphore/types" + sdkmpb "github.com/vbauerster/mpb/v8" + mpbdec "github.com/vbauerster/mpb/v8/decor" +) + +const done = "Done" +const run = "Running" + +func (o *sem) isMbp() bool { + return o.m != nil +} + +func (o *sem) defOpts(unit interface{}, name, job string, bar semtps.Bar) []sdkmpb.BarOption { + var opt = make([]sdkmpb.BarOption, 0) + + if bar != nil { + if b, k := bar.(semtps.BarMPB); k { + opt = append(opt, sdkmpb.BarQueueAfter(b.GetMPB())) + } + } + + var dec = make([]mpbdec.Decorator, 0) + + if len(name) > 0 { + dec = append(dec, + mpbdec.Name(name, mpbdec.WC{W: len(name) + 1, C: mpbdec.DidentRight}), + ) + } + + if len(job) > 0 { + if len(dec) > 0 { + dec = append(dec, + mpbdec.Name(" | "), + ) + } + dec = append(dec, + mpbdec.Name(job, mpbdec.WC{W: len(job) + 1, C: mpbdec.DidentRight | mpbdec.DextraSpace}), + ) + } + + if unit != nil { + if len(dec) > 0 { + dec = append(dec, + mpbdec.Name(" | "), + ) + } + dec = append(dec, + mpbdec.Counters(unit, "", mpbdec.WCSyncWidth), + ) + } + + opt = append(opt, sdkmpb.PrependDecorators(dec...)) + + dec = append(make([]mpbdec.Decorator, 0), + mpbdec.Percentage(mpbdec.WC{W: 5, C: 0}), + mpbdec.Name(" | "), + mpbdec.AverageETA(mpbdec.ET_STYLE_GO, mpbdec.WCSyncWidth), + ) + + if unit != nil { + dec = append(dec, + mpbdec.Name(" | "), + mpbdec.AverageSpeed(unit, "% .2f", mpbdec.WCSyncWidth), + ) + } + + return append(opt, sdkmpb.AppendDecorators(append(dec, mpbdec.OnComplete(mpbdec.Name(""), " | "+done))...)) +} + +func (o *sem) BarBytes(name, job string, tot int64, drop bool, bar semtps.SemBar) semtps.SemBar { + return o.BarOpts(tot, drop, o.defOpts(mpbdec.SizeB1024(0), name, job, bar)...) +} + +func (o *sem) BarTime(name, job string, tot int64, drop bool, bar semtps.SemBar) semtps.SemBar { + return o.BarOpts(tot, drop, o.defOpts(nil, name, job, bar)...) +} + +func (o *sem) BarNumber(name, job string, tot int64, drop bool, bar semtps.SemBar) semtps.SemBar { + return o.BarOpts(tot, drop, o.defOpts(int64(0), name, job, bar)...) +} + +func (o *sem) BarOpts(tot int64, drop bool, opts ...sdkmpb.BarOption) semtps.SemBar { + return sembar.New(o, tot, drop, opts...) +} + +func (o *sem) GetMPB() *sdkmpb.Progress { + return o.m +} diff --git a/semaphore/semaphore.go b/semaphore/semaphore.go index 56c0c451..052dc5bc 100644 --- a/semaphore/semaphore.go +++ b/semaphore/semaphore.go @@ -21,108 +21,37 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * + * */ package semaphore -import ( - "context" - "sync/atomic" - - liberr "github.com/nabbar/golib/errors" - "golang.org/x/sync/semaphore" -) - -type sem struct { - d *atomic.Value // compatibility with SemBar => isCompleted - i int64 // max process simultaneous - s *semaphore.Weighted - x context.Context - c context.CancelFunc -} - -func (s *sem) getCompleted() bool { - if s.d == nil { - s.d = new(atomic.Value) - } - - if i := s.d.Load(); i == nil { - return false - } else if o, ok := i.(bool); !ok { - return false - } else { - return o - } -} - -func (s *sem) setCompleted(flag bool) { - if s.d == nil { - s.d = new(atomic.Value) - } - - s.d.Store(flag) -} - -func (s *sem) NewWorker() liberr.Error { - e := s.s.Acquire(s.context(), 1) - return ErrorWorkerNew.IfError(e) +func (o *sem) NewWorker() error { + return o.s.Acquire(o.x, 1) } -func (s *sem) NewWorkerTry() bool { - return s.s.TryAcquire(1) +func (o *sem) NewWorkerTry() bool { + return o.s.TryAcquire(1) } -func (s *sem) WaitAll() liberr.Error { - e := s.s.Acquire(s.context(), s.i) - s.setCompleted(true) - return ErrorWorkerWaitAll.IfError(e) +func (o *sem) DeferWorker() { + o.s.Release(1) } -func (s *sem) DeferWorker() { - s.s.Release(1) -} - -func (s *sem) DeferMain() { - s.setCompleted(true) - if s.c != nil { - s.c() +func (o *sem) DeferMain() { + if o.isMbp() { + o.m.Shutdown() } -} -func (s *sem) context() context.Context { - if s.x == nil { - if s.c != nil { - s.c() - } - s.x, s.c = NewContext(context.Background(), 0, EmptyTime()) + if o.c != nil { + o.c() } - return s.x -} - -func (s *sem) Current() int64 { - return -1 -} - -func (s *sem) Completed() bool { - return s.getCompleted() -} - -func (s *sem) Reset(total, current int64) { - return -} - -func (s *sem) ResetDefined(current int64) { - return -} - -func (s *sem) Done() { - return } -func (s *sem) Increment(n int) { - return +func (o *sem) WaitAll() error { + return o.s.Acquire(o.x, o.n) } -func (s *sem) Increment64(n int64) { - return +func (o *sem) Wheigted() int64 { + return o.n } diff --git a/semaphore/types/bar.go b/semaphore/types/bar.go new file mode 100644 index 00000000..f28a8933 --- /dev/null +++ b/semaphore/types/bar.go @@ -0,0 +1,48 @@ +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package types + +import "github.com/vbauerster/mpb/v8" + +type Bar interface { + Inc(n int) + Dec(n int) + + Inc64(n int64) + Dec64(n int64) + + Reset(tot, current int64) + Complete() + + Completed() bool + Current() int64 + Total() int64 +} + +type BarMPB interface { + GetMPB() *mpb.Bar +} diff --git a/semaphore/types/progress.go b/semaphore/types/progress.go new file mode 100644 index 00000000..955fd6c3 --- /dev/null +++ b/semaphore/types/progress.go @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package types + +import ( + sdkmpb "github.com/vbauerster/mpb/v8" +) + +type Progress interface { + BarBytes(name, job string, tot int64, drop bool, bar SemBar) SemBar + BarTime(name, job string, tot int64, drop bool, bar SemBar) SemBar + BarNumber(name, job string, tot int64, drop bool, bar SemBar) SemBar + BarOpts(tot int64, drop bool, opts ...sdkmpb.BarOption) SemBar +} + +type ProgressMPB interface { + GetMPB() *sdkmpb.Progress +} diff --git a/semaphore/types/semaphore.go b/semaphore/types/semaphore.go new file mode 100644 index 00000000..34ca9581 --- /dev/null +++ b/semaphore/types/semaphore.go @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package types + +import "context" + +type SemPgb interface { + context.Context + Sem + ProgressMPB +} + +type SemBar interface { + context.Context + Sem + Bar +} + +type Sem interface { + NewWorker() error + NewWorkerTry() bool + + DeferWorker() + DeferMain() + + WaitAll() error + + Wheigted() int64 +} diff --git a/test/progress-mpb/main/main.go b/test/progress-mpb/main/main.go new file mode 100644 index 00000000..39eb3fa4 --- /dev/null +++ b/test/progress-mpb/main/main.go @@ -0,0 +1,64 @@ +//go:build examples +// +build examples + +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package main + +import ( + "fmt" + "os" + "time" + + tools "github.com/nabbar/golib/test/progress-mpb/tools" +) + +func main() { + pg := tools.MakeMPB(nil) + + b0 := tools.MakeBar(pg, nil, "bar 0") + b1 := tools.MakeBar(pg, b0, "bar 1") + b2 := tools.MakeBar(pg, b1, "bar 2") + b3 := tools.MakeBar(pg, b2, "bar 3") + b4 := tools.MakeBar(pg, b3, "bar 4") + + tot := int64(80) + inc := int64(20) + + fail := func() {} + log := func(msg string) { + _, _ = fmt.Fprintln(os.Stderr, msg) + } + + tools.Run(b0, time.Second, tot, inc, fail, log) + tools.Run(b1, time.Second, tot, inc, fail, log) + tools.Run(b2, time.Second, tot, inc, fail, log) + tools.Run(b3, time.Second, tot, inc, fail, log) + tools.Run(b4, time.Second, tot, inc, fail, log) + + pg.Wait() +} diff --git a/test/progress-mpb/main/main_test.go b/test/progress-mpb/main/main_test.go new file mode 100644 index 00000000..69a99cfa --- /dev/null +++ b/test/progress-mpb/main/main_test.go @@ -0,0 +1,80 @@ +//go:build examples +// +build examples + +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package main_test + +import ( + "io" + "testing" + "time" + + tools "github.com/nabbar/golib/test/progress-mpb/tools" +) + +func TestBar(t *testing.T) { + pg := tools.MakeMPB(io.Discard) + b0 := tools.MakeBar(pg, nil, "bar 0") + b1 := tools.MakeBar(pg, b0, "bar 1") + b2 := tools.MakeBar(pg, b1, "bar 2") + b3 := tools.MakeBar(pg, b2, "bar 3") + b4 := tools.MakeBar(pg, b3, "bar 4") + + tot := int64(80) + inc := int64(20) + + fail := func() { + t.Fail() + } + + log := func(msg string) { + t.Errorf(msg) + } + + t.Run("Bar0", func(t *testing.T) { + tools.Run(b0, 10*time.Millisecond, tot, inc, fail, log) + }) + + t.Run("Bar1", func(t *testing.T) { + tools.Run(b1, 10*time.Millisecond, tot, inc, fail, log) + }) + + t.Run("Bar2", func(t *testing.T) { + tools.Run(b2, 10*time.Millisecond, tot, inc, fail, log) + }) + + t.Run("Bar3", func(t *testing.T) { + tools.Run(b3, 10*time.Millisecond, tot, inc, fail, log) + }) + + t.Run("Bar4", func(t *testing.T) { + tools.Run(b4, 10*time.Millisecond, tot, inc, fail, log) + }) + + pg.Wait() +} diff --git a/test/progress-mpb/tools/tools.go b/test/progress-mpb/tools/tools.go new file mode 100644 index 00000000..95b8fcb0 --- /dev/null +++ b/test/progress-mpb/tools/tools.go @@ -0,0 +1,132 @@ +//go:build examples +// +build examples + +/* + * MIT License + * + * Copyright (c) 2019 Nicolas JUHEL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +package tools + +import ( + "fmt" + "io" + "time" + + "github.com/vbauerster/mpb/v8" + "github.com/vbauerster/mpb/v8/decor" +) + +func MakeMPB(w io.Writer) *mpb.Progress { + if w != nil { + return mpb.New( + mpb.WithWidth(80), + mpb.WithOutput(w), + mpb.WithRefreshRate(10*time.Millisecond), + ) + } else { + return mpb.New( + mpb.WithWidth(80), + mpb.WithRefreshRate(10*time.Millisecond), + ) + } +} + +func MakeBar(p *mpb.Progress, bar *mpb.Bar, name string) *mpb.Bar { + tit := "Complex Bar" + msg := "Done" + + pct := []decor.Decorator{ + decor.Percentage(decor.WC{W: 5, C: 0}), + decor.Name(" | "), + decor.EwmaSpeed(decor.SizeB1024(0), "% .2f", 60), + } + + pr := []decor.Decorator{ + decor.Name(tit, decor.WC{W: len(tit) + 1, C: decor.DidentRight}), + decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight | decor.DextraSpace}), + decor.Counters(decor.SizeB1024(0), "% .2f / % .2f", decor.WC{W: 20, C: decor.DextraSpace}), + decor.Name(" ", decor.WC{W: 3, C: decor.DidentRight | decor.DextraSpace}), + decor.OnComplete(decor.AverageETA(decor.ET_STYLE_GO, decor.WC{W: len(msg) + 1, C: 0}), msg), + } + + if bar == nil { + return p.AddBar(0, + mpb.PrependDecorators(pr...), + mpb.AppendDecorators(pct...), + ) + } else { + return p.AddBar(0, + mpb.BarQueueAfter(bar), + mpb.PrependDecorators(pr...), + mpb.AppendDecorators(pct...), + ) + } +} + +func Run(bar *mpb.Bar, dur time.Duration, tot, inc int64, fct func(), log func(msg string)) { + for _, f := range []func(){ + func() { + bar.SetTotal(tot/2, false) + time.Sleep(dur) + }, + func() { + for i := int64(0); i < (inc * 3); i++ { + bar.IncrInt64(1) + time.Sleep(dur / 10) + } + time.Sleep(dur) + }, + func() { + bar.SetTotal(tot, false) + time.Sleep(dur) + }, + func() { + bar.EnableTriggerComplete() + time.Sleep(dur) + }, + func() { + bar.SetTotal(tot+inc, true) + time.Sleep(dur) + }, + } { + f() + if bar.Completed() { + fct() + } + } + + bar.IncrInt64(inc) + time.Sleep(dur) + + if !bar.Completed() { + fct() + } + + if current := bar.Current(); current != tot { + log(fmt.Sprintf("Expected current: %d, got: %d", tot, current)) + } + + time.Sleep(dur) +} diff --git a/test/test-nutsdb/main.go b/test/test-nutsdb/main.go index 612c3a48..95a5597e 100644 --- a/test/test-nutsdb/main.go +++ b/test/test-nutsdb/main.go @@ -1,4 +1,3 @@ -//+build examples //go:build examples // +build examples @@ -41,15 +40,18 @@ import ( "sync/atomic" "time" + logcfg "github.com/nabbar/golib/logger/config" + loglvl "github.com/nabbar/golib/logger/level" + semtps "github.com/nabbar/golib/semaphore/types" + "github.com/c-bata/go-prompt" "github.com/c-bata/go-prompt/completer" - libclu "github.com/nabbar/golib/cluster" liberr "github.com/nabbar/golib/errors" liblog "github.com/nabbar/golib/logger" libndb "github.com/nabbar/golib/nutsdb" libpwd "github.com/nabbar/golib/password" - libpgb "github.com/nabbar/golib/progress" + libsem "github.com/nabbar/golib/semaphore" libsh "github.com/nabbar/golib/shell" libvrs "github.com/nabbar/golib/version" "github.com/nutsdb/nutsdb" @@ -76,7 +78,9 @@ var ( func init() { ctx, cnl = context.WithCancel(context.Background()) liberr.SetModeReturnError(liberr.ErrorReturnCodeErrorTraceFull) - log.Store(liblog.New(ctx)) + log.Store(liblog.New(func() context.Context { + return ctx + })) initLogger() } @@ -94,7 +98,7 @@ func main() { tStart := time.Now() cluster := Start(ctx) - liblog.SetLevel(liblog.WarnLevel) + getLogger().SetLevel(loglvl.WarnLevel) defer func() { Stop(ctx, cluster) }() @@ -123,17 +127,16 @@ func main() { } func Inject(ctx context.Context, tStart time.Time, cluster []libndb.NutsDB) []string { - lvl := liblog.GetCurrentLevel() - liblog.SetLevel(liblog.WarnLevel) + getLogger().SetLevel(loglvl.WarnLevel) tInit := time.Since(tStart) mInit := fmt.Sprintf("Memory used after Init: \n%s", strings.Join(GetMemUsage(), "\n")) runtime.GC() println(fmt.Sprintf("Init done. \n")) - pgb := libpgb.NewProgressBarWithContext(ctx, mpb.WithWidth(64), mpb.WithRefreshRate(200*time.Millisecond)) - barPut := pgb.NewBarSimpleCounter("PutEntry", int64(NbEntries)) - defer barPut.DeferMain(true) + pgb := libsem.New(ctx, 0, true, mpb.WithWidth(64), mpb.WithRefreshRate(200*time.Millisecond)) + barPut := pgb.BarNumber("PutEntry", "", int64(NbEntries), true, nil) + defer barPut.DeferMain() tStart = time.Now() for i := 0; i < NbEntries; i++ { @@ -141,7 +144,7 @@ func Inject(ctx context.Context, tStart time.Time, cluster []libndb.NutsDB) []st continue } - go func(ctx context.Context, bar libpgb.Bar, clu libndb.NutsDB, num int) { + go func(ctx context.Context, bar semtps.SemBar, clu libndb.NutsDB, num int) { defer bar.DeferWorker() if AllowPut { Put(ctx, clu, fmt.Sprintf("key-%03d", num), fmt.Sprintf("val-%03d|%s|%s|%s", num, libpwd.Generate(50), libpwd.Generate(50), libpwd.Generate(50))) @@ -156,8 +159,8 @@ func Inject(ctx context.Context, tStart time.Time, cluster []libndb.NutsDB) []st mPut := fmt.Sprintf("Memory used after Put entries: \n%s", strings.Join(GetMemUsage(), "\n")) runtime.GC() - barGet := pgb.NewBarSimpleCounter("GetEntry", int64(NbEntries)) - defer barGet.DeferMain(true) + barGet := pgb.BarNumber("GetEntry", "", int64(NbEntries), true, nil) + defer barGet.DeferMain() tStart = time.Now() for i := 0; i < NbEntries; i++ { @@ -170,7 +173,7 @@ func Inject(ctx context.Context, tStart time.Time, cluster []libndb.NutsDB) []st c = 0 } - go func(ctx context.Context, bar libpgb.Bar, clu libndb.NutsDB, num int) { + go func(ctx context.Context, bar semtps.SemBar, clu libndb.NutsDB, num int) { defer bar.DeferWorker() if AllowGet { Get(ctx, clu, fmt.Sprintf("key-%03d", num), fmt.Sprintf("val-%03d", num)) @@ -195,9 +198,8 @@ func Inject(ctx context.Context, tStart time.Time, cluster []libndb.NutsDB) []st mGet, } runtime.GC() - liblog.SetLevel(liblog.InfoLevel) - liblog.InfoLevel.Logf("Results testing: \n%s", strings.Join(res, "\n")) - liblog.SetLevel(lvl) + getLogger().SetLevel(loglvl.InfoLevel) + getLogger().Info("Results testing: \n%s", nil, strings.Join(res, "\n")) return res } @@ -222,10 +224,10 @@ func Get(ctx context.Context, c libndb.NutsDB, key, val string) { //_, _ = c.Client(ctx, 100*time.Microsecond).Get("myBucket", []byte(key)) v, e := c.Client(ctx, 100*time.Microsecond).Get("myBucket", []byte(key)) if e != nil { - liblog.ErrorLevel.Logf("Cmd Get for key '%s', error : %v", key, e) + getLogger().Error("Cmd Get for key '%s', error : %v", nil, key, e) fmt.Printf("Cmd Get for key '%s', error : %v", key, e) } else if !bytes.HasPrefix(v.Value, []byte(val)) { - liblog.ErrorLevel.Logf("Cmd Get for key '%s', awaiting value start with '%s', but find : %s", key, val, string(v.Value)) + getLogger().Error("Cmd Get for key '%s', awaiting value start with '%s', but find : %s", nil, key, val, string(v.Value)) fmt.Printf("Cmd Get for key '%s', awaiting value start with '%s', but find : %s", key, val, string(v.Value)) } } @@ -241,7 +243,7 @@ func Start(ctx context.Context) []libndb.NutsDB { return l }) - liblog.InfoLevel.Logf("Starting node ID #%d...", i+1) + getLogger().Info("Starting node ID #%d...", nil, i+1) if err := clusters[i].Listen(); err != nil { panic(err) } @@ -254,7 +256,7 @@ func Start(ctx context.Context) []libndb.NutsDB { func Stop(ctx context.Context, clusters []libndb.NutsDB) { for i := 0; i < NbInstances; i++ { - liblog.InfoLevel.Logf("Stopping node ID #%d...", i+1) + getLogger().Info("Stopping node ID #%d...", nil, i+1) if err := clusters[i].Shutdown(); err != nil { panic(err) } @@ -275,11 +277,10 @@ func initNutDB(num int) libndb.NutsDB { func configNutDB() libndb.Config { cfg := libndb.Config{ DB: libndb.NutsDBOptions{ - EntryIdxMode: nutsdb.HintKeyAndRAMIdxMode, - RWMode: nutsdb.FileIO, - SegmentSize: 64 * 1024, - SyncEnable: true, - StartFileLoadingMode: nutsdb.MMap, + EntryIdxMode: nutsdb.HintKeyAndRAMIdxMode, + RWMode: nutsdb.FileIO, + SegmentSize: 64 * 1024, + SyncEnable: true, }, Cluster: libclu.Config{ @@ -358,11 +359,11 @@ func configNutDB() libndb.Config { func getLogger() liblog.Logger { if log == nil { - return liblog.New(context.Background()) + return liblog.New(context.Background) } else if i := log.Load(); i == nil { - return liblog.New(context.Background()) + return liblog.New(context.Background) } else if l, ok := i.(liblog.Logger); !ok { - return liblog.New(context.Background()) + return liblog.New(context.Background) } else { return l } @@ -384,15 +385,13 @@ func setLogger(l liblog.Logger) { func initLogger() { l := getLogger() - l.SetLevel(liblog.InfoLevel) - if err := l.SetOptions(&liblog.Options{ - DisableStandard: true, - DisableStack: false, - DisableTimestamp: false, - EnableTrace: false, - TraceFilter: "", - DisableColor: false, - LogFile: []liblog.OptionsFile{ + l.SetLevel(loglvl.InfoLevel) + if err := l.SetOptions(&logcfg.Options{ + InheritDefault: false, + TraceFilter: "", + Stdout: nil, + LogFileExtend: false, + LogFile: []logcfg.OptionsFile{ { LogLevel: []string{ "panic", @@ -412,6 +411,8 @@ func initLogger() { EnableTrace: true, }, }, + LogSyslogExtend: false, + LogSyslog: nil, }); err != nil { panic(err) } diff --git a/test/test-progressbar-complex-mpb/main.go b/test/test-progressbar-complex-mpb/main.go deleted file mode 100644 index 16d05b09..00000000 --- a/test/test-progressbar-complex-mpb/main.go +++ /dev/null @@ -1,136 +0,0 @@ -//go:build examples -// +build examples - -/* - * MIT License - * - * Copyright (c) 2020 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -package main - -import ( - "fmt" - "math/rand" - "sync" - "time" - - "github.com/vbauerster/mpb/v8" - "github.com/vbauerster/mpb/v8/decor" -) - -func main() { - var ( - tot = int64(1000) - inc = int64(1) - nbb = 5 - bar = make([]*mpb.Bar, 0) - wgp = sync.WaitGroup{} - msg = "done" - pct = []decor.Decorator{ - decor.Percentage(decor.WC{W: 5, C: 0}), - decor.Name(" | "), - decor.EwmaSpeed(decor.SizeB1024(0), "% .2f", 60), - } - cnt = decor.Counters(decor.SizeB1024(0), "% .2f / % .2f", decor.WC{W: 20, C: decor.DextraSpace}) - ) - - pb := mpb.New( - mpb.WithWidth(64), - mpb.WithRefreshRate(200*time.Millisecond), - ) - - for i := 0; i < nbb; i++ { - name := "Complex Bar" - job := fmt.Sprintf(" | step %d | ", i) - - if i > 0 { - pr := []decor.Decorator{ - decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}), - decor.Name(job, decor.WC{W: len(job) + 1, C: decor.DidentRight | decor.DextraSpace}), - cnt, - decor.Name(" ", decor.WC{W: 3, C: decor.DidentRight | decor.DextraSpace}), - decor.OnComplete(decor.AverageETA(decor.ET_STYLE_GO, decor.WC{W: len(msg) + 1, C: 0}), msg), - } - - if i%2 != 1 { - bar = append(bar, pb.AddBar(tot, - mpb.BarQueueAfter(bar[i-1]), - mpb.BarFillerClearOnComplete(), - mpb.PrependDecorators(pr...), - mpb.AppendDecorators(pct...), - )) - } else { - bar = append(bar, pb.AddBar(0, - mpb.BarQueueAfter(bar[i-1]), - mpb.BarFillerClearOnComplete(), - mpb.PrependDecorators(pr...), - mpb.AppendDecorators(pct...), - )) - } - } else { - pr := []decor.Decorator{ - decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}), - decor.Name(job, decor.WC{W: len(job) + 1, C: decor.DidentRight | decor.DextraSpace}), - cnt, - decor.Name(" ", decor.WC{W: 3, C: decor.DidentRight | decor.DextraSpace}), - } - bar = append(bar, pb.AddBar(0, - mpb.BarFillerClearOnComplete(), - mpb.PrependDecorators(pr...), - mpb.AppendDecorators(pct...), - )) - } - } - - for i := range bar { - wgp.Add(1) - go func(nb int, done func()) { - defer done() - - rand.Seed(999) - - for { - if nb > 0 && !(bar[nb-1].Aborted() || bar[nb-1].Completed()) { - time.Sleep(time.Second) - } else if bar[nb].Current() == 0 { - bar[nb].SetTotal(tot, false) - bar[nb].SetRefill(0) - } - - if bar[nb].Current() < tot { - time.Sleep(time.Duration(rand.Intn(9)+1) * time.Millisecond) - bar[nb].IncrInt64(inc) - } else { - bar[nb].EnableTriggerComplete() - bar[nb].Abort(false) - return - } - } - }(i, wgp.Done) - } - - wgp.Wait() - time.Sleep(500 * time.Millisecond) - - println("finish complex...") -} diff --git a/test/test-progressbar-complex/main.go b/test/test-progressbar-complex/main.go index 56c4a014..07ddeb1d 100644 --- a/test/test-progressbar-complex/main.go +++ b/test/test-progressbar-complex/main.go @@ -29,72 +29,77 @@ package main import ( + "context" "fmt" "math/rand" "time" - "github.com/nabbar/golib/progress" + semtps "github.com/nabbar/golib/semaphore/types" + libsem "github.com/nabbar/golib/semaphore" - "github.com/vbauerster/mpb/v5" + "github.com/vbauerster/mpb/v8" ) func main() { - tot := int64(1000) - inc := int64(1) + tot := int64(100000) + inc := int64(100) nbb := 5 - bar := make([]progress.Bar, 0) - - println("\n\n\n") - println("Starting complex...") - - pb := progress.NewProgressBar(mpb.WithWidth(64), mpb.WithRefreshRate(200*time.Millisecond)) - pb.MainProcessInit() + bar := make([]semtps.SemBar, 0) + sem := libsem.New(context.Background(), 0, true, mpb.WithWidth(80), mpb.WithRefreshRate(10*time.Millisecond)) defer func() { - pb.DeferMain() + sem.DeferMain() }() + println("\n\n\n") + println("Starting complex...") + for i := 0; i < nbb; i++ { if i > 0 && i%2 == 1 { - bar = append(bar, pb.NewBarKBits("KiB bar", tot, fmt.Sprintf(" | step %d | ", i), bar[i-1])) + bar = append(bar, sem.BarBytes("KiB bar", fmt.Sprintf("step %d", i), tot, false, bar[i-1])) } else if i > 0 && i%2 != 1 { - bar = append(bar, pb.NewBarKBits("KiB bar", 0, fmt.Sprintf(" | step %d | ", i), bar[i-1])) + bar = append(bar, sem.BarNumber("KiB bar", fmt.Sprintf("step %d", i), 0, false, bar[i-1])) } else { - bar = append(bar, pb.NewBarKBits("KiB bar", 0, fmt.Sprintf(" | step %d | ", i), nil)) + bar = append(bar, sem.BarTime("KiB bar", fmt.Sprintf("step %d", i), 0, false, nil)) } } for i := range bar { - if e := pb.NewWorker(); e != nil { + if e := sem.NewWorker(); e != nil { panic(e) } else { - go func(nb int, sem libsem.Sem) { + go func(nb int, sem semtps.Sem) { defer func() { - pb.DeferWorker() + sem.DeferWorker() }() rand.Seed(999) for { - if nb > 0 && !bar[nb-1].Completed() { - time.Sleep(time.Second) - } else if bar[nb].Current() == 0 { + if nb > 0 { + if !bar[nb-1].Completed() { + time.Sleep(time.Second) + continue + } + } + + if bar[nb].Current() == 0 { bar[nb].Reset(tot, 0) } if bar[nb].Current() < tot { - time.Sleep(time.Duration(rand.Intn(9)+1) * time.Millisecond) - bar[nb].Increment64(inc) + time.Sleep(getRandTime()) + bar[nb].Inc64(inc) } else { - bar[nb].Done() + bar[nb].DeferMain() return } } - }(i, pb) + }(i, sem) } } - if e := pb.WaitAll(); e != nil { + if e := sem.WaitAll(); e != nil { panic(e) } @@ -102,3 +107,14 @@ func main() { println("finish complex...") } + +func getRandTime() time.Duration { + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + dur := time.Duration(rng.Intn(9)+1) * time.Millisecond + + if dur > 25*time.Millisecond { + return 10 * time.Millisecond + } else { + return dur + } +} diff --git a/test/test-progressbar/main.go b/test/test-progressbar/main.go index 25777a84..58e98fb4 100644 --- a/test/test-progressbar/main.go +++ b/test/test-progressbar/main.go @@ -29,11 +29,12 @@ package main import ( + "context" "math/rand" "time" - "github.com/nabbar/golib/progress" - "github.com/vbauerster/mpb/v5" + libsem "github.com/nabbar/golib/semaphore" + "github.com/vbauerster/mpb/v8" ) func main() { @@ -42,21 +43,21 @@ func main() { println("\n\n\n") println("Starting simple...") - pb := progress.NewProgressBar(mpb.WithWidth(64), mpb.WithRefreshRate(200*time.Millisecond)) + pb := libsem.New(context.Background(), 0, true, mpb.WithWidth(64), mpb.WithRefreshRate(200*time.Millisecond)) - brE := pb.NewBarSimpleETA("ETA bar", 0) + brE := pb.BarTime("ETA bar", "", 0, false, nil) brE.Reset(tot/2, 0) - brE.Increment64(inc - 1) + brE.Inc64(inc) brE.Reset(tot, 0) - brC := pb.NewBarSimpleCounter("counter bar", 0) + brC := pb.BarNumber("counter bar", "", 0, false, nil) brC.Reset(tot/2, 0) - brC.Increment64(inc - 1) + brC.Inc64(inc) brC.Reset(tot, 0) - brK := pb.NewBarSimpleKBits("KiB bar", 0) + brK := pb.BarBytes("KiB bar", "", 0, false, nil) brK.Reset(tot/2, 0) - brK.Increment64(inc - 1) + brK.Inc64(inc) brK.Reset(tot, 0) defer func() { @@ -81,7 +82,7 @@ func main() { /* #nosec */ time.Sleep(time.Duration(rand.Intn(9)) * time.Millisecond) - brE.Increment64(inc - 1) + brE.Inc64(inc) }() } @@ -98,7 +99,7 @@ func main() { /* #nosec */ time.Sleep(time.Duration(rand.Intn(9)) * time.Millisecond) - brC.Increment64(inc - 1) + brC.Inc64(inc) }() } @@ -115,7 +116,7 @@ func main() { /* #nosec */ time.Sleep(time.Duration(rand.Intn(9)) * time.Millisecond) - brK.Increment64(inc - 1) + brK.Inc64(inc) }() } }