mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-16 17:03:46 +00:00
pot, swarm/network: cleanup, fix depth in kad table
This commit is contained in:
parent
1598e68600
commit
72517463c8
14 changed files with 185 additions and 559 deletions
|
|
@ -197,7 +197,7 @@ func ToBytes(v Val) []byte {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultPof returns a proximity order operator function
|
// DefaultPof returns a proximity order comparison operator function
|
||||||
// where all
|
// where all
|
||||||
func DefaultPof(max int) func(one, other Val, pos int) (int, bool) {
|
func DefaultPof(max int) func(one, other Val, pos int) (int, bool) {
|
||||||
return func(one, other Val, pos int) (int, bool) {
|
return func(one, other Val, pos int) (int, bool) {
|
||||||
|
|
|
||||||
|
|
@ -1,142 +0,0 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
package pot
|
|
||||||
|
|
||||||
//
|
|
||||||
// import (
|
|
||||||
// "math/rand"
|
|
||||||
// "reflect"
|
|
||||||
// "testing"
|
|
||||||
//
|
|
||||||
// "github.com/ethereum/go-ethereum/common"
|
|
||||||
// )
|
|
||||||
// //
|
|
||||||
// // func (Address) Generate(rand *rand.Rand, size int) reflect.Value {
|
|
||||||
// // var id Address
|
|
||||||
// // for i := 0; i < len(id); i++ {
|
|
||||||
// // id[i] = byte(uint8(rand.Intn(255)))
|
|
||||||
// // }
|
|
||||||
// // return reflect.ValueOf(id)
|
|
||||||
// // }
|
|
||||||
//
|
|
||||||
// func TestCommonBitsAddrF(t *testing.T) {
|
|
||||||
// a := Address(common.HexToHash("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))
|
|
||||||
// b := Address(common.HexToHash("0x8123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))
|
|
||||||
// c := Address(common.HexToHash("0x4123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))
|
|
||||||
// d := Address(common.HexToHash("0x0023456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))
|
|
||||||
// e := Address(common.HexToHash("0x01A3456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"))
|
|
||||||
// ab := CommonBitsAddrF(a, b, func() byte { return byte(0x00) }, 10)
|
|
||||||
// expab := Address(common.HexToHash("0x8000000000000000000000000000000000000000000000000000000000000000"))
|
|
||||||
//
|
|
||||||
// if ab != expab {
|
|
||||||
// t.Fatalf("%v != %v", ab, expab)
|
|
||||||
// }
|
|
||||||
// ac := CommonBitsAddrF(a, c, func() byte { return byte(0x00) }, 10)
|
|
||||||
// expac := Address(common.HexToHash("0x4000000000000000000000000000000000000000000000000000000000000000"))
|
|
||||||
//
|
|
||||||
// if ac != expac {
|
|
||||||
// t.Fatalf("%v != %v", ac, expac)
|
|
||||||
// }
|
|
||||||
// ad := CommonBitsAddrF(a, d, func() byte { return byte(0x00) }, 10)
|
|
||||||
// expad := Address(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"))
|
|
||||||
//
|
|
||||||
// if ad != expad {
|
|
||||||
// t.Fatalf("%v != %v", ad, expad)
|
|
||||||
// }
|
|
||||||
// ae := CommonBitsAddrF(a, e, func() byte { return byte(0x00) }, 10)
|
|
||||||
// expae := Address(common.HexToHash("0x0180000000000000000000000000000000000000000000000000000000000000"))
|
|
||||||
//
|
|
||||||
// if ae != expae {
|
|
||||||
// t.Fatalf("%v != %v", ae, expae)
|
|
||||||
// }
|
|
||||||
// acf := CommonBitsAddrF(a, c, func() byte { return byte(0xff) }, 10)
|
|
||||||
// expacf := Address(common.HexToHash("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
|
|
||||||
//
|
|
||||||
// if acf != expacf {
|
|
||||||
// t.Fatalf("%v != %v", acf, expacf)
|
|
||||||
// }
|
|
||||||
// aeo := CommonBitsAddrF(a, e, func() byte { return byte(0x00) }, 2)
|
|
||||||
// expaeo := Address(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"))
|
|
||||||
//
|
|
||||||
// if aeo != expaeo {
|
|
||||||
// t.Fatalf("%v != %v", aeo, expaeo)
|
|
||||||
// }
|
|
||||||
// aep := CommonBitsAddrF(a, e, func() byte { return byte(0xff) }, 2)
|
|
||||||
// expaep := Address(common.HexToHash("0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
|
|
||||||
//
|
|
||||||
// if aep != expaep {
|
|
||||||
// t.Fatalf("%v != %v", aep, expaep)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func TestRandomAddressAt(t *testing.T) {
|
|
||||||
// var a Address
|
|
||||||
// for i := 0; i < 100; i++ {
|
|
||||||
// a = RandomAddress()
|
|
||||||
// prox := rand.Intn(255)
|
|
||||||
// b := RandomAddressAt(a, prox)
|
|
||||||
// p, _ := proximity(a, b)
|
|
||||||
// if p != prox {
|
|
||||||
// t.Fatalf("incorrect address prox(%v, %v) == %v (expected %v)", a, b, p, prox)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const (
|
|
||||||
// maxTestPOs = 1000
|
|
||||||
// testPOkeylen = 9
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// func TestPOs(t *testing.T) {
|
|
||||||
// for i := 0; i < maxTestPOs; i++ {
|
|
||||||
// length := rand.Intn(256) + 1
|
|
||||||
// v0 := RandomAddress().Bin()[:length]
|
|
||||||
// v1 := RandomAddress().Bin()[:length]
|
|
||||||
// a0 := NewBoolAddress(v0)
|
|
||||||
// a1 := NewBoolAddress(v1)
|
|
||||||
// b0 := NewHashAddress(v0)
|
|
||||||
// b1 := NewHashAddress(v1)
|
|
||||||
// pos := rand.Intn(length) + 1
|
|
||||||
// apo, aeq := a0.PO(a1, pos)
|
|
||||||
// bpo, beq := b0.PO(b1, pos)
|
|
||||||
// if bpo == 256 {
|
|
||||||
// bpo = length
|
|
||||||
// }
|
|
||||||
// a0s := a0.String()
|
|
||||||
// if a0s != v0 {
|
|
||||||
// t.Fatalf("incorrect bool address. expected %v, got %v", v0, a0s)
|
|
||||||
// }
|
|
||||||
// a1s := a1.String()
|
|
||||||
// if a1s != v1 {
|
|
||||||
// t.Fatalf("incorrect bool address. expected %v, got %v", v1, a1s)
|
|
||||||
// }
|
|
||||||
// b0s := b0.String()[:length]
|
|
||||||
// if b0s != v0 {
|
|
||||||
// t.Fatalf("incorrect hash address. expected %v, got %v", v0, b0s)
|
|
||||||
// }
|
|
||||||
// b1s := b1.String()[:length]
|
|
||||||
// if b1s != v1 {
|
|
||||||
// t.Fatalf("incorrect hash address. expected %v, got %v", v1, b1s)
|
|
||||||
// }
|
|
||||||
// if apo != bpo {
|
|
||||||
// t.Fatalf("PO does not match for %v X %v (pos: %v): expected %v, got %v", v0, v1, pos, apo, bpo)
|
|
||||||
// }
|
|
||||||
// if aeq != beq {
|
|
||||||
// t.Fatalf("PO equality does not match for %v X %v (pos: %v): expected %v, got %v", v0, v1, pos, aeq, beq)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
40
pot/doc.go
40
pot/doc.go
|
|
@ -16,23 +16,21 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package pot (proximity order tree) implements a container similar to a binary tree.
|
Package pot (proximity order tree) implements a container similar to a binary tree.
|
||||||
Value types implement the PoVal interface which provides the PO (proximity order)
|
The elements are generic Val interface types.
|
||||||
comparison operator.
|
|
||||||
Each fork in the trie is itself a value. Values of the subtree contained under
|
Each fork in the trie is itself a value. Values of the subtree contained under
|
||||||
a node all share the same order when compared to other elements in the tree.
|
a node all share the same order when compared to other elements in the tree.
|
||||||
|
|
||||||
Example of proximity order is the length of the common prefix over bitvectors.
|
Example of proximity order is the length of the common prefix over bitvectors.
|
||||||
(which is equivalent to the order of magnitude of the XOR distance over integers).
|
(which is equivalent to the reverse rank of order of magnitude of the MSB first X
|
||||||
|
OR distance over finite set of integers).
|
||||||
|
|
||||||
The package provides two implementations of PoVal,
|
Methods take a comparison operator (pof, proximity order function) to compare two
|
||||||
|
value types. The default pof assumes Val to be or project to a byte slice using
|
||||||
* BoolAddress: an arbitrary length boolean vector
|
the reverse rank on the MSB first XOR logarithmic disctance.
|
||||||
* HashAddress: a bitvector based address derived from 256 bit hash (common.Hash)
|
|
||||||
|
|
||||||
If the address space if limited, equality is defined as the maximum proximity order.
|
If the address space if limited, equality is defined as the maximum proximity order.
|
||||||
|
|
||||||
Arbitrary value types can extend these base types or define their own PO method.
|
|
||||||
|
|
||||||
The container offers applicative (funcional) style methods on PO trees:
|
The container offers applicative (funcional) style methods on PO trees:
|
||||||
* adding/removing en element
|
* adding/removing en element
|
||||||
* swap (value based add/remove)
|
* swap (value based add/remove)
|
||||||
|
|
@ -42,8 +40,10 @@ as well as iterator accessors that respect proximity order
|
||||||
|
|
||||||
When synchronicity of membership if not 100% requirement (e.g. used as a database
|
When synchronicity of membership if not 100% requirement (e.g. used as a database
|
||||||
of network connections), applicative structures have the advantage that nodes
|
of network connections), applicative structures have the advantage that nodes
|
||||||
are immutable therefore manipulation does not need locking allowing for parallel retrievals.
|
are immutable therefore manipulation does not need locking allowing for
|
||||||
For the use case where the entire container is supposed to allow changes by parallel routines, instance methods with write locks and access methods with readlock are provided. The latter only locks while reading the root node.
|
concurrent retrievals.
|
||||||
|
For the use case where the entire container is supposed to allow changes by
|
||||||
|
concurrent routines,
|
||||||
|
|
||||||
Pot
|
Pot
|
||||||
* retrieval, insertion and deletion by key involves log(n) pointer lookups
|
* retrieval, insertion and deletion by key involves log(n) pointer lookups
|
||||||
|
|
@ -51,10 +51,11 @@ Pot
|
||||||
* provide syncronous iterators respecting proximity ordering wrt any item
|
* provide syncronous iterators respecting proximity ordering wrt any item
|
||||||
* provide asyncronous iterator (for parallel execution of operations) over n items
|
* provide asyncronous iterator (for parallel execution of operations) over n items
|
||||||
* allows cheap iteration over ranges
|
* allows cheap iteration over ranges
|
||||||
* asymmetric parallellised merge (union)
|
* asymmetric concurrent merge (union)
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
* as is, union only makes sense for set representations since which of two values with equal keys survives is random
|
* as is, union only makes sense for set representations since which of two values
|
||||||
|
with equal keys survives is random
|
||||||
* intersection is not implemented
|
* intersection is not implemented
|
||||||
* simple get accessor is not implemented (but derivable from EachNeighbour)
|
* simple get accessor is not implemented (but derivable from EachNeighbour)
|
||||||
|
|
||||||
|
|
@ -63,16 +64,17 @@ Pinned value on the node implies no need to copy keys of the item type.
|
||||||
Note that
|
Note that
|
||||||
* the same set of values allows for a large number of alternative
|
* the same set of values allows for a large number of alternative
|
||||||
POT representations.
|
POT representations.
|
||||||
* values on the top are accessed faster than lower ones and the steps needed to retrieve items has a logarithmic distribution.
|
* values on the top are accessed faster than lower ones and the steps needed to
|
||||||
|
retrieve items has a logarithmic distribution.
|
||||||
|
|
||||||
As a consequence on can organise the tree so that items that need faster access are torwards the top.
|
As a consequence one can organise the tree so that items that need faster access
|
||||||
In particular for any subset where popularity has a power distriution that is independent of
|
are torwards the top. In particular for any subset where popularity has a power
|
||||||
proximity order (content addressed storage of chunks), it is in principle possible to create a pot where the steps needed to access an item is inversely proportional to its popularity.
|
distriution that is independent of proximity order (content addressed storage of
|
||||||
|
chunks), it is in principle possible to create a pot where the steps needed to
|
||||||
|
access an item is inversely proportional to its popularity.
|
||||||
Such organisation is not implemented as yet.
|
Such organisation is not implemented as yet.
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
* swap
|
|
||||||
* get
|
|
||||||
* overwrite-style merge
|
* overwrite-style merge
|
||||||
* intersection
|
* intersection
|
||||||
* access frequency based optimisations
|
* access frequency based optimisations
|
||||||
|
|
|
||||||
120
pot/pot.go
120
pot/pot.go
|
|
@ -26,12 +26,6 @@ const (
|
||||||
maxkeylen = 256
|
maxkeylen = 256
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pot is the root node type, allows locked non-applicative manipulation
|
|
||||||
// type Pot struct {
|
|
||||||
// lock sync.RWMutex
|
|
||||||
// *Pot
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Pot is the node type (same for root, branching node and leaf)
|
// Pot is the node type (same for root, branching node and leaf)
|
||||||
type Pot struct {
|
type Pot struct {
|
||||||
pin Val
|
pin Val
|
||||||
|
|
@ -43,10 +37,10 @@ type Pot struct {
|
||||||
// Val is the element type for Pots
|
// Val is the element type for Pots
|
||||||
type Val interface{}
|
type Val interface{}
|
||||||
|
|
||||||
// Pof is the proximity order function
|
// Pof is the proximity order comparison operator function
|
||||||
type Pof func(Val, Val, int) (int, bool)
|
type Pof func(Val, Val, int) (int, bool)
|
||||||
|
|
||||||
// NewPot constructor. Requires value of type Val to pin
|
// NewPot constructor. Requires a value of type Val to pin
|
||||||
// and po to point to a span in the Val key
|
// and po to point to a span in the Val key
|
||||||
// The pinned item counts towards the size
|
// The pinned item counts towards the size
|
||||||
func NewPot(v Val, po int) *Pot {
|
func NewPot(v Val, po int) *Pot {
|
||||||
|
|
@ -68,37 +62,20 @@ func (t *Pot) Pin() Val {
|
||||||
|
|
||||||
// Size returns the number of values in the Pot
|
// Size returns the number of values in the Pot
|
||||||
func (t *Pot) Size() int {
|
func (t *Pot) Size() int {
|
||||||
// t.lock.RLock()
|
|
||||||
// defer t.lock.RUnlock()
|
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return t.size
|
return t.size
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add inserts v into the Pot and
|
// Add inserts a new value into the Pot and
|
||||||
// returns the proximity order of v and a boolean
|
// returns the proximity order of v and a boolean
|
||||||
// indicating if the item was found
|
// indicating if the item was found
|
||||||
// Add locks the Pot while using applicative add on its Pot
|
|
||||||
// func (t *Pot) Add(val Val) (po int, found bool) {
|
|
||||||
// // t.lock.Lock()
|
|
||||||
// // defer t.lock.Unlock()
|
|
||||||
// t.Pot, po, found = add(t.Pot, val)
|
|
||||||
// return po, found
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Add called on (t, v) returns a new Pot that contains all the elements of t
|
// Add called on (t, v) returns a new Pot that contains all the elements of t
|
||||||
// plus the value v, using the applicative add
|
// plus the value v, using the applicative add
|
||||||
// the second return value is the proximity order of the inserted element
|
// the second return value is the proximity order of the inserted element
|
||||||
// the third is boolean indicating if the item was found
|
// the third is boolean indicating if the item was found
|
||||||
// it only readlocks the Pot while reading its Pot
|
|
||||||
func Add(t *Pot, val Val, pof Pof) (*Pot, int, bool) {
|
func Add(t *Pot, val Val, pof Pof) (*Pot, int, bool) {
|
||||||
// // t.lock.RLock()
|
|
||||||
// n := t.Pot
|
|
||||||
// // t.lock.RUnlock()
|
|
||||||
// r, po, found := add(n, val)
|
|
||||||
// return &Pot{Pot: r}, po, found
|
|
||||||
// // return &Pot{Pot: r}, po, found
|
|
||||||
return add(t, val, pof)
|
return add(t, val, pof)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,25 +147,11 @@ func add(t *Pot, val Val, pof Pof) (*Pot, int, bool) {
|
||||||
// Remove called on (v) deletes v from the Pot and returns
|
// Remove called on (v) deletes v from the Pot and returns
|
||||||
// the proximity order of v and a boolean value indicating
|
// the proximity order of v and a boolean value indicating
|
||||||
// if the value was found
|
// if the value was found
|
||||||
// Remove locks Pot while using applicative remove on its Pot
|
|
||||||
// func (t *Pot) Remove(val Val) (po int, found bool) {
|
|
||||||
// // t.lock.Lock()
|
|
||||||
// // defer t.lock.Unlock()
|
|
||||||
// t.Pot, po, found = remove(t.Pot, val)
|
|
||||||
// return po, found
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Remove called on (t, v) returns a new Pot that contains all the elements of t
|
// Remove called on (t, v) returns a new Pot that contains all the elements of t
|
||||||
// minus the value v, using the applicative remove
|
// minus the value v, using the applicative remove
|
||||||
// the second return value is the proximity order of the inserted element
|
// the second return value is the proximity order of the inserted element
|
||||||
// the third is boolean indicating if the item was found
|
// the third is boolean indicating if the item was found
|
||||||
// it only readlocks the Pot while reading its Pot
|
|
||||||
func Remove(t *Pot, v Val, pof Pof) (*Pot, int, bool) {
|
func Remove(t *Pot, v Val, pof Pof) (*Pot, int, bool) {
|
||||||
// // t.lock.RLock()
|
|
||||||
// n := t.Pot
|
|
||||||
// // t.lock.RUnlock()
|
|
||||||
// r, po, found := remove(n, v)
|
|
||||||
// return &Pot{Pot: r}, po, found
|
|
||||||
return remove(t, v, pof)
|
return remove(t, v, pof)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,30 +210,11 @@ func remove(t *Pot, val Val, pof Pof) (r *Pot, po int, found bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap called on (k, f) looks up the item at k
|
// Swap called on (k, f) looks up the item at k
|
||||||
// and applies the function f to the value v at k or nil if the item is not found
|
// and applies the function f to the value v at k or to nil if the item is not found
|
||||||
// if f returns nil, the element is removed
|
// if f(v) returns nil, the element is removed
|
||||||
// if f returns v' <> v then v' is inserted into the Pot
|
// if f(v) returns v' <> v then v' is inserted into the Pot
|
||||||
// if v' == v the Pot is not changed
|
// if (v) == v the Pot is not changed
|
||||||
// it panics if v'.PO(k, 0) says v and k are not equal
|
// it panics if Pof(f(v), k) show that v' and v are not key-equal
|
||||||
// func (t *Pot) Swap(val Val, f func(v Val) Val) (po int, found bool, change bool) {
|
|
||||||
// t.lock.Lock()
|
|
||||||
// defer t.lock.Unlock()
|
|
||||||
// var t0 *Pot
|
|
||||||
// t0, po, found, change = swap(t.Pot, val, f)
|
|
||||||
// if change {
|
|
||||||
// t.Pot = t0
|
|
||||||
// }
|
|
||||||
// return po, found, change
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Swap is applicative add, change, remove on a Pot
|
|
||||||
// func Swap(t *Pot, val Val, f func(v Val) Val) (_ *Pot, po int, found bool, change bool) {
|
|
||||||
// var t0 *Pot
|
|
||||||
// t0, po, found, change = swap(t.Pot, val, f)
|
|
||||||
// return &Pot{Pot: t0}, po, found, change
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func swap(t *Pot, k Val, f func(v Val) Val) (r *Pot, po int, found bool, change bool) {
|
|
||||||
func Swap(t *Pot, k Val, pof Pof, f func(v Val) Val) (r *Pot, po int, found bool, change bool) {
|
func Swap(t *Pot, k Val, pof Pof, f func(v Val) Val) (r *Pot, po int, found bool, change bool) {
|
||||||
var val Val
|
var val Val
|
||||||
if t.pin == nil {
|
if t.pin == nil {
|
||||||
|
|
@ -325,7 +269,6 @@ func Swap(t *Pot, k Val, pof Pof, f func(v Val) Val) (r *Pot, po int, found bool
|
||||||
return t, po, found, false
|
return t, po, found, false
|
||||||
}
|
}
|
||||||
// recursive change
|
// recursive change
|
||||||
//size += p.size - n.size
|
|
||||||
bins := append([]*Pot{}, t.bins[:i]...)
|
bins := append([]*Pot{}, t.bins[:i]...)
|
||||||
if p.size == 0 {
|
if p.size == 0 {
|
||||||
size--
|
size--
|
||||||
|
|
@ -371,33 +314,10 @@ func Swap(t *Pot, k Val, pof Pof, f func(v Val) Val) (r *Pot, po int, found bool
|
||||||
return r, po, found, true
|
return r, po, found, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge called on (t1) changes t0 to contain all the elements of t1
|
// Union called on (t0, t1, pof) returns the union of t0 and t1
|
||||||
// it locks t0, but only readlocks t1 while taking its Pot
|
|
||||||
// uses applicative union
|
|
||||||
// func (t *Pot) Merge(t1 *Pot) (c int) {
|
|
||||||
// t.lock.Lock()
|
|
||||||
// defer t.lock.Unlock()
|
|
||||||
// t1.lock.RLock()
|
|
||||||
// n1 := t1.Pot
|
|
||||||
// t1.lock.RUnlock()
|
|
||||||
// t.Pot, c = union(t.Pot, n1)
|
|
||||||
// return c
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Union returns the union of t0 and t1
|
|
||||||
// it only readlocks the Pot-s to read their Pots and
|
|
||||||
// calculates the union using the applicative union
|
// calculates the union using the applicative union
|
||||||
// the second return value is the number of common elements
|
// the second return value is the number of common elements
|
||||||
func Union(t0, t1 *Pot, pof Pof) (*Pot, int) {
|
func Union(t0, t1 *Pot, pof Pof) (*Pot, int) {
|
||||||
// t0.lock.RLock()
|
|
||||||
// n0 := t0.Pot
|
|
||||||
// t0.lock.RUnlock()
|
|
||||||
// t1.lock.RLock()
|
|
||||||
// n1 := t1.Pot
|
|
||||||
// t1.lock.RUnlock()
|
|
||||||
//
|
|
||||||
// p, c := union(n0, n1)
|
|
||||||
// return &Pot{Pot: p}, c
|
|
||||||
return union(t0, t1, pof)
|
return union(t0, t1, pof)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -537,10 +457,6 @@ func union(t0, t1 *Pot, pof Pof) (*Pot, int) {
|
||||||
// respecting an ordering
|
// respecting an ordering
|
||||||
// proximity > pinnedness
|
// proximity > pinnedness
|
||||||
func (t *Pot) Each(f func(Val, int) bool) bool {
|
func (t *Pot) Each(f func(Val, int) bool) bool {
|
||||||
// t.lock.RLock()
|
|
||||||
// n := t.Pot
|
|
||||||
// t.lock.RUnlock()
|
|
||||||
// return n.each(f)
|
|
||||||
return t.each(f)
|
return t.each(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -570,10 +486,6 @@ func (t *Pot) each(f func(Val, int) bool) bool {
|
||||||
// the iteration ends if the function return false or there are no more elements
|
// 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
|
// end of a po range can be implemented since po is passed to the function
|
||||||
func (t *Pot) EachFrom(f func(Val, int) bool, po int) bool {
|
func (t *Pot) EachFrom(f func(Val, int) bool, po int) bool {
|
||||||
// t.lock.RLock()
|
|
||||||
// n := t.Pot
|
|
||||||
// t.lock.RUnlock()
|
|
||||||
// return n.eachFrom(f, po)
|
|
||||||
return t.eachFrom(f, po)
|
return t.eachFrom(f, po)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -595,10 +507,6 @@ func (t *Pot) eachFrom(f func(Val, int) bool, po int) bool {
|
||||||
// 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, i int) bool) bool) bool) {
|
||||||
// t.lock.RLock()
|
|
||||||
// n := t.Pot
|
|
||||||
// t.lock.RUnlock()
|
|
||||||
// n.eachBin(val, po, f)
|
|
||||||
t.eachBin(val, pof, po, f)
|
t.eachBin(val, pof, po, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -649,10 +557,6 @@ func (t *Pot) eachBin(val Val, pof Pof, po int, f func(int, int, func(func(val V
|
||||||
// the order of elements retrieved reflect proximity order to the target
|
// the order of elements retrieved reflect proximity order to the target
|
||||||
// TODO: add maximum proxbin to start range of iteration
|
// TODO: add maximum proxbin to start range of iteration
|
||||||
func (t *Pot) EachNeighbour(val Val, pof Pof, f func(Val, int) bool) bool {
|
func (t *Pot) EachNeighbour(val Val, pof Pof, f func(Val, int) bool) bool {
|
||||||
// t.lock.RLock()
|
|
||||||
// n := t.Pot
|
|
||||||
// t.lock.RUnlock()
|
|
||||||
// return n.eachNeighbour(val, f)
|
|
||||||
return t.eachNeighbour(val, pof, f)
|
return t.eachNeighbour(val, pof, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -717,9 +621,6 @@ func (t *Pot) eachNeighbour(val Val, pof Pof, f func(Val, int) bool) bool {
|
||||||
// if wait is true, the iterator returns only if all calls to f are finished
|
// if wait is true, the iterator returns only if all calls to f are finished
|
||||||
// TODO: implement minPos for proper prox range iteration
|
// TODO: implement minPos for proper prox range iteration
|
||||||
func (t *Pot) EachNeighbourAsync(val Val, pof Pof, max int, maxPos int, f func(Val, int), wait bool) {
|
func (t *Pot) EachNeighbourAsync(val Val, pof Pof, max int, maxPos int, f func(Val, int), wait bool) {
|
||||||
// t.lock.RLock()
|
|
||||||
// n := t.Pot
|
|
||||||
// t.lock.RUnlock()
|
|
||||||
if max > t.size {
|
if max > t.size {
|
||||||
max = t.size
|
max = t.size
|
||||||
}
|
}
|
||||||
|
|
@ -727,8 +628,7 @@ func (t *Pot) EachNeighbourAsync(val Val, pof Pof, max int, maxPos int, f func(V
|
||||||
if wait {
|
if wait {
|
||||||
wg = &sync.WaitGroup{}
|
wg = &sync.WaitGroup{}
|
||||||
}
|
}
|
||||||
// _ = n.eachNeighbourAsync(val, max, maxPos, f, wg)
|
t.eachNeighbourAsync(val, pof, max, maxPos, f, wg)
|
||||||
_ = t.eachNeighbourAsync(val, pof, max, maxPos, f, wg)
|
|
||||||
if wait {
|
if wait {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,6 @@ func TestPotRemove(t *testing.T) {
|
||||||
|
|
||||||
func TestPotSwap(t *testing.T) {
|
func TestPotSwap(t *testing.T) {
|
||||||
for i := 0; i < maxSwapTests; i++ {
|
for i := 0; i < maxSwapTests; i++ {
|
||||||
// alen := maxkeylen
|
|
||||||
alen := maxkeylen
|
alen := maxkeylen
|
||||||
pof := DefaultPof(alen)
|
pof := DefaultPof(alen)
|
||||||
max := rand.Intn(maxSwap)
|
max := rand.Intn(maxSwap)
|
||||||
|
|
@ -292,7 +291,6 @@ func TestPotMergeCommon(t *testing.T) {
|
||||||
vs := make([]*testAddr, mergeTestCount)
|
vs := make([]*testAddr, mergeTestCount)
|
||||||
for i := 0; i < maxEachNeighbourTests; i++ {
|
for i := 0; i < maxEachNeighbourTests; i++ {
|
||||||
alen := maxkeylen
|
alen := maxkeylen
|
||||||
// alen := maxkeylen
|
|
||||||
pof := DefaultPof(alen)
|
pof := DefaultPof(alen)
|
||||||
|
|
||||||
for j := 0; j < len(vs); j++ {
|
for j := 0; j < len(vs); j++ {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,19 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -19,27 +35,27 @@ type discPeer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDiscovery discovery peer contructor
|
// NewDiscovery discovery peer contructor
|
||||||
func NewDiscovery(p *bzzPeer, o Overlay) *discPeer {
|
func newDiscovery(p *bzzPeer, o Overlay) *discPeer {
|
||||||
self := &discPeer{
|
d := &discPeer{
|
||||||
overlay: o,
|
overlay: o,
|
||||||
bzzPeer: p,
|
bzzPeer: p,
|
||||||
peers: make(map[string]bool),
|
peers: make(map[string]bool),
|
||||||
}
|
}
|
||||||
self.seen(self)
|
d.seen(d)
|
||||||
return self
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *discPeer) HandleMsg(msg interface{}) error {
|
func (d *discPeer) HandleMsg(msg interface{}) error {
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
|
|
||||||
case *peersMsg:
|
case *peersMsg:
|
||||||
return self.handlePeersMsg(msg)
|
return d.handlePeersMsg(msg)
|
||||||
|
|
||||||
case *getPeersMsg:
|
case *getPeersMsg:
|
||||||
return self.handleGetPeersMsg(msg)
|
return d.handleGetPeersMsg(msg)
|
||||||
|
|
||||||
case *subPeersMsg:
|
case *subPeersMsg:
|
||||||
return self.handleSubPeersMsg(msg)
|
return d.handleSubPeersMsg(msg)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown message type: %T", msg)
|
return fmt.Errorf("unknown message type: %T", msg)
|
||||||
|
|
@ -48,8 +64,8 @@ func (self *discPeer) HandleMsg(msg interface{}) error {
|
||||||
|
|
||||||
// NotifyPeer notifies the receiver remote end of a peer p or PO po.
|
// NotifyPeer notifies the receiver remote end of a peer p or PO po.
|
||||||
// callback for overlay driver
|
// callback for overlay driver
|
||||||
func (self *discPeer) NotifyPeer(a OverlayAddr, po uint8) error {
|
func (d *discPeer) NotifyPeer(a OverlayAddr, po uint8) error {
|
||||||
if po < self.depth || self.seen(a) {
|
if po < d.depth || d.seen(a) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Warn(fmt.Sprintf("notification about %x", a.Address()))
|
log.Warn(fmt.Sprintf("notification about %x", a.Address()))
|
||||||
|
|
@ -57,15 +73,15 @@ func (self *discPeer) NotifyPeer(a OverlayAddr, po uint8) error {
|
||||||
resp := &peersMsg{
|
resp := &peersMsg{
|
||||||
Peers: []*bzzAddr{ToAddr(a)}, // perhaps the PeerAddr interface is unnecessary generalization
|
Peers: []*bzzAddr{ToAddr(a)}, // perhaps the PeerAddr interface is unnecessary generalization
|
||||||
}
|
}
|
||||||
return self.Send(resp)
|
return d.Send(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyDepth sends a subPeers Msg to the receiver notifying them about
|
// NotifyDepth sends a subPeers Msg to the receiver notifying them about
|
||||||
// a change in the prox limit (radius of the set including the nearest X peers
|
// a change in the prox limit (radius of the set including the nearest X peers
|
||||||
// or first empty row)
|
// or first empty row)
|
||||||
// callback for overlay driver
|
// callback for overlay driver
|
||||||
func (self *discPeer) NotifyDepth(po uint8) error {
|
func (d *discPeer) NotifyDepth(po uint8) error {
|
||||||
return self.Send(&subPeersMsg{Depth: po})
|
return d.Send(&subPeersMsg{Depth: po})
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -91,8 +107,8 @@ type peersMsg struct {
|
||||||
Peers []*bzzAddr
|
Peers []*bzzAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self peersMsg) String() string {
|
func (msg peersMsg) String() string {
|
||||||
return fmt.Sprintf("%T: %v", self, self.Peers)
|
return fmt.Sprintf("%T: %v", msg, msg.Peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getPeersMsg is sent to (random) peers to request (Max) peers of a specific order
|
// getPeersMsg is sent to (random) peers to request (Max) peers of a specific order
|
||||||
|
|
@ -101,8 +117,8 @@ type getPeersMsg struct {
|
||||||
Max uint8
|
Max uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self getPeersMsg) String() string {
|
func (msg getPeersMsg) String() string {
|
||||||
return fmt.Sprintf("%T: accept max %v peers of PO%03d", self, self.Max, self.Order)
|
return fmt.Sprintf("%T: accept max %v peers of PO%03d", msg, msg.Max, msg.Order)
|
||||||
}
|
}
|
||||||
|
|
||||||
// subPeers msg is communicating the depth/sharpness/focus of the overlay table of a peer
|
// subPeers msg is communicating the depth/sharpness/focus of the overlay table of a peer
|
||||||
|
|
@ -110,41 +126,41 @@ type subPeersMsg struct {
|
||||||
Depth uint8
|
Depth uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self subPeersMsg) String() string {
|
func (msg subPeersMsg) String() string {
|
||||||
return fmt.Sprintf("%T: request peers > PO%02d. ", self, self.Depth)
|
return fmt.Sprintf("%T: request peers > PO%02d. ", msg, msg.Depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *discPeer) handleSubPeersMsg(msg *subPeersMsg) error {
|
func (d *discPeer) handleSubPeersMsg(msg *subPeersMsg) error {
|
||||||
self.depth = msg.Depth
|
d.depth = msg.Depth
|
||||||
if !self.sentPeers {
|
if !d.sentPeers {
|
||||||
var peers []*bzzAddr
|
var peers []*bzzAddr
|
||||||
self.overlay.EachConn(self.Over(), 255, func(p OverlayConn, po int, isproxbin bool) bool {
|
d.overlay.EachConn(d.Over(), 255, func(p OverlayConn, po int, isproxbin bool) bool {
|
||||||
if uint8(po) < self.depth {
|
if uint8(po) < d.depth {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !self.seen(p) {
|
if !d.seen(p) {
|
||||||
peers = append(peers, ToAddr(p.Off()))
|
peers = append(peers, ToAddr(p.Off()))
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
log.Warn(fmt.Sprintf("found initial %v peers not farther than %v", len(peers), self.depth))
|
log.Warn(fmt.Sprintf("found initial %v peers not farther than %v", len(peers), d.depth))
|
||||||
if len(peers) > 0 {
|
if len(peers) > 0 {
|
||||||
if err := self.Send(&peersMsg{Peers: peers}); err != nil {
|
if err := d.Send(&peersMsg{Peers: peers}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.sentPeers = true
|
d.sentPeers = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlePeersMsg called by the protocol when receiving peerset (for target address)
|
// handlePeersMsg called by the protocol when receiving peerset (for target address)
|
||||||
// list of nodes ([]PeerAddr in peersMsg) is added to the overlay db using the
|
// list of nodes ([]PeerAddr in peersMsg) is added to the overlay db using the
|
||||||
// Register interface method
|
// Register interface method
|
||||||
func (self *discPeer) handlePeersMsg(msg *peersMsg) error {
|
func (d *discPeer) handlePeersMsg(msg *peersMsg) error {
|
||||||
// register all addresses
|
// register all addresses
|
||||||
if len(msg.Peers) == 0 {
|
if len(msg.Peers) == 0 {
|
||||||
log.Debug(fmt.Sprintf("whoops, no peers in incoming peersMsg from %v", self))
|
log.Debug(fmt.Sprintf("whoops, no peers in incoming peersMsg from %v", d))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,12 +168,12 @@ func (self *discPeer) handlePeersMsg(msg *peersMsg) error {
|
||||||
go func() {
|
go func() {
|
||||||
defer close(c)
|
defer close(c)
|
||||||
for _, a := range msg.Peers {
|
for _, a := range msg.Peers {
|
||||||
self.seen(a)
|
d.seen(a)
|
||||||
c <- a
|
c <- a
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
log.Info("discovery overlay register")
|
log.Info("discovery overlay register")
|
||||||
return self.overlay.Register(c)
|
return d.overlay.Register(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleGetPeersMsg is called by the protocol when receiving a
|
// handleGetPeersMsg is called by the protocol when receiving a
|
||||||
|
|
@ -165,29 +181,31 @@ func (self *discPeer) handlePeersMsg(msg *peersMsg) error {
|
||||||
// peers suggestions are retrieved from the overlay topology driver
|
// peers suggestions are retrieved from the overlay topology driver
|
||||||
// using the EachConn interface iterator method
|
// using the EachConn interface iterator method
|
||||||
// peers sent are remembered throughout a session and not sent twice
|
// peers sent are remembered throughout a session and not sent twice
|
||||||
func (self *discPeer) handleGetPeersMsg(msg *getPeersMsg) error {
|
func (d *discPeer) handleGetPeersMsg(msg *getPeersMsg) error {
|
||||||
var peers []*bzzAddr
|
var peers []*bzzAddr
|
||||||
i := 0
|
i := 0
|
||||||
self.overlay.EachConn(self.Over(), int(msg.Order), func(p OverlayConn, po int, isproxbin bool) bool {
|
d.overlay.EachConn(d.Over(), int(msg.Order), func(p OverlayConn, po int, isproxbin bool) bool {
|
||||||
i++
|
i++
|
||||||
// only send peers we have not sent before in this session
|
// only send peers we have not sent before in this session
|
||||||
a := ToAddr(p.Off())
|
a := ToAddr(p.Off())
|
||||||
if self.seen(a) {
|
if d.seen(a) {
|
||||||
peers = append(peers, a)
|
peers = append(peers, a)
|
||||||
}
|
}
|
||||||
return len(peers) < int(msg.Max)
|
return len(peers) < int(msg.Max)
|
||||||
})
|
})
|
||||||
if len(peers) == 0 {
|
if len(peers) == 0 {
|
||||||
log.Debug(fmt.Sprintf("no peers found for %v", self))
|
log.Debug(fmt.Sprintf("no peers found for %v", d))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Debug(fmt.Sprintf("%v peers sent to %v", len(peers), self))
|
log.Debug(fmt.Sprintf("%v peers sent to %v", len(peers), d))
|
||||||
resp := &peersMsg{
|
resp := &peersMsg{
|
||||||
Peers: peers,
|
Peers: peers,
|
||||||
}
|
}
|
||||||
return self.Send(resp)
|
return d.Send(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequestOrder broadcasts to trageted peers a request for peers of a particular
|
||||||
|
// proximity order
|
||||||
func RequestOrder(k Overlay, order, broadcastSize, maxPeers uint8) {
|
func RequestOrder(k Overlay, order, broadcastSize, maxPeers uint8) {
|
||||||
req := &getPeersMsg{
|
req := &getPeersMsg{
|
||||||
Order: uint8(order),
|
Order: uint8(order),
|
||||||
|
|
@ -207,13 +225,13 @@ func RequestOrder(k Overlay, order, broadcastSize, maxPeers uint8) {
|
||||||
log.Info(fmt.Sprintf("requesting bees of PO%03d from %v/%v (each max %v)", order, i, broadcastSize, maxPeers))
|
log.Info(fmt.Sprintf("requesting bees of PO%03d from %v/%v (each max %v)", order, i, broadcastSize, maxPeers))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *discPeer) seen(p OverlayPeer) bool {
|
func (d *discPeer) seen(p OverlayPeer) bool {
|
||||||
self.mtx.Lock()
|
d.mtx.Lock()
|
||||||
defer self.mtx.Unlock()
|
defer d.mtx.Unlock()
|
||||||
k := string(p.Address())
|
k := string(p.Address())
|
||||||
if self.peers[k] {
|
if d.peers[k] {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
self.peers[k] = true
|
d.peers[k] = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,19 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -18,7 +34,7 @@ func TestDiscovery(t *testing.T) {
|
||||||
to := NewKademlia(addr.OAddr, NewKadParams())
|
to := NewKademlia(addr.OAddr, NewKadParams())
|
||||||
|
|
||||||
run := func(p *bzzPeer) error {
|
run := func(p *bzzPeer) error {
|
||||||
dp := NewDiscovery(p, to)
|
dp := newDiscovery(p, to)
|
||||||
to.On(p)
|
to.On(p)
|
||||||
defer to.Off(p)
|
defer to.Off(p)
|
||||||
log.Trace(fmt.Sprintf("kademlia on %v", p))
|
log.Trace(fmt.Sprintf("kademlia on %v", p))
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ func (h *Hive) Stop() {
|
||||||
|
|
||||||
// Run protocol run function
|
// Run protocol run function
|
||||||
func (h *Hive) Run(p *bzzPeer) error {
|
func (h *Hive) Run(p *bzzPeer) error {
|
||||||
dp := NewDiscovery(p, h)
|
dp := newDiscovery(p, h)
|
||||||
log.Debug(fmt.Sprintf("to add new bee %v", p))
|
log.Debug(fmt.Sprintf("to add new bee %v", p))
|
||||||
h.On(dp)
|
h.On(dp)
|
||||||
h.wake()
|
h.wake()
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,19 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -299,10 +299,10 @@ func (k *Kademlia) On(p OverlayConn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
depth := uint8(k.depth())
|
depth := uint8(k.depth())
|
||||||
|
var depthChanged bool
|
||||||
if depth != k.currentDepth {
|
if depth != k.currentDepth {
|
||||||
|
depthChanged = true
|
||||||
k.currentDepth = depth
|
k.currentDepth = depth
|
||||||
} else {
|
|
||||||
depth = 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go np.NotifyDepth(depth)
|
go np.NotifyDepth(depth)
|
||||||
|
|
@ -310,7 +310,7 @@ func (k *Kademlia) On(p OverlayConn) {
|
||||||
dp := val.(*entry).OverlayPeer.(Notifier)
|
dp := val.(*entry).OverlayPeer.(Notifier)
|
||||||
dp.NotifyPeer(p.Off(), uint8(po))
|
dp.NotifyPeer(p.Off(), uint8(po))
|
||||||
log.Trace(fmt.Sprintf("peer %v notified of %v (%v)", dp, p, po))
|
log.Trace(fmt.Sprintf("peer %v notified of %v (%v)", dp, p, po))
|
||||||
if depth > 0 {
|
if depthChanged {
|
||||||
dp.NotifyDepth(depth)
|
dp.NotifyDepth(depth)
|
||||||
log.Trace(fmt.Sprintf("peer %v notified of new depth %v", dp, depth))
|
log.Trace(fmt.Sprintf("peer %v notified of new depth %v", dp, depth))
|
||||||
}
|
}
|
||||||
|
|
@ -442,9 +442,8 @@ func (k *Kademlia) String() string {
|
||||||
|
|
||||||
liverows := make([]string, k.MaxProxDisplay)
|
liverows := make([]string, k.MaxProxDisplay)
|
||||||
peersrows := make([]string, k.MaxProxDisplay)
|
peersrows := make([]string, k.MaxProxDisplay)
|
||||||
var depth int
|
|
||||||
prev := -1
|
depth := k.depth()
|
||||||
var depthSet bool
|
|
||||||
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, i int) bool) bool) bool {
|
||||||
var rowlen int
|
var rowlen int
|
||||||
|
|
@ -459,14 +458,9 @@ func (k *Kademlia) String() string {
|
||||||
rowlen++
|
rowlen++
|
||||||
return rowlen < 4
|
return rowlen < 4
|
||||||
})
|
})
|
||||||
if !depthSet && (po > prev+1 || rest < k.MinProxBinSize) {
|
|
||||||
depthSet = true
|
|
||||||
depth = prev + 1
|
|
||||||
}
|
|
||||||
r := strings.Join(row, " ")
|
r := strings.Join(row, " ")
|
||||||
r = r + wsrow
|
r = r + wsrow
|
||||||
liverows[po] = r[:31]
|
liverows[po] = r[:31]
|
||||||
prev = po
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -27,9 +28,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
h := log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))
|
// h := log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))
|
||||||
// h := log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))
|
h := log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))
|
||||||
// h := log.CallerFileHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(true)))
|
|
||||||
log.Root().SetHandler(h)
|
log.Root().SetHandler(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,26 +65,26 @@ type dropError struct {
|
||||||
addr string
|
addr string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *testDropPeer) Drop(err error) {
|
func (d *testDropPeer) Drop(err error) {
|
||||||
err2 := &dropError{err, binStr(self)}
|
err2 := &dropError{err, binStr(d)}
|
||||||
self.dropc <- err2
|
d.dropc <- err2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *testDiscPeer) NotifyDepth(po uint8) error {
|
func (d *testDiscPeer) NotifyDepth(po uint8) error {
|
||||||
key := binStr(self)
|
key := binStr(d)
|
||||||
self.lock.Lock()
|
d.lock.Lock()
|
||||||
defer self.lock.Unlock()
|
defer d.lock.Unlock()
|
||||||
self.notifications[key] = po
|
d.notifications[key] = po
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *testDiscPeer) NotifyPeer(p OverlayAddr, po uint8) error {
|
func (d *testDiscPeer) NotifyPeer(p OverlayAddr, po uint8) error {
|
||||||
key := binStr(self)
|
key := binStr(d)
|
||||||
key += binStr(p)
|
key += binStr(p)
|
||||||
self.lock.Lock()
|
d.lock.Lock()
|
||||||
defer self.lock.Unlock()
|
defer d.lock.Unlock()
|
||||||
log.Trace(fmt.Sprintf("key %v=>%v", key, po))
|
log.Trace(fmt.Sprintf("key %v=>%v", key, po))
|
||||||
self.notifications[key] = po
|
d.notifications[key] = po
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -432,31 +432,31 @@ func TestPruning(t *testing.T) {
|
||||||
func TestKademliaHiveString(t *testing.T) {
|
func TestKademliaHiveString(t *testing.T) {
|
||||||
k := newTestKademlia("00000000").On("01000000", "00100000").Register("10000000", "10000001")
|
k := newTestKademlia("00000000").On("01000000", "00100000").Register("10000000", "10000001")
|
||||||
h := k.String()
|
h := k.String()
|
||||||
expH := "\n=========================================================================\nMon Feb 27 12:10:28 UTC 2017 KΛÐΞMLIΛ hive: queen's address: 000000\npopulation: 2 (4), MinProxBinSize: 2, MinBinSize: 1, MaxBinSize: 4\n============ DEPTH: 0 ==========================================\n000 0 | 2 8100 (0) 8000 (0)\n001 1 4000 | 1 4000 (0)\n002 1 2000 | 1 2000 (0)\n003 0 | 0\n004 0 | 0\n005 0 | 0\n006 0 | 0\n007 0 | 0\n========================================================================="
|
expH := "\n=========================================================================\nMon Feb 27 12:10:28 UTC 2017 KΛÐΞMLIΛ hive: queen's address: 000000\npopulation: 2 (4), MinProxBinSize: 2, MinBinSize: 1, MaxBinSize: 4\n000 0 | 2 8100 (0) 8000 (0)\n============ DEPTH: 1 ==========================================\n001 1 4000 | 1 4000 (0)\n002 1 2000 | 1 2000 (0)\n003 0 | 0\n004 0 | 0\n005 0 | 0\n006 0 | 0\n007 0 | 0\n========================================================================="
|
||||||
if expH[100:] != h[100:] {
|
if expH[100:] != h[100:] {
|
||||||
t.Fatalf("incorrect hive output. expected %v, got %v", expH, h)
|
t.Fatalf("incorrect hive output. expected %v, got %v", expH, h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *testKademlia) checkNotifications(npeers []*testPeerNotification, nprox []*testDepthNotification) error {
|
func (k *testKademlia) checkNotifications(npeers []*testPeerNotification, nprox []*testDepthNotification) error {
|
||||||
for _, pn := range npeers {
|
for _, pn := range npeers {
|
||||||
key := pn.rec + pn.addr
|
key := pn.rec + pn.addr
|
||||||
po, found := self.notifications[key]
|
po, found := k.notifications[key]
|
||||||
if !found || pn.po != po {
|
if !found || pn.po != po {
|
||||||
return fmt.Errorf("%v, expected to have notified %v about peer %v (%v)", key, pn.rec, pn.addr, pn.po)
|
return fmt.Errorf("%v, expected to have notified %v about peer %v (%v)", key, pn.rec, pn.addr, pn.po)
|
||||||
}
|
}
|
||||||
delete(self.notifications, key)
|
delete(k.notifications, key)
|
||||||
}
|
}
|
||||||
for _, pn := range nprox {
|
for _, pn := range nprox {
|
||||||
key := pn.rec
|
key := pn.rec
|
||||||
po, found := self.notifications[key]
|
po, found := k.notifications[key]
|
||||||
if !found || pn.po != po {
|
if !found || pn.po != po {
|
||||||
return fmt.Errorf("expected to have notified %v about new prox limit %v", pn.rec, pn.po)
|
return fmt.Errorf("expected to have notified %v about new prox limit %v", pn.rec, pn.po)
|
||||||
}
|
}
|
||||||
delete(self.notifications, key)
|
delete(k.notifications, key)
|
||||||
}
|
}
|
||||||
if len(self.notifications) > 0 {
|
if len(k.notifications) > 0 {
|
||||||
return fmt.Errorf("%v unexpected notifications", len(self.notifications))
|
return fmt.Errorf("%v unexpected notifications", len(k.notifications))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NetworkId = 322 // BZZ in l33t
|
NetworkID = 322 // BZZ in l33t
|
||||||
ProtocolMaxMsgSize = 10 * 1024 * 1024
|
ProtocolMaxMsgSize = 10 * 1024 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BzzHandshakeSpec is the spec of the generic swarm handshake
|
||||||
var BzzHandshakeSpec = &protocols.Spec{
|
var BzzHandshakeSpec = &protocols.Spec{
|
||||||
Name: "bzz",
|
Name: "bzz",
|
||||||
Version: 1,
|
Version: 1,
|
||||||
|
|
@ -211,7 +212,7 @@ func (b *Bzz) getHandshake(peerID discover.NodeID) *bzzHandshake {
|
||||||
if !ok {
|
if !ok {
|
||||||
handshake = &bzzHandshake{
|
handshake = &bzzHandshake{
|
||||||
Version: uint64(BzzHandshakeSpec.Version),
|
Version: uint64(BzzHandshakeSpec.Version),
|
||||||
NetworkId: uint64(NetworkId),
|
NetworkID: uint64(NetworkID),
|
||||||
Addr: b.localAddr,
|
Addr: b.localAddr,
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
@ -250,12 +251,12 @@ func (self *bzzPeer) LastActive() time.Time {
|
||||||
Handshake
|
Handshake
|
||||||
|
|
||||||
* Version: 8 byte integer version of the protocol
|
* Version: 8 byte integer version of the protocol
|
||||||
* NetworkId: 8 byte integer network identifier
|
* NetworkID: 8 byte integer network identifier
|
||||||
* Addr: the address advertised by the node including underlay and overlay connecctions
|
* Addr: the address advertised by the node including underlay and overlay connecctions
|
||||||
*/
|
*/
|
||||||
type bzzHandshake struct {
|
type bzzHandshake struct {
|
||||||
Version uint64
|
Version uint64
|
||||||
NetworkId uint64
|
NetworkID uint64
|
||||||
Addr *bzzAddr
|
Addr *bzzAddr
|
||||||
|
|
||||||
// peerAddr is the address received in the peer handshake
|
// peerAddr is the address received in the peer handshake
|
||||||
|
|
@ -266,7 +267,7 @@ type bzzHandshake struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *bzzHandshake) String() string {
|
func (self *bzzHandshake) String() string {
|
||||||
return fmt.Sprintf("Handshake: Version: %v, NetworkId: %v, Addr: %v", self.Version, self.NetworkId, self.Addr)
|
return fmt.Sprintf("Handshake: Version: %v, NetworkID: %v, Addr: %v", self.Version, self.NetworkID, self.Addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
const bzzHandshakeTimeout = time.Second
|
const bzzHandshakeTimeout = time.Second
|
||||||
|
|
@ -284,8 +285,8 @@ func (self *bzzHandshake) Perform(p *p2p.Peer, rw p2p.MsgReadWriter) (err error)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rhs := hs.(*bzzHandshake)
|
rhs := hs.(*bzzHandshake)
|
||||||
if rhs.NetworkId != self.NetworkId {
|
if rhs.NetworkID != self.NetworkID {
|
||||||
return fmt.Errorf("network id mismatch %d (!= %d)", rhs.NetworkId, self.NetworkId)
|
return fmt.Errorf("network id mismatch %d (!= %d)", rhs.NetworkID, self.NetworkID)
|
||||||
}
|
}
|
||||||
if rhs.Version != self.Version {
|
if rhs.Version != self.Version {
|
||||||
return fmt.Errorf("version mismatch %d (!= %d)", rhs.Version, self.Version)
|
return fmt.Errorf("version mismatch %d (!= %d)", rhs.Version, self.Version)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,19 @@
|
||||||
|
// Copyright 2016 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -140,12 +156,12 @@ func (s *bzzTester) runHandshakes(ids ...discover.NodeID) {
|
||||||
func correctBzzHandshake(addr *bzzAddr) *bzzHandshake {
|
func correctBzzHandshake(addr *bzzAddr) *bzzHandshake {
|
||||||
return &bzzHandshake{
|
return &bzzHandshake{
|
||||||
Version: 0,
|
Version: 0,
|
||||||
NetworkId: 322,
|
NetworkID: 322,
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBzzHandshakeNetworkIdMismatch(t *testing.T) {
|
func TestBzzHandshakeNetworkIDMismatch(t *testing.T) {
|
||||||
pp := p2ptest.NewTestPeerPool()
|
pp := p2ptest.NewTestPeerPool()
|
||||||
addr := RandomAddr()
|
addr := RandomAddr()
|
||||||
s := newBzzTester(t, 1, addr, pp, nil, nil)
|
s := newBzzTester(t, 1, addr, pp, nil, nil)
|
||||||
|
|
@ -154,7 +170,7 @@ func TestBzzHandshakeNetworkIdMismatch(t *testing.T) {
|
||||||
id := s.IDs[0]
|
id := s.IDs[0]
|
||||||
s.testHandshake(
|
s.testHandshake(
|
||||||
correctBzzHandshake(addr),
|
correctBzzHandshake(addr),
|
||||||
&bzzHandshake{Version: 0, NetworkId: 321, Addr: NewAddrFromNodeID(id)},
|
&bzzHandshake{Version: 0, NetworkID: 321, Addr: NewAddrFromNodeID(id)},
|
||||||
&p2ptest.Disconnect{Peer: id, Error: fmt.Errorf("network id mismatch 321 (!= 322)")},
|
&p2ptest.Disconnect{Peer: id, Error: fmt.Errorf("network id mismatch 321 (!= 322)")},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +184,7 @@ func TestBzzHandshakeVersionMismatch(t *testing.T) {
|
||||||
id := s.IDs[0]
|
id := s.IDs[0]
|
||||||
s.testHandshake(
|
s.testHandshake(
|
||||||
correctBzzHandshake(addr),
|
correctBzzHandshake(addr),
|
||||||
&bzzHandshake{Version: 1, NetworkId: 322, Addr: NewAddrFromNodeID(id)},
|
&bzzHandshake{Version: 1, NetworkID: 322, Addr: NewAddrFromNodeID(id)},
|
||||||
&p2ptest.Disconnect{Peer: id, Error: fmt.Errorf("version mismatch 1 (!= 0)")},
|
&p2ptest.Disconnect{Peer: id, Error: fmt.Errorf("version mismatch 1 (!= 0)")},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -182,6 +198,6 @@ func TestBzzHandshakeSuccess(t *testing.T) {
|
||||||
id := s.IDs[0]
|
id := s.IDs[0]
|
||||||
s.testHandshake(
|
s.testHandshake(
|
||||||
correctBzzHandshake(addr),
|
correctBzzHandshake(addr),
|
||||||
&bzzHandshake{Version: 0, NetworkId: 322, Addr: NewAddrFromNodeID(id)},
|
&bzzHandshake{Version: 0, NetworkID: 322, Addr: NewAddrFromNodeID(id)},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,193 +0,0 @@
|
||||||
package network
|
|
||||||
|
|
||||||
//
|
|
||||||
// import (
|
|
||||||
// "fmt"
|
|
||||||
// "strings"
|
|
||||||
// "sync"
|
|
||||||
//
|
|
||||||
// "github.com/ethereum/go-ethereum/log"
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// const orders = 8
|
|
||||||
//
|
|
||||||
// type testOverlay struct {
|
|
||||||
// mu sync.Mutex
|
|
||||||
// addr []byte
|
|
||||||
// pos [][]OverlayAddr
|
|
||||||
// posMap map[string]OverlayAddr
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// type testPeerAddr struct {
|
|
||||||
// Addr
|
|
||||||
// Peer
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testPeerAddr) Address() []byte {
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testPeerAddr) Update(a OverlayAddr) OverlayAddr {
|
|
||||||
// return self
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testPeerAddr) On(p OverlayConn) OverlayConn {
|
|
||||||
// return self
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testPeerAddr) Off() OverlayAddr {
|
|
||||||
// return self
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testOverlay) Register(peers chan OverlayAddr) error {
|
|
||||||
// self.mu.Lock()
|
|
||||||
// defer self.mu.Unlock()
|
|
||||||
// var nas []OverlayAddr
|
|
||||||
// for a := range peers {
|
|
||||||
// nas = append(nas, a)
|
|
||||||
// }
|
|
||||||
// return self.register(nas...)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testOverlay) BaseAddr() []byte {
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testOverlay) register(nas ...OverlayAddr) error {
|
|
||||||
// for _, na := range nas {
|
|
||||||
// addr := na.Address()
|
|
||||||
// if self.posMap[string(addr)] != nil {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// self.posMap[string(addr)] = na
|
|
||||||
// o := order(addr)
|
|
||||||
// log.Trace(fmt.Sprintf("PO: %v, orders: %v", o, orders))
|
|
||||||
// self.pos[o] = append(self.pos[o], na)
|
|
||||||
// }
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func order(addr []byte) int {
|
|
||||||
// return int(addr[0]) / 32
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testOverlay) On(n OverlayConn) {
|
|
||||||
// self.mu.Lock()
|
|
||||||
// defer self.mu.Unlock()
|
|
||||||
// addr := n.Address()
|
|
||||||
// na := self.posMap[string(addr)]
|
|
||||||
// if na == nil {
|
|
||||||
// self.register(n)
|
|
||||||
// na = self.posMap[string(addr)]
|
|
||||||
// } else if na.Peer != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// log.Trace(fmt.Sprintf("Online: %x", addr[:4]))
|
|
||||||
// na.Peer = n
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testOverlay) Off(n OverlayConn) {
|
|
||||||
// self.mu.Lock()
|
|
||||||
// defer self.mu.Unlock()
|
|
||||||
// addr := n.Over()
|
|
||||||
// na := self.posMap[string(addr)]
|
|
||||||
// if na == nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// delete(self.posMap, string(addr))
|
|
||||||
// na.Peer = nil
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // caller must hold the lock
|
|
||||||
// func (self *testOverlay) on(po []*testPeerAddr) (nodes []OverlayConn) {
|
|
||||||
// for _, na := range po {
|
|
||||||
// if na.Peer != nil {
|
|
||||||
// nodes = append(nodes, na)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return nodes
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // caller must hold the lock
|
|
||||||
// func (self *testOverlay) off(po []*testPeerAddr) (nas []OverlayAddr) {
|
|
||||||
// for _, na := range po {
|
|
||||||
// if na.Peer == (*bzzPeer)(nil) {
|
|
||||||
// nas = append(nas, Addr(na))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return nas
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testOverlay) EachConn(base []byte, o int, f func(OverlayConn, int, bool) bool) {
|
|
||||||
// for i := o; i < len(self.pos); i++ {
|
|
||||||
// for _, na := range self.pos[i] {
|
|
||||||
// if na.Peer != nil {
|
|
||||||
// if !f(na, o, false) {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testOverlay) EachAddr(base []byte, o int, f func(OverlayAddr, int) bool) {
|
|
||||||
// for i := o; i < len(self.pos); i++ {
|
|
||||||
// for _, na := range self.pos[i] {
|
|
||||||
// if !f(na, i) {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testOverlay) SuggestPeer() (OverlayAddr, int, bool) {
|
|
||||||
// self.mu.Lock()
|
|
||||||
// defer self.mu.Unlock()
|
|
||||||
// for i, po := range self.pos {
|
|
||||||
// ons := self.on(po)
|
|
||||||
// if len(ons) < 2 {
|
|
||||||
// offs := self.off(po)
|
|
||||||
// if len(offs) > 0 {
|
|
||||||
// log.Trace(fmt.Sprintf("node %v is off", offs[0]))
|
|
||||||
// return offs[0], i, true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return nil, 0, true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (self *testOverlay) String() string {
|
|
||||||
// self.mu.Lock()
|
|
||||||
// defer self.mu.Unlock()
|
|
||||||
// var t []string
|
|
||||||
// var ons, offs int
|
|
||||||
// var ns []Peer
|
|
||||||
// var nas []Addr
|
|
||||||
// for o, po := range self.pos {
|
|
||||||
// var row []string
|
|
||||||
// ns = self.on(po)
|
|
||||||
// nas = self.off(po)
|
|
||||||
// ons = len(ns)
|
|
||||||
// for _, n := range ns {
|
|
||||||
// addr := n.Over()
|
|
||||||
// row = append(row, fmt.Sprintf("%x", addr[:4]))
|
|
||||||
// }
|
|
||||||
// row = append(row, "|")
|
|
||||||
// offs = len(nas)
|
|
||||||
// for _, na := range nas {
|
|
||||||
// addr := na.Over()
|
|
||||||
// row = append(row, fmt.Sprintf("%x", addr[:4]))
|
|
||||||
// }
|
|
||||||
// t = append(t, fmt.Sprintf("%v: (%v/%v) %v", o, ons, offs, strings.Join(row, " ")))
|
|
||||||
// }
|
|
||||||
// return strings.Join(t, "\n")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func NewTestOverlay(addr []byte) *testOverlay {
|
|
||||||
// return &testOverlay{
|
|
||||||
// addr: addr,
|
|
||||||
// posMap: make(map[string]*testPeerAddr),
|
|
||||||
// pos: make([][]*testPeerAddr, orders),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
Loading…
Reference in a new issue