Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
9f38ef5d
Commit
9f38ef5d
authored
May 21, 2015
by
Felix Lange
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
p2p/discover: add ReadRandomNodes
parent
64564da2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
83 additions
and
1 deletion
+83
-1
table.go
p2p/discover/table.go
+49
-0
table_test.go
p2p/discover/table_test.go
+34
-1
No files found.
p2p/discover/table.go
View file @
9f38ef5d
...
@@ -8,6 +8,7 @@ package discover
...
@@ -8,6 +8,7 @@ package discover
import
(
import
(
"crypto/rand"
"crypto/rand"
"encoding/binary"
"net"
"net"
"sort"
"sort"
"sync"
"sync"
...
@@ -90,10 +91,58 @@ func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string
...
@@ -90,10 +91,58 @@ func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string
}
}
// Self returns the local node.
// Self returns the local node.
// The returned node should not be modified by the caller.
func
(
tab
*
Table
)
Self
()
*
Node
{
func
(
tab
*
Table
)
Self
()
*
Node
{
return
tab
.
self
return
tab
.
self
}
}
// ReadRandomNodes fills the given slice with random nodes from the
// table. It will not write the same node more than once. The nodes in
// the slice are copies and can be modified by the caller.
func
(
tab
*
Table
)
ReadRandomNodes
(
buf
[]
*
Node
)
(
n
int
)
{
tab
.
mutex
.
Lock
()
defer
tab
.
mutex
.
Unlock
()
// TODO: tree-based buckets would help here
// Find all non-empty buckets and get a fresh slice of their entries.
var
buckets
[][]
*
Node
for
_
,
b
:=
range
tab
.
buckets
{
if
len
(
b
.
entries
)
>
0
{
buckets
=
append
(
buckets
,
b
.
entries
[
:
])
}
}
if
len
(
buckets
)
==
0
{
return
0
}
// Shuffle the buckets.
for
i
:=
uint32
(
len
(
buckets
))
-
1
;
i
>
0
;
i
--
{
j
:=
randUint
(
i
)
buckets
[
i
],
buckets
[
j
]
=
buckets
[
j
],
buckets
[
i
]
}
// Move head of each bucket into buf, removing buckets that become empty.
var
i
,
j
int
for
;
i
<
len
(
buf
);
i
,
j
=
i
+
1
,
(
j
+
1
)
%
len
(
buckets
)
{
b
:=
buckets
[
j
]
buf
[
i
]
=
&
(
*
b
[
0
])
buckets
[
j
]
=
b
[
1
:
]
if
len
(
b
)
==
1
{
buckets
=
append
(
buckets
[
:
j
],
buckets
[
j
+
1
:
]
...
)
}
if
len
(
buckets
)
==
0
{
break
}
}
return
i
+
1
}
func
randUint
(
max
uint32
)
uint32
{
if
max
==
0
{
return
0
}
var
b
[
4
]
byte
rand
.
Read
(
b
[
:
])
return
binary
.
BigEndian
.
Uint32
(
b
[
:
])
%
max
}
// Close terminates the network listener and flushes the node database.
// Close terminates the network listener and flushes the node database.
func
(
tab
*
Table
)
Close
()
{
func
(
tab
*
Table
)
Close
()
{
tab
.
net
.
close
()
tab
.
net
.
close
()
...
...
p2p/discover/table_test.go
View file @
9f38ef5d
...
@@ -210,6 +210,36 @@ func TestTable_closest(t *testing.T) {
...
@@ -210,6 +210,36 @@ func TestTable_closest(t *testing.T) {
}
}
}
}
func
TestTable_ReadRandomNodesGetAll
(
t
*
testing
.
T
)
{
cfg
:=
&
quick
.
Config
{
MaxCount
:
200
,
Rand
:
quickrand
,
Values
:
func
(
args
[]
reflect
.
Value
,
rand
*
rand
.
Rand
)
{
args
[
0
]
=
reflect
.
ValueOf
(
make
([]
*
Node
,
rand
.
Intn
(
1000
)))
},
}
test
:=
func
(
buf
[]
*
Node
)
bool
{
tab
:=
newTable
(
nil
,
NodeID
{},
&
net
.
UDPAddr
{},
""
)
for
i
:=
0
;
i
<
len
(
buf
);
i
++
{
ld
:=
quickrand
.
Intn
(
len
(
tab
.
buckets
))
tab
.
add
([]
*
Node
{
nodeAtDistance
(
tab
.
self
.
sha
,
ld
)})
}
gotN
:=
tab
.
ReadRandomNodes
(
buf
)
if
gotN
!=
tab
.
len
()
{
t
.
Errorf
(
"wrong number of nodes, got %d, want %d"
,
gotN
,
tab
.
len
())
return
false
}
if
hasDuplicates
(
buf
[
:
gotN
])
{
t
.
Errorf
(
"result contains duplicates"
)
return
false
}
return
true
}
if
err
:=
quick
.
Check
(
test
,
cfg
);
err
!=
nil
{
t
.
Error
(
err
)
}
}
type
closeTest
struct
{
type
closeTest
struct
{
Self
NodeID
Self
NodeID
Target
common
.
Hash
Target
common
.
Hash
...
@@ -517,7 +547,10 @@ func (n *preminedTestnet) mine(target NodeID) {
...
@@ -517,7 +547,10 @@ func (n *preminedTestnet) mine(target NodeID) {
func
hasDuplicates
(
slice
[]
*
Node
)
bool
{
func
hasDuplicates
(
slice
[]
*
Node
)
bool
{
seen
:=
make
(
map
[
NodeID
]
bool
)
seen
:=
make
(
map
[
NodeID
]
bool
)
for
_
,
e
:=
range
slice
{
for
i
,
e
:=
range
slice
{
if
e
==
nil
{
panic
(
fmt
.
Sprintf
(
"nil *Node at %d"
,
i
))
}
if
seen
[
e
.
ID
]
{
if
seen
[
e
.
ID
]
{
return
true
return
true
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment