Commit 03dc1869 authored by Petar Maymounkov's avatar Petar Maymounkov

Fix bug in routing table health calculation.

parent 64ea8239
......@@ -81,6 +81,14 @@ func AllTablesHealth(tables []*Table) (report []*TableHealthReport) {
return
}
func TableHealthFromSets(node key.Key, nodeContacts []key.Key, knownNodes []key.Key) *TableHealthReport {
knownNodesTrie := trie.New()
for _, k := range knownNodes {
knownNodesTrie.Add(k)
}
return TableHealth(node, nodeContacts, knownNodesTrie)
}
// TableHealth computes the health report for a node,
// given its routing contacts and a list of all known nodes in the network currently.
func TableHealth(node key.Key, nodeContacts []key.Key, knownNodes *trie.Trie) *TableHealthReport {
......@@ -114,6 +122,7 @@ func walkBucketHealth(depth int, node key.Key, nodeTable, knownNodes *trie.Trie)
} else {
dir := node.BitAt(depth)
switch {
//
case knownNodes == nil || knownNodes.IsEmptyLeaf():
r := walkBucketHealth(depth+1, node, nodeTable.Branch[dir], nil)
return append(r,
......@@ -135,12 +144,12 @@ func walkBucketHealth(depth int, node key.Key, nodeTable, knownNodes *trie.Trie)
})
} else {
r := walkBucketHealth(depth+1, node, nodeTable.Branch[dir], nil)
return append(r, bucketReportFromTries(depth, nodeTable.Branch[1-dir], knownNodes))
return append(r, bucketReportFromTries(depth+1, nodeTable.Branch[1-dir], knownNodes))
}
case !knownNodes.IsLeaf():
r := walkBucketHealth(depth+1, node, nodeTable.Branch[dir], knownNodes.Branch[dir])
return append(r,
bucketReportFromTries(depth, nodeTable.Branch[1-dir], knownNodes.Branch[1-dir]))
bucketReportFromTries(depth+1, nodeTable.Branch[1-dir], knownNodes.Branch[1-dir]))
default:
panic("unreachable")
}
......@@ -148,7 +157,7 @@ func walkBucketHealth(depth int, node key.Key, nodeTable, knownNodes *trie.Trie)
}
func bucketReportFromTries(depth int, actualBucket, maxBucket *trie.Trie) *BucketHealthReport {
actualKnown := trie.Intersect(actualBucket, maxBucket)
actualKnown := trie.IntersectAtDepth(depth, actualBucket, maxBucket)
actualKnownSize := actualKnown.Size()
return &BucketHealthReport{
Depth: depth,
......
package kademlia
import (
"math/rand"
"testing"
"github.com/libp2p/go-libp2p-xor/key"
)
func TestTableHealthFromSets(t *testing.T) {
for i := 0; i < 10; i++ {
s := randomTestTableHealthSubsetSamples(10, 100)
report := TableHealthFromSets(s.Node, s.Contacts, s.Known)
for _, b := range report.Bucket {
if b.ActualUnknownContacts != 0 {
t.Errorf("expecting no actual unknown contacts, got %d", b.ActualUnknownContacts)
}
}
}
}
func randomTestTableHealthSubsetSamples(contactSize, knownSize int) *testTableHealthSample {
known := make([]key.Key, knownSize)
for i := range known {
known[i] = randomKey(16)
}
contacts := make([]key.Key, contactSize)
perm := rand.Perm(knownSize)
for i := 0; i < contactSize; i++ {
contacts[i] = known[perm[i]]
}
return &testTableHealthSample{
Node: randomKey(16),
Contacts: contacts,
Known: known,
}
}
func randomKey(size int) key.Key {
k := make([]byte, size)
rand.Read(k)
return key.Key(k)
}
type testTableHealthSample struct {
Node key.Key
Contacts []key.Key
Known []key.Key
}
......@@ -188,13 +188,4 @@ func testIntersectTrieFromJSON(srcJSON string) *testIntersectTrie {
return s
}
var testIntersectJSONTries = []string{
// `
// {
// "LeftTrie": [
// ],
// "RightTrie": [
// ]
// }
// `,
}
var testIntersectJSONTries = []string{}
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