Refactor port allocation logic a little, deflake tests.

This commit is contained in:
Brendan Burns
2016-12-18 21:16:27 -08:00
parent 9ba4a0effc
commit 47b79de76e
4 changed files with 147 additions and 30 deletions

View File

@@ -57,7 +57,7 @@ func newPortAllocator(r net.PortRange) PortAllocator {
if r.Base == 0 {
return &randomAllocator{}
}
return newPortRangeAllocator(r)
return newPortRangeAllocator(r, true)
}
const (
@@ -74,7 +74,7 @@ type rangeAllocator struct {
rand *rand.Rand
}
func newPortRangeAllocator(r net.PortRange) PortAllocator {
func newPortRangeAllocator(r net.PortRange, autoFill bool) PortAllocator {
if r.Base == 0 || r.Size == 0 {
panic("illegal argument: may not specify an empty port range")
}
@@ -83,26 +83,31 @@ func newPortRangeAllocator(r net.PortRange) PortAllocator {
ports: make(chan int, portsBufSize),
rand: rand.New(rand.NewSource(time.Now().UnixNano())),
}
go wait.Until(func() { ra.fillPorts(wait.NeverStop) }, nextFreePortCooldown, wait.NeverStop)
if autoFill {
go wait.Forever(func() { ra.fillPorts() }, nextFreePortCooldown)
}
return ra
}
// fillPorts loops, always searching for the next free port and, if found, fills the ports buffer with it.
// this func blocks until either there are no remaining free ports, or else the stopCh chan is closed.
func (r *rangeAllocator) fillPorts(stopCh <-chan struct{}) {
// this func blocks unless there are no remaining free ports.
func (r *rangeAllocator) fillPorts() {
for {
port := r.nextFreePort()
if port == -1 {
if !r.fillPortsOnce() {
return
}
select {
case <-stopCh:
return
case r.ports <- port:
}
}
}
func (r *rangeAllocator) fillPortsOnce() bool {
port := r.nextFreePort()
if port == -1 {
return false
}
r.ports <- port
return true
}
// nextFreePort finds a free port, first picking a random port. if that port is already in use
// then the port range is scanned sequentially until either a port is found or the scan completes
// unsuccessfully. an unsuccessful scan returns a port of -1.