From eb5c4219d3852d64480e18e57d5e772f9cc343d3 Mon Sep 17 00:00:00 2001 From: nabbar Date: Sun, 6 Aug 2023 14:30:52 +0200 Subject: [PATCH] Package Status: - fix listmandatory: transform into sync.map to prevent race detection --- status/config.go | 30 +++-- status/listmandatory/interface.go | 32 ++++- status/listmandatory/model.go | 195 +++++++++++++++++++----------- 3 files changed, 167 insertions(+), 90 deletions(-) diff --git a/status/config.go b/status/config.go index 87bb0b12..55ce7782 100644 --- a/status/config.go +++ b/status/config.go @@ -42,16 +42,16 @@ const ( keyConfigMandatory = "cfgMandatory" ) -type Config struct { - ReturnCode map[monsts.Status]int - MandatoryComponent stslmd.ListMandatory -} - type Mandatory struct { Mode stsctr.Mode Keys []string } +type Config struct { + ReturnCode map[monsts.Status]int + MandatoryComponent []Mandatory +} + func (o Config) Validate() error { var e = ErrorValidatorError.Error(nil) @@ -75,7 +75,6 @@ func (o Config) Validate() error { func (o *sts) SetConfig(cfg Config) { if len(cfg.ReturnCode) < 1 { - var def = make(map[monsts.Status]int, 0) def[monsts.KO] = http.StatusInternalServerError def[monsts.Warn] = http.StatusMultiStatus @@ -86,11 +85,18 @@ func (o *sts) SetConfig(cfg Config) { o.x.Store(keyConfigReturnCode, cfg.ReturnCode) } - if len(cfg.MandatoryComponent) < 1 { - o.x.Store(keyConfigMandatory, make([]string, 0)) - } else { - o.x.Store(keyConfigMandatory, cfg.MandatoryComponent) + var lst = stslmd.New() + + if len(cfg.MandatoryComponent) > 0 { + for _, i := range cfg.MandatoryComponent { + var m = stsmdt.New() + m.SetMode(i.Mode) + m.KeyAdd(i.Keys...) + lst.Add(m) + } } + + o.x.Store(keyConfigMandatory, lst) } func (o *sts) cfgGetReturnCode(s monsts.Status) int { @@ -116,7 +122,7 @@ func (o *sts) cfgGetMandatory() stslmd.ListMandatory { } func (o *sts) cfgGetMode(key string) stsctr.Mode { - if l := o.cfgGetMandatory(); len(l) < 1 { + if l := o.cfgGetMandatory(); l == nil { return stsctr.Ignore } else { return l.GetMode(key) @@ -124,7 +130,7 @@ func (o *sts) cfgGetMode(key string) stsctr.Mode { } func (o *sts) cfgGetOne(key string) []string { - if l := o.cfgGetMandatory(); len(l) < 1 { + if l := o.cfgGetMandatory(); l == nil { return make([]string, 0) } else { var r []string diff --git a/status/listmandatory/interface.go b/status/listmandatory/interface.go index 38340b06..c97d7a9a 100644 --- a/status/listmandatory/interface.go +++ b/status/listmandatory/interface.go @@ -26,12 +26,34 @@ package listmandatory -import stsmdt "github.com/nabbar/golib/status/mandatory" +import ( + "sync" + "sync/atomic" -type ListMandatory []stsmdt.Mandatory + stsctr "github.com/nabbar/golib/status/control" + stsmdt "github.com/nabbar/golib/status/mandatory" +) + +type ListMandatory interface { + Len() int + Walk(fct func(m stsmdt.Mandatory) bool) + Add(m ...stsmdt.Mandatory) + Del(m stsmdt.Mandatory) + GetMode(key string) stsctr.Mode + SetMode(key string, mod stsctr.Mode) +} func New(m ...stsmdt.Mandatory) ListMandatory { - res := make([]stsmdt.Mandatory, 0) - copy(res, m) - return res + var o = &model{ + l: sync.Map{}, + k: new(atomic.Int32), + } + + o.k.Store(0) + + for _, i := range m { + o.l.Store(o.inc(), i) + } + + return o } diff --git a/status/listmandatory/model.go b/status/listmandatory/model.go index 9bb0719d..1b871c5e 100644 --- a/status/listmandatory/model.go +++ b/status/listmandatory/model.go @@ -27,100 +27,149 @@ package listmandatory import ( + "sort" + "sync" + "sync/atomic" + stsctr "github.com/nabbar/golib/status/control" stsmdt "github.com/nabbar/golib/status/mandatory" + "golang.org/x/exp/slices" ) -func (l *ListMandatory) Walk(fct func(m stsmdt.Mandatory) bool) { - if l == nil { - return - } else if len(*l) < 1 { - return - } - - var ( - k bool - m stsmdt.Mandatory - n = *l - ) - - for i := range n { - m = n[i] - k = fct(m) - n[i] = m - - if !k { - break - } - } - - *l = n +type model struct { + l sync.Map + k *atomic.Int32 } -func (l *ListMandatory) Add(m ...stsmdt.Mandatory) { - if l == nil { - return - } - - var n = *l +func (o *model) inc() int32 { + i := o.k.Load() + i++ + o.k.Store(i) + return i +} - if len(n) < 1 { - n = make([]stsmdt.Mandatory, 0) - } +func (o *model) Len() int { + var l int - *l = append(n, m...) -} + o.l.Range(func(key, value any) bool { + var k bool -func (l *ListMandatory) Del(m stsmdt.Mandatory) { - if l == nil { - return - } + if _, k = key.(int32); !k { + o.l.Delete(key) + return true + } else if _, k = value.(stsmdt.Mandatory); !k { + o.l.Delete(key) + return true + } - var ( - n = *l - r = make([]stsmdt.Mandatory, 0) - ) + l++ + return true + }) - if len(n) < 1 { - *l = make([]stsmdt.Mandatory, 0) - return - } + return l +} - for i := range n { - if n[i] != m { - r = append(r, n[i]) +func (o *model) Walk(fct func(m stsmdt.Mandatory) bool) { + o.l.Range(func(key, value any) bool { + var ( + k bool + v stsmdt.Mandatory + ) + + if _, k = key.(int32); !k { + o.l.Delete(key) + return true + } else if v, k = value.(stsmdt.Mandatory); !k { + o.l.Delete(key) + return true + } else { + k = fct(v) + o.l.Store(k, v) + return k } - } - - *l = r + }) } -func (l ListMandatory) GetMode(key string) stsctr.Mode { - if len(l) < 1 { - return stsctr.Ignore +func (o *model) Add(m ...stsmdt.Mandatory) { + for _, v := range m { + o.l.Store(o.inc(), v) } +} - for i := range l { - if l[i].KeyHas(key) { - return l[i].GetMode() +func (o *model) Del(m stsmdt.Mandatory) { + o.l.Range(func(key, value any) bool { + var ( + k bool + v stsmdt.Mandatory + ) + + if _, k = key.(int32); !k { + o.l.Delete(key) + return true + } else if v, k = value.(stsmdt.Mandatory); !k { + o.l.Delete(key) + return true + } else { + u := v.KeyList() + sort.Strings(u) + + n := m.KeyList() + sort.Strings(n) + + if slices.Compare(u, n) != 0 { + return true + } + + o.l.Delete(key) + return true } - } - - return stsctr.Ignore + }) } -func (l *ListMandatory) SetMode(key string, mod stsctr.Mode) { - if len(*l) < 1 { - return - } +func (o *model) GetMode(key string) stsctr.Mode { + var res = stsctr.Ignore + + o.l.Range(func(ref, value any) bool { + var ( + k bool + v stsmdt.Mandatory + ) + + if _, k = ref.(int32); !k { + o.l.Delete(ref) + return true + } else if v, k = value.(stsmdt.Mandatory); !k { + o.l.Delete(ref) + return true + } else if v.KeyHas(key) { + res = v.GetMode() + return false + } else { + return true + } + }) - var n = *l + return res +} - for i := range n { - if n[i].KeyHas(key) { - n[i].SetMode(mod) - *l = n - return +func (o *model) SetMode(key string, mod stsctr.Mode) { + o.l.Range(func(ref, value any) bool { + var ( + k bool + v stsmdt.Mandatory + ) + + if _, k = ref.(int32); !k { + o.l.Delete(ref) + return true + } else if v, k = value.(stsmdt.Mandatory); !k { + o.l.Delete(ref) + return true + } else if v.KeyHas(key) { + v.SetMode(mod) + return false + } else { + return true } - } + }) }