mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
swarm/network: kademlia suggestPeer cleanup, improved comments
This commit is contained in:
parent
4ceac79069
commit
94cd49d17d
1 changed files with 42 additions and 38 deletions
|
|
@ -173,30 +173,30 @@ func (k *Kademlia) SuggestPeer() (suggestedPeer *BzzAddr, saturationDepth int, c
|
||||||
k.lock.Lock()
|
k.lock.Lock()
|
||||||
defer k.lock.Unlock()
|
defer k.lock.Unlock()
|
||||||
radius := neighbourhoodRadiusForPot(k.conns, k.NeighbourhoodSize, k.base)
|
radius := neighbourhoodRadiusForPot(k.conns, k.NeighbourhoodSize, k.base)
|
||||||
// find the undersaturated bins from lowest cardinality from shallow to deep
|
// first collect undersaturated bins starting from smallest size from shallow to deep
|
||||||
// first map unsaturated bins to cardinalities
|
// saturation is a map: bin size (int) -> deepening list of PO bins with that size ([]int)
|
||||||
spo := make(map[int][]int)
|
saturation := make(map[int][]int)
|
||||||
var prev int
|
var lastPO int // the last non-empty PO bin in the iteration
|
||||||
saturationDepth = -1
|
saturationDepth = -1 // the deepest PO such that all shallower bins have >= k.MinBinSize peers
|
||||||
var pastDepth bool
|
var pastDepth bool // whether po of iteration >= depth
|
||||||
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 {
|
||||||
// process skipped empty bins
|
// process skipped empty bins
|
||||||
for ; prev < po; prev++ {
|
for ; lastPO < po; lastPO++ {
|
||||||
// find the lowest unsaturated bin
|
// find the lowest unsaturated bin
|
||||||
if saturationDepth == -1 {
|
if saturationDepth == -1 {
|
||||||
saturationDepth = prev
|
saturationDepth = lastPO
|
||||||
}
|
}
|
||||||
// if there is an empty bin, depth is surely passed
|
// if there is an empty bin, depth is surely passed
|
||||||
pastDepth = true
|
pastDepth = true
|
||||||
spo[0] = append(spo[0], prev)
|
saturation[0] = append(saturation[0], lastPO)
|
||||||
}
|
}
|
||||||
prev = po + 1
|
lastPO = po + 1
|
||||||
// past radius, depth is surely passed
|
// past radius, depth is surely passed
|
||||||
if po >= radius {
|
if po >= radius {
|
||||||
pastDepth = true
|
pastDepth = true
|
||||||
}
|
}
|
||||||
// beyond depth the bin is treated as unsaturated to achieve full connectivity
|
// beyond depth the bin is treated as unsaturated even if size >= k.MinBinSize
|
||||||
// to all neighbours
|
// in order to achieve full connectivity to all neighbours
|
||||||
if pastDepth && size >= k.MinBinSize {
|
if pastDepth && size >= k.MinBinSize {
|
||||||
size = k.MinBinSize - 1
|
size = k.MinBinSize - 1
|
||||||
}
|
}
|
||||||
|
|
@ -206,7 +206,7 @@ func (k *Kademlia) SuggestPeer() (suggestedPeer *BzzAddr, saturationDepth int, c
|
||||||
if saturationDepth == -1 {
|
if saturationDepth == -1 {
|
||||||
saturationDepth = po
|
saturationDepth = po
|
||||||
}
|
}
|
||||||
spo[size] = append(spo[size], po)
|
saturation[size] = append(saturation[size], po)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
@ -217,53 +217,57 @@ func (k *Kademlia) SuggestPeer() (suggestedPeer *BzzAddr, saturationDepth int, c
|
||||||
nearestAddrAt = po
|
nearestAddrAt = po
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
for ; prev <= nearestAddrAt; prev++ {
|
// including bins as size 0 has the effect that requesting connection
|
||||||
spo[0] = append(spo[0], prev)
|
// is prioritised over non-empty shallower bins
|
||||||
|
for ; lastPO <= nearestAddrAt; lastPO++ {
|
||||||
|
saturation[0] = append(saturation[0], lastPO)
|
||||||
}
|
}
|
||||||
// all PO bins are saturated, ie., minsize >= k.MinBinSize, no peer suggested
|
// all PO bins are saturated, ie., minsize >= k.MinBinSize, no peer suggested
|
||||||
if len(spo) == 0 {
|
if len(saturation) == 0 {
|
||||||
return nil, 0, false
|
return nil, 0, false
|
||||||
}
|
}
|
||||||
// find the first callable peer
|
// find the first callable peer in the address book
|
||||||
// starting from the lowest cardinality
|
// starting from the bins with smallest size proceeding from shallow to deep
|
||||||
// for each bin (up until neighbourhood radius) we find callable candidate peers
|
// for each bin (up until neighbourhood radius) we find callable candidate peers
|
||||||
for i := 0; i < k.MinBinSize && suggestedPeer == nil; i++ {
|
for size := 0; size < k.MinBinSize && suggestedPeer == nil; size++ {
|
||||||
bins, ok := spo[i]
|
bins, ok := saturation[size]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
// no bin with this size
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ci := 0
|
cur := 0
|
||||||
cpo := bins[0]
|
curPO := bins[0]
|
||||||
k.addrs.EachBin(k.base, Pof, cpo, func(po, _ int, f func(func(pot.Val) bool) bool) bool {
|
k.addrs.EachBin(k.base, Pof, curPO, func(po, _ int, f func(func(pot.Val) bool) bool) bool {
|
||||||
cpo = bins[ci]
|
curPO = bins[cur]
|
||||||
// find the next bin with cardinality i
|
// find the next bin that has size size
|
||||||
if cpo == po {
|
if curPO == po {
|
||||||
ci++
|
cur++
|
||||||
} else {
|
} else {
|
||||||
// skip bins that have no addresses
|
// skip bins that have no addresses
|
||||||
for ; ci < len(bins) && cpo < po; ci++ {
|
for ; cur < len(bins) && curPO < po; cur++ {
|
||||||
cpo = bins[ci]
|
curPO = bins[cur]
|
||||||
}
|
}
|
||||||
if po < cpo {
|
if po < curPO {
|
||||||
ci--
|
cur--
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// stop if there are no addresses
|
// stop if there are no addresses
|
||||||
if cpo < po {
|
if curPO < po {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// curPO found
|
||||||
// find a callable peer out of the addresses in the unsaturated bin
|
// find a callable peer out of the addresses in the unsaturated bin
|
||||||
// stop if found
|
// stop if found
|
||||||
f(func(val pot.Val) bool {
|
f(func(val pot.Val) bool {
|
||||||
e := val.(*entry)
|
e := val.(*entry)
|
||||||
c := k.callable(e)
|
if k.callable(e) {
|
||||||
if c {
|
|
||||||
suggestedPeer = e.BzzAddr
|
suggestedPeer = e.BzzAddr
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return !c
|
return true
|
||||||
})
|
})
|
||||||
return ci < len(bins) && suggestedPeer == nil
|
return cur < len(bins) && suggestedPeer == nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -434,7 +438,7 @@ func (k *Kademlia) NeighbourhoodDepth() (depth int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// neighbourhoodRadiusForPot returns the neighbourhood radius of the kademlia
|
// neighbourhoodRadiusForPot returns the neighbourhood radius of the kademlia
|
||||||
// neighbourhood radius encloses the nearest neighbour set with cardinality >= neighbourhoodSize
|
// neighbourhood radius encloses the nearest neighbour set with size >= neighbourhoodSize
|
||||||
// i.e., neighbourhood radius is the deepest PO such that all bins not shallower altogether
|
// i.e., neighbourhood radius is the deepest PO such that all bins not shallower altogether
|
||||||
// contain at least neighbourhoodSize connected peers
|
// contain at least neighbourhoodSize connected peers
|
||||||
// if there is altogether less than neighbourhoodSize peers connected, it returns 0
|
// if there is altogether less than neighbourhoodSize peers connected, it returns 0
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue