Commit 4aeeecfd authored by gluk256's avatar gluk256 Committed by Anton Evangelatov

swarm/pot: each() functions refactored (#18452)

parent 1636d957
...@@ -198,7 +198,7 @@ func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) { ...@@ -198,7 +198,7 @@ func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) {
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, i int) bool) bool) bool { k.conns.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val) bool) bool) bool {
prev++ prev++
for ; prev < po; prev++ { for ; prev < po; prev++ {
bpo = append(bpo, prev) bpo = append(bpo, prev)
...@@ -219,12 +219,12 @@ func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) { ...@@ -219,12 +219,12 @@ func (k *Kademlia) SuggestPeer() (a *BzzAddr, o int, want bool) {
// try to select a candidate peer // 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, int) bool) bool) bool { k.addrs.EachBin(k.base, Pof, nxt, func(po, _ int, f func(func(pot.Val) bool) bool) bool {
// for each bin (up until depth) we find callable candidate peers // for each bin (up until depth) we find callable candidate peers
if po >= depth { if po >= depth {
return false return false
} }
return f(func(val pot.Val, _ int) bool { return f(func(val pot.Val) bool {
e := val.(*entry) e := val.(*entry)
c := k.callable(e) c := k.callable(e)
if c { if c {
...@@ -442,7 +442,7 @@ func depthForPot(p *pot.Pot, neighbourhoodSize int, pivotAddr []byte) (depth int ...@@ -442,7 +442,7 @@ func depthForPot(p *pot.Pot, neighbourhoodSize int, pivotAddr []byte) (depth int
// 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
// we stop iterating if we hit the maxDepth determined in the first step // we stop iterating if we hit the maxDepth determined in the first step
p.EachBin(pivotAddr, Pof, 0, func(po int, _ int, f func(func(pot.Val, int) bool) bool) bool { p.EachBin(pivotAddr, Pof, 0, func(po int, _ int, f func(func(pot.Val) bool) bool) bool {
if po == depth { if po == depth {
if maxDepth == depth { if maxDepth == depth {
return false return false
...@@ -514,14 +514,14 @@ func (k *Kademlia) string() string { ...@@ -514,14 +514,14 @@ func (k *Kademlia) string() string {
depth := depthForPot(k.conns, k.NeighbourhoodSize, k.base) depth := depthForPot(k.conns, k.NeighbourhoodSize, k.base)
rest := k.conns.Size() rest := k.conns.Size()
k.conns.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool { k.conns.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val) bool) bool) bool {
var rowlen int var rowlen int
if po >= k.MaxProxDisplay { if po >= k.MaxProxDisplay {
po = k.MaxProxDisplay - 1 po = k.MaxProxDisplay - 1
} }
row := []string{fmt.Sprintf("%2d", size)} row := []string{fmt.Sprintf("%2d", size)}
rest -= size rest -= size
f(func(val pot.Val, vpo int) bool { f(func(val pot.Val) bool {
e := val.(*Peer) e := val.(*Peer)
row = append(row, fmt.Sprintf("%x", e.Address()[:2])) row = append(row, fmt.Sprintf("%x", e.Address()[:2]))
rowlen++ rowlen++
...@@ -533,7 +533,7 @@ func (k *Kademlia) string() string { ...@@ -533,7 +533,7 @@ func (k *Kademlia) string() string {
return true return true
}) })
k.addrs.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool { k.addrs.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val) bool) bool) bool {
var rowlen int var rowlen int
if po >= k.MaxProxDisplay { if po >= k.MaxProxDisplay {
po = k.MaxProxDisplay - 1 po = k.MaxProxDisplay - 1
...@@ -543,7 +543,7 @@ func (k *Kademlia) string() string { ...@@ -543,7 +543,7 @@ func (k *Kademlia) string() string {
} }
row := []string{fmt.Sprintf("%2d", size)} row := []string{fmt.Sprintf("%2d", size)}
// we are displaying live peers too // we are displaying live peers too
f(func(val pot.Val, vpo int) bool { f(func(val pot.Val) bool {
e := val.(*entry) e := val.(*entry)
row = append(row, Label(e)) row = append(row, Label(e))
rowlen++ rowlen++
...@@ -634,7 +634,7 @@ func NewPeerPotMap(neighbourhoodSize int, addrs [][]byte) map[string]*PeerPot { ...@@ -634,7 +634,7 @@ func NewPeerPotMap(neighbourhoodSize int, addrs [][]byte) map[string]*PeerPot {
// TODO this function will stop at the first bin with less than MinBinSize peers, even if there are empty bins between that bin and the depth. This may not be correct behavior // TODO this function will stop at the first bin with less than MinBinSize peers, even if there are empty bins between that bin and the depth. This may not be correct behavior
func (k *Kademlia) saturation() int { func (k *Kademlia) saturation() int {
prev := -1 prev := -1
k.addrs.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val, i int) bool) bool) bool { k.addrs.EachBin(k.base, Pof, 0, func(po, size int, f func(func(val pot.Val) bool) bool) bool {
prev++ prev++
return prev == po && size >= k.MinBinSize return prev == po && size >= k.MinBinSize
}) })
......
...@@ -447,60 +447,50 @@ func union(t0, t1 *Pot, pof Pof) (*Pot, int) { ...@@ -447,60 +447,50 @@ func union(t0, t1 *Pot, pof Pof) (*Pot, int) {
return n, common return n, common
} }
// Each called with (f) is a synchronous iterator over the bins of a node // Each is a synchronous iterator over the elements of pot with function f.
// respecting an ordering func (t *Pot) Each(f func(Val) bool) bool {
// proximity > pinnedness
func (t *Pot) Each(f func(Val, int) bool) bool {
return t.each(f) return t.each(f)
} }
func (t *Pot) each(f func(Val, int) bool) bool { // each is a synchronous iterator over the elements of pot with function f.
var next bool // the iteration ends if the function return false or there are no more elements.
func (t *Pot) each(f func(Val) bool) bool {
if t == nil || t.size == 0 {
return false
}
for _, n := range t.bins { for _, n := range t.bins {
if n == nil { if !n.each(f) {
return true
}
next = n.each(f)
if !next {
return false return false
} }
} }
if t.size == 0 { return f(t.pin)
return false
}
return f(t.pin, t.po)
} }
// eachFrom called with (f, start) is a synchronous iterator over the elements of a Pot // eachFrom is a synchronous iterator over the elements of pot with function f,
// within the inclusive range starting from proximity order start // starting from certain proximity order po, which is passed as a second parameter.
// the function argument is passed the value and the proximity order wrt the root pin // the iteration ends if the function return false or there are no more elements.
// it does NOT include the pinned item of the root func (t *Pot) eachFrom(f func(Val) bool, po int) bool {
// respecting an ordering if t == nil || t.size == 0 {
// proximity > pinnedness return false
// the iteration ends if the function return false or there are no more elements }
// end of a po range can be implemented since po is passed to the function _, beg := t.getPos(po)
func (t *Pot) eachFrom(f func(Val, int) bool, po int) bool { for i := beg; i < len(t.bins); i++ {
var next bool if !t.bins[i].each(f) {
_, lim := t.getPos(po)
for i := lim; i < len(t.bins); i++ {
n := t.bins[i]
next = n.each(f)
if !next {
return false return false
} }
} }
return f(t.pin, t.po) return f(t.pin)
} }
// EachBin iterates over bins of the pivot node and offers iterators to the caller on each // EachBin iterates over bins of the pivot node and offers iterators to the caller on each
// subtree passing the proximity order and the size // subtree passing the proximity order and the size
// the iteration continues until the function's return value is false // the iteration continues until the function's return value is false
// or there are no more subtries // or there are no more subtries
func (t *Pot) EachBin(val Val, pof Pof, po int, f func(int, int, func(func(val Val, i int) bool) bool) bool) { func (t *Pot) EachBin(val Val, pof Pof, po int, f func(int, int, func(func(val Val) bool) bool) bool) {
t.eachBin(val, pof, po, f) t.eachBin(val, pof, po, f)
} }
func (t *Pot) eachBin(val Val, pof Pof, po int, f func(int, int, func(func(val Val, i int) bool) bool) bool) { func (t *Pot) eachBin(val Val, pof Pof, po int, f func(int, int, func(func(val Val) bool) bool) bool) {
if t == nil || t.size == 0 { if t == nil || t.size == 0 {
return return
} }
...@@ -520,8 +510,8 @@ func (t *Pot) eachBin(val Val, pof Pof, po int, f func(int, int, func(func(val V ...@@ -520,8 +510,8 @@ func (t *Pot) eachBin(val Val, pof Pof, po int, f func(int, int, func(func(val V
} }
if lim == len(t.bins) { if lim == len(t.bins) {
if spr >= po { if spr >= po {
f(spr, 1, func(g func(Val, int) bool) bool { f(spr, 1, func(g func(Val) bool) bool {
return g(t.pin, spr) return g(t.pin)
}) })
} }
return return
...@@ -535,9 +525,9 @@ func (t *Pot) eachBin(val Val, pof Pof, po int, f func(int, int, func(func(val V ...@@ -535,9 +525,9 @@ func (t *Pot) eachBin(val Val, pof Pof, po int, f func(int, int, func(func(val V
size += n.size size += n.size
} }
if spr >= po { if spr >= po {
if !f(spr, t.size-size, func(g func(Val, int) bool) bool { if !f(spr, t.size-size, func(g func(Val) bool) bool {
return t.eachFrom(func(v Val, j int) bool { return t.eachFrom(func(v Val) bool {
return g(v, spr) return g(v)
}, spo) }, spo)
}) { }) {
return return
...@@ -585,7 +575,7 @@ func (t *Pot) eachNeighbour(val Val, pof Pof, f func(Val, int) bool) bool { ...@@ -585,7 +575,7 @@ func (t *Pot) eachNeighbour(val Val, pof Pof, f func(Val, int) bool) bool {
} }
for i := l - 1; i > ir; i-- { for i := l - 1; i > ir; i-- {
next = t.bins[i].each(func(v Val, _ int) bool { next = t.bins[i].each(func(v Val) bool {
return f(v, po) return f(v, po)
}) })
if !next { if !next {
...@@ -595,7 +585,7 @@ func (t *Pot) eachNeighbour(val Val, pof Pof, f func(Val, int) bool) bool { ...@@ -595,7 +585,7 @@ func (t *Pot) eachNeighbour(val Val, pof Pof, f func(Val, int) bool) bool {
for i := il - 1; i >= 0; i-- { for i := il - 1; i >= 0; i-- {
n := t.bins[i] n := t.bins[i]
next = n.each(func(v Val, _ int) bool { next = n.each(func(v Val) bool {
return f(v, n.po) return f(v, n.po)
}) })
if !next { if !next {
...@@ -709,7 +699,7 @@ func (t *Pot) eachNeighbourAsync(val Val, pof Pof, max int, maxPos int, f func(V ...@@ -709,7 +699,7 @@ func (t *Pot) eachNeighbourAsync(val Val, pof Pof, max int, maxPos int, f func(V
wg.Add(m) wg.Add(m)
} }
go func(pn *Pot, pm int) { go func(pn *Pot, pm int) {
pn.each(func(v Val, _ int) bool { pn.each(func(v Val) bool {
if wg != nil { if wg != nil {
defer wg.Done() defer wg.Done()
} }
...@@ -736,7 +726,7 @@ func (t *Pot) eachNeighbourAsync(val Val, pof Pof, max int, maxPos int, f func(V ...@@ -736,7 +726,7 @@ func (t *Pot) eachNeighbourAsync(val Val, pof Pof, max int, maxPos int, f func(V
wg.Add(m) wg.Add(m)
} }
go func(pn *Pot, pm int) { go func(pn *Pot, pm int) {
pn.each(func(v Val, _ int) bool { pn.each(func(v Val) bool {
if wg != nil { if wg != nil {
defer wg.Done() defer wg.Done()
} }
......
...@@ -65,14 +65,13 @@ func randomtestAddr(n int, i int) *testAddr { ...@@ -65,14 +65,13 @@ func randomtestAddr(n int, i int) *testAddr {
return newTestAddr(v, i) return newTestAddr(v, i)
} }
func indexes(t *Pot) (i []int, po []int) { func indexes(t *Pot) (i []int) {
t.Each(func(v Val, p int) bool { t.Each(func(v Val) bool {
a := v.(*testAddr) a := v.(*testAddr)
i = append(i, a.i) i = append(i, a.i)
po = append(po, p)
return true return true
}) })
return i, po return i
} }
func testAdd(t *Pot, pof Pof, j int, values ...string) (_ *Pot, n int, f bool) { func testAdd(t *Pot, pof Pof, j int, values ...string) (_ *Pot, n int, f bool) {
...@@ -102,23 +101,18 @@ func TestPotRemoveSameBin(t *testing.T) { ...@@ -102,23 +101,18 @@ func TestPotRemoveSameBin(t *testing.T) {
n := NewPot(newTestAddr("11111111", 0), 0) n := NewPot(newTestAddr("11111111", 0), 0)
n, _, _ = testAdd(n, pof, 1, "00000000", "01000000", "01100000", "01110000", "01111000") n, _, _ = testAdd(n, pof, 1, "00000000", "01000000", "01100000", "01110000", "01111000")
n, _, _ = Remove(n, newTestAddr("01110000", 0), pof) n, _, _ = Remove(n, newTestAddr("01110000", 0), pof)
inds, po := indexes(n) inds := indexes(n)
goti := n.Size() goti := n.Size()
expi := 5 expi := 5
if goti != expi { if goti != expi {
t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti) t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti)
} }
inds, po = indexes(n) inds = indexes(n)
got := fmt.Sprintf("%v", inds) got := fmt.Sprintf("%v", inds)
exp := "[5 3 2 1 0]" exp := "[5 3 2 1 0]"
if got != exp { if got != exp {
t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got) t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got)
} }
got = fmt.Sprintf("%v", po)
exp = "[3 2 1 0 0]"
if got != exp {
t.Fatalf("incorrect po-s in iteration over Pot. Expected %v, got %v", exp, got)
}
} }
// this test creates a flat pot tree (all the elements are leafs of one root), // this test creates a flat pot tree (all the elements are leafs of one root),
...@@ -129,22 +123,24 @@ func TestPotRemoveDifferentBins(t *testing.T) { ...@@ -129,22 +123,24 @@ func TestPotRemoveDifferentBins(t *testing.T) {
n := NewPot(newTestAddr("11111111", 0), 0) n := NewPot(newTestAddr("11111111", 0), 0)
n, _, _ = testAdd(n, pof, 1, "00000000", "10000000", "11000000", "11100000", "11110000") n, _, _ = testAdd(n, pof, 1, "00000000", "10000000", "11000000", "11100000", "11110000")
n, _, _ = Remove(n, newTestAddr("11100000", 0), pof) n, _, _ = Remove(n, newTestAddr("11100000", 0), pof)
inds, po := indexes(n) inds := indexes(n)
goti := n.Size() goti := n.Size()
expi := 5 expi := 5
if goti != expi { if goti != expi {
t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti) t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti)
} }
inds, po = indexes(n) inds = indexes(n)
got := fmt.Sprintf("%v", inds) got := fmt.Sprintf("%v", inds)
exp := "[1 2 3 5 0]" exp := "[1 2 3 5 0]"
if got != exp { if got != exp {
t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got) t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got)
} }
got = fmt.Sprintf("%v", po) n, _, _ = testAdd(n, pof, 4, "11100000")
exp = "[0 1 2 4 0]" inds = indexes(n)
got = fmt.Sprintf("%v", inds)
exp = "[1 2 3 4 5 0]"
if got != exp { if got != exp {
t.Fatalf("incorrect po-s in iteration over Pot. Expected %v, got %v", exp, got) t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got)
} }
} }
...@@ -171,17 +167,12 @@ func TestPotAdd(t *testing.T) { ...@@ -171,17 +167,12 @@ func TestPotAdd(t *testing.T) {
if goti != expi { if goti != expi {
t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti) t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti)
} }
inds, po := indexes(n) inds := indexes(n)
got = fmt.Sprintf("%v", inds) got = fmt.Sprintf("%v", inds)
exp = "[3 4 2]" exp = "[3 4 2]"
if got != exp { if got != exp {
t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got) t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got)
} }
got = fmt.Sprintf("%v", po)
exp = "[1 2 0]"
if got != exp {
t.Fatalf("incorrect po-s in iteration over Pot. Expected %v, got %v", exp, got)
}
} }
func TestPotRemove(t *testing.T) { func TestPotRemove(t *testing.T) {
...@@ -200,25 +191,20 @@ func TestPotRemove(t *testing.T) { ...@@ -200,25 +191,20 @@ func TestPotRemove(t *testing.T) {
if goti != expi { if goti != expi {
t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti) t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti)
} }
inds, po := indexes(n) inds := indexes(n)
got = fmt.Sprintf("%v", po)
exp = "[1 3 0]"
if got != exp {
t.Fatalf("incorrect po-s in iteration over Pot. Expected %v, got %v", exp, got)
}
got = fmt.Sprintf("%v", inds) got = fmt.Sprintf("%v", inds)
exp = "[2 4 1]" exp = "[2 4 1]"
if got != exp { if got != exp {
t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got) t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got)
} }
n, _, _ = Remove(n, newTestAddr("00111100", 0), pof) // remove again same element n, _, _ = Remove(n, newTestAddr("00111100", 0), pof) // remove again same element
inds, _ = indexes(n) inds = indexes(n)
got = fmt.Sprintf("%v", inds) got = fmt.Sprintf("%v", inds)
if got != exp { if got != exp {
t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got) t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got)
} }
n, _, _ = Remove(n, newTestAddr("00000000", 0), pof) // remove the first element n, _, _ = Remove(n, newTestAddr("00000000", 0), pof) // remove the first element
inds, _ = indexes(n) inds = indexes(n)
got = fmt.Sprintf("%v", inds) got = fmt.Sprintf("%v", inds)
exp = "[2 4]" exp = "[2 4]"
if got != exp { if got != exp {
...@@ -272,7 +258,7 @@ func TestPotSwap(t *testing.T) { ...@@ -272,7 +258,7 @@ func TestPotSwap(t *testing.T) {
}) })
} }
sum := 0 sum := 0
n.Each(func(v Val, i int) bool { n.Each(func(v Val) bool {
if v == nil { if v == nil {
return true return true
} }
......
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