// ClaimForPeers claims the entire ring for the array of peers passed // in. Only works for empty rings. func (r *Ring) ClaimForPeers(peers []router.PeerName) { common.Assert(r.Empty()) defer r.assertInvariants() defer r.updateExportedVariables() totalSize := r.distance(r.Start, r.End) share := totalSize/address.Offset(len(peers)) + 1 remainder := totalSize % address.Offset(len(peers)) pos := r.Start for i, peer := range peers { if address.Offset(i) == remainder { share-- if share == 0 { break } } if e, found := r.Entries.get(pos); found { e.update(peer, share) } else { r.Entries.insert(entry{Token: pos, Peer: peer, Free: share}) } pos += address.Address(share) } common.Assert(pos == r.End) }
func TestFuzzRing(t *testing.T) { var ( numPeers = 25 iterations = 1000 ) peers := make([]router.PeerName, numPeers) for i := 0; i < numPeers; i++ { peer, _ := router.PeerNameFromString(fmt.Sprintf("%02d:00:00:00:02:00", i)) peers[i] = peer } // Make a valid, random ring makeGoodRandomRing := func() *Ring { addressSpace := end - start numTokens := rand.Intn(int(addressSpace)) tokenMap := make(map[address.Address]bool) for i := 0; i < numTokens; i++ { tokenMap[address.Address(rand.Intn(int(addressSpace)))] = true } var tokens []address.Address for token := range tokenMap { tokens = append(tokens, token) } sort.Sort(addressSlice(tokens)) peer := peers[rand.Intn(len(peers))] ring := New(start, end, peer) for _, token := range tokens { peer = peers[rand.Intn(len(peers))] ring.Entries = append(ring.Entries, &entry{Token: start + token, Peer: peer}) } ring.assertInvariants() return ring } for i := 0; i < iterations; i++ { // make 2 random rings ring1 := makeGoodRandomRing() ring2 := makeGoodRandomRing() // Merge them - this might fail, we don't care // We just want to make sure it doesn't panic ring1.Merge(*ring2) // Check whats left still passes assertions ring1.assertInvariants() ring2.assertInvariants() } // Make an invalid, random ring makeBadRandomRing := func() *Ring { addressSpace := end - start numTokens := rand.Intn(int(addressSpace)) tokens := make([]address.Address, numTokens) for i := 0; i < numTokens; i++ { tokens[i] = address.Address(rand.Intn(int(addressSpace))) } peer := peers[rand.Intn(len(peers))] ring := New(start, end, peer) for _, token := range tokens { peer = peers[rand.Intn(len(peers))] ring.Entries = append(ring.Entries, &entry{Token: start + token, Peer: peer}) } return ring } for i := 0; i < iterations; i++ { // make 2 random rings ring1 := makeGoodRandomRing() ring2 := makeBadRandomRing() // Merge them - this might fail, we don't care // We just want to make sure it doesn't panic ring1.Merge(*ring2) // Check whats left still passes assertions ring1.assertInvariants() } }