diff --git a/ipam/allocate.go b/ipam/allocate.go index 79fe45dc..0e4a9e4b 100644 --- a/ipam/allocate.go +++ b/ipam/allocate.go @@ -43,9 +43,14 @@ func (g *allocate) Try(alloc *Allocator) bool { } // out of space - if donor, err := alloc.ring.ChoosePeerToAskForSpace(g.r.Start, g.r.End); err == nil { - alloc.debugln("Decided to ask peer", donor, "for space in range", g.r) - alloc.sendSpaceRequest(donor, g.r) + donors := alloc.ring.ChoosePeersToAskForSpace(g.r.Start, g.r.End) + for _, donor := range donors { + if err := alloc.sendSpaceRequest(donor, g.r); err != nil { + alloc.debugln("Problem asking peer", donor, "for space:", err) + } else { + alloc.debugln("Decided to ask peer", donor, "for space in range", g.r) + break + } } return false diff --git a/ipam/allocator.go b/ipam/allocator.go index 8b609b96..98f36f3d 100644 --- a/ipam/allocator.go +++ b/ipam/allocator.go @@ -575,14 +575,14 @@ func (alloc *Allocator) propose() { alloc.gossip.GossipBroadcast(alloc.Gossip()) } -func (alloc *Allocator) sendSpaceRequest(dest router.PeerName, r address.Range) { +func (alloc *Allocator) sendSpaceRequest(dest router.PeerName, r address.Range) error { buf := new(bytes.Buffer) enc := gob.NewEncoder(buf) if err := enc.Encode(r); err != nil { panic(err) } msg := router.Concat([]byte{msgSpaceRequest}, buf.Bytes()) - alloc.gossip.GossipUnicast(dest, msg) + return alloc.gossip.GossipUnicast(dest, msg) } func (alloc *Allocator) sendRingUpdate(dest router.PeerName) { diff --git a/ipam/ring/ring.go b/ipam/ring/ring.go index fcdb362e..127175e8 100644 --- a/ipam/ring/ring.go +++ b/ipam/ring/ring.go @@ -392,9 +392,20 @@ func (r *Ring) ReportFree(freespace map[address.Address]address.Offset) { } } -// ChoosePeerToAskForSpace chooses a weighted-random peer to ask -// for space in the range [start, end). Assumes start so that bigger weights sort earlier +func (ws weightedPeers) Less(i, j int) bool { return ws[i].weight > ws[j].weight } +func (ws weightedPeers) Len() int { return len(ws) } +func (ws weightedPeers) Swap(i, j int) { ws[i], ws[j] = ws[j], ws[i] } + +// ChoosePeersToAskForSpace returns all peers we can ask for space in +// the range [start, end), in weighted-random order. Assumes start