From 40c9adc8d3a9e02c7fc5e6e3a27df2be7c89b21d Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 8 Jun 2015 12:31:41 +0100 Subject: [PATCH] Extract common freelist-walking code --- ipam/space/space.go | 75 ++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/ipam/space/space.go b/ipam/space/space.go index 549424fd..c0ddcb57 100644 --- a/ipam/space/space.go +++ b/ipam/space/space.go @@ -37,26 +37,46 @@ func (s *Space) Clear() { s.ours = s.ours[:0] } -func (s *Space) Allocate(rangeStart, rangeEnd address.Address) (bool, address.Address) { - // Need to walk forward to the range, then check free space, then pick an address - // Walk down the free spaces, looking for one in range +// Walk down the free list calling f() on the in-range portions, until +// f() returns true or we run out of free space. Return true iff f() returned true +func (s *Space) walkFree(rangeStart, rangeEnd address.Address, f func(pos int, start, end address.Address) bool) bool { + if rangeStart >= rangeEnd { // degenerate case + return false + } for i := 0; i < len(s.free); i += 2 { start, end := s.free[i], s.free[i+1] - if end-1 < rangeStart { + if end <= rangeStart { // this chunk comes before the range continue } - if start > rangeEnd { + if start >= rangeEnd { + // all remaining free space is completely after range break } - res := start - if res < rangeStart { - res = rangeStart + // at this point we know end>start && end>rangeStart && rangeEnd>start && rangeEnd>rangeStart + // therefore max(start, rangeStart) < min(end, rangeEnd) + // Restrict this block of free space to be in range + if start < rangeStart { + start = rangeStart + } + if end > rangeEnd { + end = rangeEnd + } + // at this point we know start end { - e = end - } - if s >= e { - continue - } - res += address.Subtract(e, s) - } + s.walkFree(rangeStart, rangeEnd, func(_ int, start, end address.Address) bool { + res += address.Subtract(end, start) + return false + }) return res } @@ -104,20 +115,14 @@ func (s *Space) biggestFreeRange(rangeStart, rangeEnd address.Address) (int, add pos := -1 biggest := address.Offset(0) - for i := 0; i < len(s.free); i += 2 { - start, end := s.free[i], s.free[i+1] - if start < rangeStart { - start = rangeStart - } - if end > rangeEnd { - end = rangeEnd - } + s.walkFree(rangeStart, rangeEnd, func(i int, start, end address.Address) bool { size := address.Subtract(end, start) if size >= biggest { pos = i biggest = size } - } + return false + }) return pos, biggest }