eth/downloader: retry state requests on timeout

This commit is contained in:
Felix Lange 2017-05-30 12:02:46 +02:00 committed by Péter Szilágyi
parent c7e5270c70
commit 420935469d
No known key found for this signature in database
GPG key ID: E9AE538CEDF8293D

View file

@ -40,6 +40,10 @@ type stateReq struct {
response [][]byte // the response. this is nil for timed-out requests. response [][]byte // the response. this is nil for timed-out requests.
} }
func (req *stateReq) timedOut() bool {
return req.response == nil
}
type stateSyncStats struct { type stateSyncStats struct {
done uint64 // number of entries pulled done uint64 // number of entries pulled
pending uint64 // number of pending entries pending uint64 // number of pending entries
@ -219,6 +223,7 @@ func (s *stateSync) loop() error {
return errCancelStateFetch return errCancelStateFetch
case req := <-s.deliver: case req := <-s.deliver:
// response or timeout // response or timeout
log.Trace("Received node data response", "peer", req.peer.id, "count", len(req.items), "timeout", req.timedOut())
req.peer.SetNodeDataIdle(len(req.response)) req.peer.SetNodeDataIdle(len(req.response))
procStart := time.Now() procStart := time.Now()
n, err := s.process(req) n, err := s.process(req)
@ -226,7 +231,7 @@ func (s *stateSync) loop() error {
log.Warn("Node data write error", "err", err) log.Warn("Node data write error", "err", err)
return err return err
} }
if len(req.items) == 1 && req.response == nil { if len(req.items) == 1 && req.timedOut() {
log.Warn("Node data timeout, dropping peer", "peer", req.peer.id) log.Warn("Node data timeout, dropping peer", "peer", req.peer.id)
s.d.dropPeer(req.peer.id) s.d.dropPeer(req.peer.id)
} }
@ -303,6 +308,11 @@ func (s *stateSync) process(req *stateReq) (nproc int, err error) {
} }
// Put unfulfilled tasks back. // Put unfulfilled tasks back.
for hash, task := range req.tasks { for hash, task := range req.tasks {
if len(req.response) > 0 || req.timedOut() {
// Ensure that the item will be retried if the response contained some data or
// timed out.
delete(task.triedPeers, req.peer.id)
}
if npeers := s.d.peers.Len(); len(task.triedPeers) >= npeers { if npeers := s.d.peers.Len(); len(task.triedPeers) >= npeers {
return nproc, fmt.Errorf("state node %s failed with all peers (%d tries, %d peers)", hash.TerminalString(), len(task.triedPeers), npeers) return nproc, fmt.Errorf("state node %s failed with all peers (%d tries, %d peers)", hash.TerminalString(), len(task.triedPeers), npeers)
} }