diff options
author | 2018-05-16 22:38:14 +0300 | |
---|---|---|
committer | 2018-05-16 20:38:13 +0100 | |
commit | cffa1948ab21e36b3eb4397e23acc9cea6830201 (patch) | |
tree | de18a664e076f0220f9bfaf74f5c16552ea248ed /plugin | |
parent | bffb955f6952c197d17f028f30b6bee069b15f2b (diff) | |
download | coredns-cffa1948ab21e36b3eb4397e23acc9cea6830201.tar.gz coredns-cffa1948ab21e36b3eb4397e23acc9cea6830201.tar.zst coredns-cffa1948ab21e36b3eb4397e23acc9cea6830201.zip |
Probe simplification (#1784)
* Probe simplification
- the main reason of rework is that previous implementation hung
when calling Do() after Stop()
* replace atomics with mutex
* access Probe.interval under lock
Diffstat (limited to 'plugin')
-rw-r--r-- | plugin/pkg/up/up.go | 91 |
1 files changed, 42 insertions, 49 deletions
diff --git a/plugin/pkg/up/up.go b/plugin/pkg/up/up.go index 4d0ec21bc..e4752ce4d 100644 --- a/plugin/pkg/up/up.go +++ b/plugin/pkg/up/up.go @@ -10,71 +10,64 @@ import ( // Probe is used to run a single Func until it returns true (indicating a target is healthy). If an Func // is already in progress no new one will be added, i.e. there is always a maximum of 1 checks in flight. type Probe struct { - do chan Func - stop chan bool - - target string - sync.Mutex inprogress int + interval time.Duration } // Func is used to determine if a target is alive. If so this function must return nil. type Func func() error // New returns a pointer to an intialized Probe. -func New() *Probe { - return &Probe{stop: make(chan bool), do: make(chan Func)} -} +func New() *Probe { return &Probe{} } // Do will probe target, if a probe is already in progress this is a noop. -func (p *Probe) Do(f Func) { p.do <- f } - -// Stop stops the probing. -func (p *Probe) Stop() { p.stop <- true } - -// Start will start the probe manager, after which probes can be initialized with Do. -func (p *Probe) Start(interval time.Duration) { go p.start(interval) } - -func (p *Probe) start(interval time.Duration) { - for { - select { - case <-p.stop: - p.Lock() - p.inprogress = stop - p.Unlock() - return - case f := <-p.do: +func (p *Probe) Do(f Func) { + p.Lock() + if p.inprogress != idle { + p.Unlock() + return + } + p.inprogress = active + interval := p.interval + p.Unlock() + // Passed the lock. Now run f for as long it returns false. If a true is returned + // we return from the goroutine and we can accept another Func to run. + go func() { + for { + if err := f(); err == nil { + break + } + time.Sleep(interval) p.Lock() - if p.inprogress == active || p.inprogress == stop { + if p.inprogress == stop { p.Unlock() - continue + return } - p.inprogress = active p.Unlock() + } - // Passed the lock. Now run f for as long it returns false. If a true is returned - // we return from the goroutine and we can accept another Func to run. - go func() { - for { - if err := f(); err == nil { - break - } - time.Sleep(interval) - p.Lock() - if p.inprogress == stop { - p.Unlock() - return - } - p.Unlock() - } + p.Lock() + p.inprogress = idle + p.Unlock() + }() +} - p.Lock() - p.inprogress = idle - p.Unlock() - }() - } - } +// Stop stops the probing. +func (p *Probe) Stop() { + p.Lock() + p.inprogress = stop + p.Unlock() +} + +// Start will initialize the probe manager, after which probes can be initiated with Do. +func (p *Probe) Start(interval time.Duration) { p.SetInterval(interval) } + +// SetInterval sets the probing interval to be used by upcoming probes initiated with Do. +func (p *Probe) SetInterval(interval time.Duration) { + p.Lock() + p.interval = interval + p.Unlock() } const ( |