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
bd5720f4
Commit
bd5720f4
authored
May 08, 2015
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
eth, eth/downloader: handle sync errors a bit more gracefully
parent
9d188f73
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
48 additions
and
48 deletions
+48
-48
downloader.go
eth/downloader/downloader.go
+13
-15
downloader_test.go
eth/downloader/downloader_test.go
+3
-3
handler.go
eth/handler.go
+4
-4
sync.go
eth/sync.go
+28
-26
No files found.
eth/downloader/downloader.go
View file @
bd5720f4
...
@@ -24,12 +24,12 @@ var (
...
@@ -24,12 +24,12 @@ var (
blockTtl
=
20
*
time
.
Second
// The amount of time it takes for a block request to time out
blockTtl
=
20
*
time
.
Second
// The amount of time it takes for a block request to time out
errLowTd
=
errors
.
New
(
"peer's TD is too low"
)
errLowTd
=
errors
.
New
(
"peer's TD is too low"
)
e
rrBusy
=
errors
.
New
(
"busy"
)
E
rrBusy
=
errors
.
New
(
"busy"
)
errUnknownPeer
=
errors
.
New
(
"peer's unknown or unhealthy"
)
errUnknownPeer
=
errors
.
New
(
"peer's unknown or unhealthy"
)
E
rrBadPeer
=
errors
.
New
(
"action from bad peer ignored"
)
e
rrBadPeer
=
errors
.
New
(
"action from bad peer ignored"
)
errNoPeers
=
errors
.
New
(
"no peers to keep download active"
)
errNoPeers
=
errors
.
New
(
"no peers to keep download active"
)
errPendingQueue
=
errors
.
New
(
"pending items in queue"
)
errPendingQueue
=
errors
.
New
(
"pending items in queue"
)
e
rrTimeout
=
errors
.
New
(
"timeout"
)
E
rrTimeout
=
errors
.
New
(
"timeout"
)
errEmptyHashSet
=
errors
.
New
(
"empty hash set by peer"
)
errEmptyHashSet
=
errors
.
New
(
"empty hash set by peer"
)
errPeersUnavailable
=
errors
.
New
(
"no peers available or all peers tried for block download process"
)
errPeersUnavailable
=
errors
.
New
(
"no peers available or all peers tried for block download process"
)
errAlreadyInPool
=
errors
.
New
(
"hash already in pool"
)
errAlreadyInPool
=
errors
.
New
(
"hash already in pool"
)
...
@@ -68,7 +68,7 @@ type Downloader struct {
...
@@ -68,7 +68,7 @@ type Downloader struct {
getBlock
getBlockFn
getBlock
getBlockFn
// Status
// Status
synchroni
z
ing
int32
synchroni
s
ing
int32
// Channels
// Channels
newPeerCh
chan
*
peer
newPeerCh
chan
*
peer
...
@@ -119,15 +119,15 @@ func (d *Downloader) UnregisterPeer(id string) {
...
@@ -119,15 +119,15 @@ func (d *Downloader) UnregisterPeer(id string) {
delete
(
d
.
peers
,
id
)
delete
(
d
.
peers
,
id
)
}
}
// Synchroni
ze will select the peer and use it for synchroniz
ing. If an empty string is given
// Synchroni
se will select the peer and use it for synchronis
ing. If an empty string is given
// it will use the best peer possible and synchronize if it's TD is higher than our own. If any of the
// it will use the best peer possible and synchronize if it's TD is higher than our own. If any of the
// checks fail an error will be returned. This method is synchronous
// checks fail an error will be returned. This method is synchronous
func
(
d
*
Downloader
)
Synchroni
z
e
(
id
string
,
hash
common
.
Hash
)
error
{
func
(
d
*
Downloader
)
Synchroni
s
e
(
id
string
,
hash
common
.
Hash
)
error
{
// Make sure only one goroutine is ever allowed past this point at once
// Make sure only one goroutine is ever allowed past this point at once
if
!
atomic
.
CompareAndSwapInt32
(
&
d
.
synchroni
z
ing
,
0
,
1
)
{
if
!
atomic
.
CompareAndSwapInt32
(
&
d
.
synchroni
s
ing
,
0
,
1
)
{
return
nil
return
ErrBusy
}
}
defer
atomic
.
StoreInt32
(
&
d
.
synchroni
z
ing
,
0
)
defer
atomic
.
StoreInt32
(
&
d
.
synchroni
s
ing
,
0
)
// Abort if the queue still contains some leftover data
// Abort if the queue still contains some leftover data
if
_
,
cached
:=
d
.
queue
.
Size
();
cached
>
0
{
if
_
,
cached
:=
d
.
queue
.
Size
();
cached
>
0
{
...
@@ -272,7 +272,7 @@ out:
...
@@ -272,7 +272,7 @@ out:
// the zero hash.
// the zero hash.
if
p
==
nil
||
(
hash
==
common
.
Hash
{})
{
if
p
==
nil
||
(
hash
==
common
.
Hash
{})
{
d
.
queue
.
Reset
()
d
.
queue
.
Reset
()
return
e
rrTimeout
return
E
rrTimeout
}
}
// set p to the active peer. this will invalidate any hashes that may be returned
// set p to the active peer. this will invalidate any hashes that may be returned
...
@@ -282,7 +282,7 @@ out:
...
@@ -282,7 +282,7 @@ out:
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Hash fetching switched to new peer(%s)
\n
"
,
p
.
id
)
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Hash fetching switched to new peer(%s)
\n
"
,
p
.
id
)
}
}
}
}
glog
.
V
(
logger
.
De
tail
)
.
Infof
(
"Downloaded hashes (%d) in %v
\n
"
,
d
.
queue
.
Pending
(),
time
.
Since
(
start
))
glog
.
V
(
logger
.
De
bug
)
.
Infof
(
"Downloaded hashes (%d) in %v
\n
"
,
d
.
queue
.
Pending
(),
time
.
Since
(
start
))
return
nil
return
nil
}
}
...
@@ -384,7 +384,6 @@ out:
...
@@ -384,7 +384,6 @@ out:
}
}
}
}
}
}
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"Downloaded block(s) in"
,
time
.
Since
(
start
))
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"Downloaded block(s) in"
,
time
.
Since
(
start
))
return
nil
return
nil
...
@@ -404,11 +403,10 @@ func (d *Downloader) AddHashes(id string, hashes []common.Hash) error {
...
@@ -404,11 +403,10 @@ func (d *Downloader) AddHashes(id string, hashes []common.Hash) error {
return
fmt
.
Errorf
(
"received hashes from %s while active peer is %s"
,
id
,
d
.
activePeer
)
return
fmt
.
Errorf
(
"received hashes from %s while active peer is %s"
,
id
,
d
.
activePeer
)
}
}
if
glog
.
V
(
logger
.
De
tail
)
&&
len
(
hashes
)
!=
0
{
if
glog
.
V
(
logger
.
De
bug
)
&&
len
(
hashes
)
!=
0
{
from
,
to
:=
hashes
[
0
],
hashes
[
len
(
hashes
)
-
1
]
from
,
to
:=
hashes
[
0
],
hashes
[
len
(
hashes
)
-
1
]
glog
.
Infof
(
"adding %d (T=%d) hashes [ %x / %x ] from: %s
\n
"
,
len
(
hashes
),
d
.
queue
.
Pending
(),
from
[
:
4
],
to
[
:
4
],
id
)
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"adding %d (T=%d) hashes [ %x / %x ] from: %s
\n
"
,
len
(
hashes
),
d
.
queue
.
Pending
(),
from
[
:
4
],
to
[
:
4
],
id
)
}
}
d
.
hashCh
<-
hashPack
{
id
,
hashes
}
d
.
hashCh
<-
hashPack
{
id
,
hashes
}
return
nil
return
nil
...
...
eth/downloader/downloader_test.go
View file @
bd5720f4
...
@@ -61,7 +61,7 @@ func newTester(t *testing.T, hashes []common.Hash, blocks map[common.Hash]*types
...
@@ -61,7 +61,7 @@ func newTester(t *testing.T, hashes []common.Hash, blocks map[common.Hash]*types
func
(
dl
*
downloadTester
)
sync
(
peerId
string
,
hash
common
.
Hash
)
error
{
func
(
dl
*
downloadTester
)
sync
(
peerId
string
,
hash
common
.
Hash
)
error
{
dl
.
activePeerId
=
peerId
dl
.
activePeerId
=
peerId
return
dl
.
downloader
.
Synchroni
z
e
(
peerId
,
hash
)
return
dl
.
downloader
.
Synchroni
s
e
(
peerId
,
hash
)
}
}
func
(
dl
*
downloadTester
)
hasBlock
(
hash
common
.
Hash
)
bool
{
func
(
dl
*
downloadTester
)
hasBlock
(
hash
common
.
Hash
)
bool
{
...
@@ -217,13 +217,13 @@ func TestThrottling(t *testing.T) {
...
@@ -217,13 +217,13 @@ func TestThrottling(t *testing.T) {
}
}
}()
}()
// Synchroni
z
e the two threads and verify
// Synchroni
s
e the two threads and verify
err
:=
<-
errc
err
:=
<-
errc
done
<-
struct
{}{}
done
<-
struct
{}{}
<-
done
<-
done
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"failed to synchroni
z
e blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchroni
s
e blocks: %v"
,
err
)
}
}
if
len
(
took
)
!=
targetBlocks
{
if
len
(
took
)
!=
targetBlocks
{
t
.
Fatalf
(
"downloaded block mismatch: have %v, want %v"
,
len
(
took
),
targetBlocks
)
t
.
Fatalf
(
"downloaded block mismatch: have %v, want %v"
,
len
(
took
),
targetBlocks
)
...
...
eth/handler.go
View file @
bd5720f4
...
@@ -19,9 +19,9 @@ import (
...
@@ -19,9 +19,9 @@ import (
)
)
const
(
const
(
peerCountTimeout
=
12
*
time
.
Second
// Amount of time it takes for the peer handler to ignore minDesiredPeerCount
forceSyncCycle
=
10
*
time
.
Second
// Time interval to force syncs, even if few peers are available
blockProc
Timer
=
500
*
time
.
Millisecond
blockProc
Cycle
=
500
*
time
.
Millisecond
// Time interval to check for new blocks to process
minDesiredPeerCount
=
5
// Amount of peers desired to start syncing
minDesiredPeerCount
=
5
// Amount of peers desired to start syncing
blockProcAmount
=
256
blockProcAmount
=
256
)
)
...
@@ -324,7 +324,7 @@ func (self *ProtocolManager) handleMsg(p *peer) error {
...
@@ -324,7 +324,7 @@ func (self *ProtocolManager) handleMsg(p *peer) error {
}
}
self
.
BroadcastBlock
(
hash
,
request
.
Block
)
self
.
BroadcastBlock
(
hash
,
request
.
Block
)
}
else
{
}
else
{
go
self
.
synchroni
z
e
(
p
)
go
self
.
synchroni
s
e
(
p
)
}
}
default
:
default
:
return
errResp
(
ErrInvalidMsgCode
,
"%v"
,
msg
.
Code
)
return
errResp
(
ErrInvalidMsgCode
,
"%v"
,
msg
.
Code
)
...
...
eth/sync.go
View file @
bd5720f4
...
@@ -12,10 +12,8 @@ import (
...
@@ -12,10 +12,8 @@ import (
// Sync contains all synchronisation code for the eth protocol
// Sync contains all synchronisation code for the eth protocol
func
(
pm
*
ProtocolManager
)
update
()
{
func
(
pm
*
ProtocolManager
)
update
()
{
// itimer is used to determine when to start ignoring `minDesiredPeerCount`
forceSync
:=
time
.
Tick
(
forceSyncCycle
)
itimer
:=
time
.
NewTimer
(
peerCountTimeout
)
blockProc
:=
time
.
Tick
(
blockProcCycle
)
// btimer is used for picking of blocks from the downloader
btimer
:=
time
.
Tick
(
blockProcTimer
)
for
{
for
{
select
{
select
{
...
@@ -24,27 +22,22 @@ func (pm *ProtocolManager) update() {
...
@@ -24,27 +22,22 @@ func (pm *ProtocolManager) update() {
if
len
(
pm
.
peers
)
<
minDesiredPeerCount
{
if
len
(
pm
.
peers
)
<
minDesiredPeerCount
{
break
break
}
}
// Find the best peer and synchronise with it
// Find the best peer
peer
:=
getBestPeer
(
pm
.
peers
)
peer
:=
getBestPeer
(
pm
.
peers
)
if
peer
==
nil
{
if
peer
==
nil
{
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Sync attempt cancel
l
ed. No peers available"
)
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Sync attempt canceled. No peers available"
)
}
}
go
pm
.
synchronise
(
peer
)
itimer
.
Stop
()
case
<-
forceSync
:
go
pm
.
synchronize
(
peer
)
// Force a sync even if not enough peers are present
case
<-
itimer
.
C
:
// The timer will make sure that the downloader keeps an active state
// in which it attempts to always check the network for highest td peers
// Either select the peer or restart the timer if no peers could
// be selected.
if
peer
:=
getBestPeer
(
pm
.
peers
);
peer
!=
nil
{
if
peer
:=
getBestPeer
(
pm
.
peers
);
peer
!=
nil
{
go
pm
.
synchronize
(
peer
)
go
pm
.
synchronise
(
peer
)
}
else
{
itimer
.
Reset
(
5
*
time
.
Second
)
}
}
case
<-
btimer
:
case
<-
blockProc
:
// Try to pull some blocks from the downloaded
go
pm
.
processBlocks
()
go
pm
.
processBlocks
()
case
<-
pm
.
quitSync
:
case
<-
pm
.
quitSync
:
return
return
}
}
...
@@ -59,11 +52,11 @@ func (pm *ProtocolManager) processBlocks() error {
...
@@ -59,11 +52,11 @@ func (pm *ProtocolManager) processBlocks() error {
pm
.
wg
.
Add
(
1
)
pm
.
wg
.
Add
(
1
)
defer
pm
.
wg
.
Done
()
defer
pm
.
wg
.
Done
()
// Take a batch of blocks (will return nil if a previous batch has not reached the chain yet)
blocks
:=
pm
.
downloader
.
TakeBlocks
()
blocks
:=
pm
.
downloader
.
TakeBlocks
()
if
len
(
blocks
)
==
0
{
if
len
(
blocks
)
==
0
{
return
nil
return
nil
}
}
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Inserting chain with %d blocks (#%v - #%v)
\n
"
,
len
(
blocks
),
blocks
[
0
]
.
Number
(),
blocks
[
len
(
blocks
)
-
1
]
.
Number
())
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Inserting chain with %d blocks (#%v - #%v)
\n
"
,
len
(
blocks
),
blocks
[
0
]
.
Number
(),
blocks
[
len
(
blocks
)
-
1
]
.
Number
())
for
len
(
blocks
)
!=
0
&&
!
pm
.
quit
{
for
len
(
blocks
)
!=
0
&&
!
pm
.
quit
{
...
@@ -77,7 +70,7 @@ func (pm *ProtocolManager) processBlocks() error {
...
@@ -77,7 +70,7 @@ func (pm *ProtocolManager) processBlocks() error {
return
nil
return
nil
}
}
func
(
pm
*
ProtocolManager
)
synchroni
z
e
(
peer
*
peer
)
{
func
(
pm
*
ProtocolManager
)
synchroni
s
e
(
peer
*
peer
)
{
// Make sure the peer's TD is higher than our own. If not drop.
// Make sure the peer's TD is higher than our own. If not drop.
if
peer
.
td
.
Cmp
(
pm
.
chainman
.
Td
())
<=
0
{
if
peer
.
td
.
Cmp
(
pm
.
chainman
.
Td
())
<=
0
{
return
return
...
@@ -89,12 +82,21 @@ func (pm *ProtocolManager) synchronize(peer *peer) {
...
@@ -89,12 +82,21 @@ func (pm *ProtocolManager) synchronize(peer *peer) {
return
return
}
}
// Get the hashes from the peer (synchronously)
// Get the hashes from the peer (synchronously)
err
:=
pm
.
downloader
.
Synchronize
(
peer
.
id
,
peer
.
recentHash
)
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Attempting synchronisation: %v, 0x%x"
,
peer
.
id
,
peer
.
recentHash
)
if
err
!=
nil
&&
err
==
downloader
.
ErrBadPeer
{
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"removed peer from peer set due to bad action"
)
err
:=
pm
.
downloader
.
Synchronise
(
peer
.
id
,
peer
.
recentHash
)
switch
err
{
case
nil
:
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Synchronisation completed"
)
case
downloader
.
ErrBusy
:
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Synchronisation already in progress"
)
case
downloader
.
ErrTimeout
:
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Removing peer %v due to sync timeout"
,
peer
.
id
)
pm
.
removePeer
(
peer
)
pm
.
removePeer
(
peer
)
}
else
if
err
!=
nil
{
// handle error
default
:
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"error downloading:
"
,
err
)
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"Synchronisation failed: %v
"
,
err
)
}
}
}
}
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