swarm/network: uncomment assertHealth and improve comments

This commit is contained in:
zelig 2019-01-12 05:59:08 +01:00
parent 408fe36832
commit 28347e0780
3 changed files with 23 additions and 20 deletions

View file

@ -168,15 +168,13 @@ func (k *Kademlia) Register(peers ...*BzzAddr) error {
return nil return nil
} }
// SuggestPeer returns a known peer for the lowest proximity bin for the // SuggestPeer returns an unconnected peer address as a peer suggestion for connection
// lowest bincount below depth
// naturally if there is an empty row it returns a peer for that
func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) { func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) {
k.lock.Lock() k.lock.Lock()
defer k.lock.Unlock() defer k.lock.Unlock()
minsize := k.MinBinSize minsize := k.MinBinSize
radius := neighbourhoodRadiusForPot(k.conns, k.NeighbourhoodSize, k.base) radius := neighbourhoodRadiusForPot(k.conns, k.NeighbourhoodSize, k.base)
// if there is a callable neighbour within the current proxBin, connect // finds a callable neighbour within the current neighbourhood radius
// this makes sure nearest neighbour set is fully connected // this makes sure nearest neighbour set is fully connected
var ppo int var ppo int
k.addrs.EachNeighbour(k.base, Pof, func(val pot.Val, po int) bool { k.addrs.EachNeighbour(k.base, Pof, func(val pot.Val, po int) bool {
@ -196,6 +194,7 @@ func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) {
return a, 0, false return a, 0, false
} }
// if there are no callable neighbours, find the undersaturated bins from shallow to deep
var bpo []int var bpo []int
prev := -1 prev := -1
k.conns.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val) bool) bool) bool { k.conns.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val) bool) bool) bool {
@ -210,13 +209,10 @@ func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) {
} }
return size > 0 && po < radius return size > 0 && po < radius
}) })
// all buckets are full, ie., minsize == k.MinBinSize // all buckets are saturated, ie., minsize >= k.MinBinSize, no peer suggested
if len(bpo) == 0 { if len(bpo) == 0 {
return nil, 0, false return nil, 0, false
} }
// as long as we got candidate peers to connect to
// dont ask for new peers (want = false)
// try to select a candidate peer
// find the first callable peer // find the first callable peer
nxt := bpo[0] nxt := bpo[0]
k.addrs.EachBin(k.base, Pof, nxt, func(po, _ int, f func(func(pot.Val) bool) bool) bool { k.addrs.EachBin(k.base, Pof, nxt, func(po, _ int, f func(func(pot.Val) bool) bool) bool {
@ -398,15 +394,18 @@ func (k *Kademlia) eachAddr(base []byte, o int, f func(*BzzAddr, int) bool) {
}) })
} }
// NeighbourhoodDepth returns the depth for the pot, see depthForPot
func (k *Kademlia) NeighbourhoodDepth() (depth int) { func (k *Kademlia) NeighbourhoodDepth() (depth int) {
k.lock.RLock() k.lock.RLock()
defer k.lock.RUnlock() defer k.lock.RUnlock()
return depthForPot(k.conns, k.NeighbourhoodSize, k.base) return depthForPot(k.conns, k.NeighbourhoodSize, k.base)
} }
// neighbourhoodRadiusForPot returns the proximity order that defines the distance of // neighbourhoodRadiusForPot returns the neighbourhood radius of the kademlia
// the nearest neighbour set with cardinality >= MinProxBinSize // neighbourhood radius encloses the nearest neighbour set with cardinality >= neighbourhoodSize
// if there is altogether less than MinProxBinSize peers it returns 0 // i.e., neighbourhood radius is the deepest PO such that all bins not shallower altogether
// contain at least neighbourhoodSize connected peers
// if there is altogether less than neighbourhoodSize peers connected, it returns 0
// caller must hold the lock // caller must hold the lock
func neighbourhoodRadiusForPot(p *pot.Pot, neighbourhoodSize int, pivotAddr []byte) (depth int) { func neighbourhoodRadiusForPot(p *pot.Pot, neighbourhoodSize int, pivotAddr []byte) (depth int) {
if p.Size() <= neighbourhoodSize { if p.Size() <= neighbourhoodSize {
@ -435,15 +434,19 @@ func neighbourhoodRadiusForPot(p *pot.Pot, neighbourhoodSize int, pivotAddr []by
} }
// depthForPot returns the depth for the pot // depthForPot returns the depth for the pot
// depth is the radius of the minimal extension of nearest neighbourhood that
// includes all empty PO bins. I.e., depth is the deepest PO such that
// - it is not deeper than neighbourhood radius
// - all bins shallower than depth are not empty
// caller must hold the lock // caller must hold the lock
func depthForPot(p *pot.Pot, minProxBinSize int, pivotAddr []byte) (depth int) { func depthForPot(p *pot.Pot, neighbourhoodSize int, pivotAddr []byte) (depth int) {
if p.Size() <= minProxBinSize { if p.Size() <= neighbourhoodSize {
return 0 return 0
} }
// determining the depth is a two-step process // determining the depth is a two-step process
// first we find the proximity bin of the shallowest of the MinProxBinSize peers // first we find the proximity bin of the shallowest of the neighbourhoodSize peers
// the numeric value of depth cannot be higher than this // the numeric value of depth cannot be higher than this
maxDepth := neighbourhoodRadiusForPot(p, minProxBinSize, pivotAddr) maxDepth := neighbourhoodRadiusForPot(p, neighbourhoodSize, pivotAddr)
// the second step is to test for empty bins in order from shallowest to deepest // the second step is to test for empty bins in order from shallowest to deepest
// if an empty bin is found, this will be the actual depth // if an empty bin is found, this will be the actual depth
@ -752,7 +755,7 @@ func (k *Kademlia) Healthy(pp *PeerPot) *Health {
k.lock.RLock() k.lock.RLock()
defer k.lock.RUnlock() defer k.lock.RUnlock()
if len(pp.NNSet) < k.NeighbourhoodSize { if len(pp.NNSet) < k.NeighbourhoodSize {
panic("wrong peerpot") log.Warn("peerpot NNSet < NeighbourhoodSize")
} }
gotnn, countgotnn, culpritsgotnn := k.connectedNeighbours(pp.NNSet) gotnn, countgotnn, culpritsgotnn := k.connectedNeighbours(pp.NNSet)
knownn, countknownn, culpritsknownn := k.knowNeighbours(pp.NNSet) knownn, countknownn, culpritsknownn := k.knowNeighbours(pp.NNSet)

View file

@ -170,18 +170,18 @@ func TestHealthStrict(t *testing.T) {
// no peers // no peers
// unhealthy (and lonely) // unhealthy (and lonely)
k := newTestKademlia("11111111") k := newTestKademlia("11111111")
// assertHealth(t, k, false, false) assertHealth(t, k, false, false)
// know one peer but not connected // know one peer but not connected
// unhealthy // unhealthy
Register(k, "11100000") Register(k, "11100000")
log.Trace(k.String()) log.Trace(k.String())
// assertHealth(t, k, false, false) assertHealth(t, k, false, false)
// know one peer and connected // know one peer and connected
// healthy // healthy
On(k, "11100000") On(k, "11100000")
// assertHealth(t, k, true, false) assertHealth(t, k, true, false)
// know two peers, only one connected // know two peers, only one connected
// unhealthy // unhealthy

View file

@ -352,7 +352,7 @@ func discoveryPersistenceSimulation(nodes, conns int, adapter adapters.NodeAdapt
} }
healthy := &network.Health{} healthy := &network.Health{}
addr := id.String() addr := id.String()
ppmap := network.NewPeerPotMap(network.NewKadParams().MinProxBinSize, addrs) ppmap := network.NewPeerPotMap(network.NewKadParams().NeighbourhoodSize, addrs)
if err := client.Call(&healthy, "hive_healthy", ppmap[common.Bytes2Hex(id.Bytes())]); err != nil { if err := client.Call(&healthy, "hive_healthy", ppmap[common.Bytes2Hex(id.Bytes())]); err != nil {
return fmt.Errorf("error getting node health: %s", err) return fmt.Errorf("error getting node health: %s", err)
} }