From af5531cbf62fbc179f74141feac765ec290c8a45 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 28 May 2015 18:12:30 +0100 Subject: [PATCH 1/2] Fix incorrect calculation of free space when granting a range that spans a token and inserting a new token, the free space on the last token that we are handing over has to change. Add unit test for this too. --- ipam/address/address.go | 7 +++++++ ipam/ring/ring.go | 2 +- ipam/ring/ring_test.go | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ipam/address/address.go b/ipam/address/address.go index b9f47ac3..97e162d0 100644 --- a/ipam/address/address.go +++ b/ipam/address/address.go @@ -52,3 +52,10 @@ func Subtract(a, b Address) Offset { common.Assert(a >= b) return Offset(a - b) } + +func Min(a, b Offset) Offset { + if a > b { + return b + } + return a +} diff --git a/ipam/ring/ring.go b/ipam/ring/ring.go index 7590a3ce..16ae1451 100644 --- a/ipam/ring/ring.go +++ b/ipam/ring/ring.go @@ -167,7 +167,7 @@ func (r *Ring) GrantRangeToHost(start, end address.Address, peer router.PeerName pos := preceedingPos + 1 for ; pos < len(r.Entries) && r.Entries.entry(pos).Token < end; pos++ { entry := r.Entries.entry(pos) - entry.update(peer, entry.Free) + entry.update(peer, address.Min(entry.Free, r.distance(entry.Token, end))) } // There is never an entry with a token of r.End, as the end of diff --git a/ipam/ring/ring_test.go b/ipam/ring/ring_test.go index 1c12c777..f3ec1e0f 100644 --- a/ipam/ring/ring_test.go +++ b/ipam/ring/ring_test.go @@ -158,6 +158,17 @@ func TestGrantSplit(t *testing.T) { wt.AssertEquals(t, ring1.Entries, entries{{Token: start, Peer: peer1name, Free: 10, Version: 1}, {Token: dot10, Peer: peer2name, Free: 235}, {Token: dot245, Peer: peer1name, Free: 10}}) + ring1.assertInvariants() + + // Grant range spanning a live token, and inserting a new token + ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 10, Version: 2}, + {Token: dot10, Peer: peer1name, Free: 118}, {Token: middle, Peer: peer1name, Free: 127}} + ring1.GrantRangeToHost(dot10, dot245, peer2name) + wt.AssertEquals(t, ring1.Entries, entries{{Token: start, Peer: peer1name, Free: 10, Version: 2}, + {Token: dot10, Peer: peer2name, Free: 118, Version: 1}, + {Token: middle, Peer: peer2name, Free: 117, Version: 1}, + {Token: dot245, Peer: peer1name, Free: 10, Version: 0}}) + ring1.assertInvariants() } func TestMergeSimple(t *testing.T) { From 915bf392e9aa772bc59d4ff1c7407b6c5394ff72 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 28 May 2015 16:22:22 +0100 Subject: [PATCH 2/2] Improve error reporting of too much free space --- ipam/ring/ring.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ipam/ring/ring.go b/ipam/ring/ring.go index 16ae1451..1bb891f4 100644 --- a/ipam/ring/ring.go +++ b/ipam/ring/ring.go @@ -40,7 +40,6 @@ var ( ErrInvalidEntry = errors.New("Received invalid state update!") ErrEntryInMyRange = errors.New("Received new entry in my range!") ErrNoFreeSpace = errors.New("No free space found!") - ErrTooMuchFreeSpace = errors.New("Entry reporting too much free space!") ErrInvalidTimeout = errors.New("dt must be greater than 0") ErrNotFound = errors.New("No entries for peer found") ) @@ -76,7 +75,7 @@ func (r *Ring) checkInvariants() error { distance := r.distance(entry.Token, next.Token) if entry.Free > distance { - return ErrTooMuchFreeSpace + return fmt.Errorf("Entry %s-%s reporting too much free space: %d > %d", entry.Token, next.Token, entry.Free, distance) } }