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..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) } } @@ -167,7 +166,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) {