internal/kobject: pass action kind for range
All checks were successful
Test / Create distribution (push) Successful in 1m5s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 3m47s
Test / Hakurei (push) Successful in 3m52s
Test / Sandbox (race detector) (push) Successful in 5m24s
Test / Hakurei (race detector) (push) Successful in 6m33s
Test / Flake checks (push) Successful in 1m22s
All checks were successful
Test / Create distribution (push) Successful in 1m5s
Test / Sandbox (push) Successful in 2m52s
Test / ShareFS (push) Successful in 3m47s
Test / Hakurei (push) Successful in 3m52s
Test / Sandbox (race detector) (push) Successful in 5m24s
Test / Hakurei (race detector) (push) Successful in 6m33s
Test / Flake checks (push) Successful in 1m22s
Useful for handling most uevents. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -101,7 +101,7 @@ func (o *Object) update(env map[string]string, strip bool) {
|
||||
// A pendingIterator is a callback currently iterating through objects targeted
|
||||
// by ongoing events.
|
||||
type pendingIterator struct {
|
||||
f func(o *Object) bool
|
||||
f func(o *Object, act uevent.KobjectAction) bool
|
||||
done chan<- struct{}
|
||||
}
|
||||
|
||||
@@ -150,12 +150,12 @@ func (s *State) deleteIter(p *pendingIterator) {
|
||||
}
|
||||
|
||||
// dispatchIter broadcasts an [Object] to all alive iterators.
|
||||
func (s *State) dispatchIter(o *Object) {
|
||||
func (s *State) dispatchIter(o *Object, act uevent.KobjectAction) {
|
||||
s.iterMu.Lock()
|
||||
defer s.iterMu.Unlock()
|
||||
|
||||
for _, p := range s.iter {
|
||||
if !p.f(o) {
|
||||
if !p.f(o, act) {
|
||||
s.deleteIter(p)
|
||||
close(p.done)
|
||||
}
|
||||
@@ -165,14 +165,17 @@ func (s *State) dispatchIter(o *Object) {
|
||||
// Range calls f on all current and upcoming [Object] values tracked by s until
|
||||
// f returns false or the context is cancelled. f must not retain o or modify
|
||||
// the value it points to.
|
||||
func (s *State) Range(ctx context.Context, f func(o *Object) bool) {
|
||||
func (s *State) Range(
|
||||
ctx context.Context,
|
||||
f func(o *Object, act uevent.KobjectAction) bool,
|
||||
) {
|
||||
done := make(chan struct{})
|
||||
p := pendingIterator{f, done}
|
||||
|
||||
s.iterMu.Lock()
|
||||
s.ueventMu.RLock()
|
||||
for _, o := range s.uevent {
|
||||
if !f(o) {
|
||||
if !f(o, uevent.KOBJ_ADD) {
|
||||
s.ueventMu.RUnlock()
|
||||
s.iterMu.Unlock()
|
||||
return
|
||||
@@ -296,13 +299,13 @@ func (s *State) processEvent(e *Event) {
|
||||
return
|
||||
}
|
||||
|
||||
switch e.Action {
|
||||
switch act := e.Action; act {
|
||||
case uevent.KOBJ_ADD:
|
||||
if e.Synth == nil {
|
||||
if o, ok := s.uevent[e.DevPath]; ok {
|
||||
s.reportErr(e.NewError(EDuplicateAdd, o))
|
||||
o.merge(e.Env)
|
||||
s.dispatchIter(o)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -312,7 +315,7 @@ func (s *State) processEvent(e *Event) {
|
||||
}
|
||||
o.merge(e.Env)
|
||||
s.uevent[e.DevPath] = o
|
||||
s.dispatchIter(o)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_REMOVE:
|
||||
@@ -338,14 +341,14 @@ func (s *State) processEvent(e *Event) {
|
||||
o = e.makeColdboot()
|
||||
o.merge(e.Env)
|
||||
s.uevent[e.DevPath] = o
|
||||
s.dispatchIter(o)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
}
|
||||
o.update(e.Env, true)
|
||||
if s.handleChange != nil {
|
||||
s.handleChange(o, e.Env)
|
||||
}
|
||||
s.dispatchIter(o)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_MOVE:
|
||||
@@ -368,7 +371,7 @@ func (s *State) processEvent(e *Event) {
|
||||
o.merge(e.Env)
|
||||
s.uevent[e.DevPath] = o
|
||||
o.DevPath = e.DevPath
|
||||
s.dispatchIter(o)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_ONLINE:
|
||||
@@ -384,7 +387,7 @@ func (s *State) processEvent(e *Event) {
|
||||
s.reportErr(e.NewError(EUnexpectedOffline, o))
|
||||
}
|
||||
o.Offline = false
|
||||
s.dispatchIter(o)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_OFFLINE:
|
||||
@@ -400,7 +403,7 @@ func (s *State) processEvent(e *Event) {
|
||||
s.reportErr(e.NewError(EUnexpectedOffline, o))
|
||||
}
|
||||
o.Offline = true
|
||||
s.dispatchIter(o)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_BIND:
|
||||
@@ -416,7 +419,7 @@ func (s *State) processEvent(e *Event) {
|
||||
}
|
||||
o.State = StateBound
|
||||
o.merge(e.Env)
|
||||
s.dispatchIter(o)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_UNBIND:
|
||||
@@ -432,7 +435,7 @@ func (s *State) processEvent(e *Event) {
|
||||
}
|
||||
o.State = StateNew
|
||||
o.Driver = ""
|
||||
s.dispatchIter(o)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
default: // not reached
|
||||
|
||||
@@ -388,7 +388,9 @@ func TestIter(t *testing.T) {
|
||||
"SEQNUM=1",
|
||||
}}
|
||||
synctest.Wait()
|
||||
s.Range(t.Context(), func(o *Object) bool { return false })
|
||||
s.Range(t.Context(), func(*Object, uevent.KobjectAction) bool {
|
||||
return false
|
||||
})
|
||||
|
||||
var got []*Object
|
||||
check := func(want []*Object) {
|
||||
@@ -405,7 +407,7 @@ func TestIter(t *testing.T) {
|
||||
defer cancel()
|
||||
var done bool
|
||||
wg.Go(func() {
|
||||
s.Range(ctx, func(o *Object) bool {
|
||||
s.Range(ctx, func(o *Object, _ uevent.KobjectAction) bool {
|
||||
got = append(got, o.Clone())
|
||||
return !done
|
||||
})
|
||||
@@ -437,7 +439,11 @@ func TestIter(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
wg.Go(func() { s.Range(ctx, func(*Object) bool { return true }) })
|
||||
wg.Go(func() {
|
||||
s.Range(ctx, func(*Object, uevent.KobjectAction) bool {
|
||||
return true
|
||||
})
|
||||
})
|
||||
synctest.Wait()
|
||||
|
||||
iter := reflect.ValueOf(s).Elem().FieldByName("iter")
|
||||
|
||||
Reference in New Issue
Block a user