Commit 47a36442 authored by Steven Allen's avatar Steven Allen

fix: when the target bucket is empty or low, pull from all other buckets

The neighbors may _also_ be empty or low. This can cause peers with a low number
of peers in their routing table to fail to find _any_ peers in their routing table.
parent 193d952d
...@@ -8,3 +8,5 @@ require ( ...@@ -8,3 +8,5 @@ require (
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16
github.com/multiformats/go-multihash v0.0.1 github.com/multiformats/go-multihash v0.0.1
) )
go 1.13
...@@ -243,27 +243,25 @@ func (rt *RoutingTable) NearestPeers(id ID, count int) []peer.ID { ...@@ -243,27 +243,25 @@ func (rt *RoutingTable) NearestPeers(id ID, count int) []peer.ID {
// It's assumed that this also protects the buckets. // It's assumed that this also protects the buckets.
rt.tabLock.RLock() rt.tabLock.RLock()
// Get bucket at cpl index or last bucket // Get bucket index or last bucket
var bucket *Bucket
if cpl >= len(rt.Buckets) { if cpl >= len(rt.Buckets) {
cpl = len(rt.Buckets) - 1 cpl = len(rt.Buckets) - 1
} }
bucket = rt.Buckets[cpl]
pds := peerDistanceSorter{ pds := peerDistanceSorter{
peers: make([]peerDistance, 0, 3*rt.bucketsize), peers: make([]peerDistance, 0, 3*rt.bucketsize),
target: id, target: id,
} }
pds.appendPeersFromList(bucket.list)
if pds.Len() < count { // Add peers from the target bucket and _less_ specific buckets until we
// In the case of an unusual split, one bucket may be short or empty. // have enough peers.
// if this happens, search both surrounding buckets for nearby peers for i := cpl; i < len(rt.Buckets) && pds.Len() < count; i++ {
if cpl > 0 { pds.appendPeersFromList(rt.Buckets[i].list)
pds.appendPeersFromList(rt.Buckets[cpl-1].list) }
}
if cpl < len(rt.Buckets)-1 { // If we're still short, add more specific buckets (i.e., closer to us).
pds.appendPeersFromList(rt.Buckets[cpl+1].list) for i := cpl - 1; i >= 0 && pds.Len() < count; i-- {
} pds.appendPeersFromList(rt.Buckets[i].list)
} }
rt.tabLock.RUnlock() rt.tabLock.RUnlock()
......
...@@ -229,6 +229,26 @@ func TestTableFindMultiple(t *testing.T) { ...@@ -229,6 +229,26 @@ func TestTableFindMultiple(t *testing.T) {
} }
} }
func TestTableFindMultipleBuckets(t *testing.T) {
local := test.RandPeerIDFatal(t)
m := pstore.NewMetrics()
rt := NewRoutingTable(5, ConvertPeerID(local), time.Hour, m)
peers := make([]peer.ID, 100)
for i := 0; i < 100; i++ {
peers[i] = test.RandPeerIDFatal(t)
rt.Update(peers[i])
}
t.Logf("Searching for peer: '%s'", peers[2])
// should be able to find at least 30
// ~31 (logtwo(100) * 5)
found := rt.NearestPeers(ConvertPeerID(peers[2]), 20)
if len(found) != 20 {
t.Fatalf("asked for 15 peers, got %d", len(found))
}
}
// Looks for race conditions in table operations. For a more 'certain' // Looks for race conditions in table operations. For a more 'certain'
// test, increase the loop counter from 1000 to a much higher number // test, increase the loop counter from 1000 to a much higher number
// and set GOMAXPROCS above 1 // and set GOMAXPROCS above 1
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment