Skip to content

Commit 45f8304

Browse files
committed
eth/downloader: fix expiration not running while fetching
1 parent 4800c94 commit 45f8304

File tree

2 files changed

+32
-34
lines changed

2 files changed

+32
-34
lines changed

eth/downloader/downloader.go

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -346,13 +346,28 @@ out:
346346
d.peers.setState(blockPack.peerId, idleState)
347347
}
348348
case <-ticker.C:
349-
// after removing bad peers make sure we actually have sufficient peer left to keep downloading
349+
// Check for bad peers. Bad peers may indicate a peer not responding
350+
// to a `getBlocks` message. A timeout of 5 seconds is set. Peers
351+
// that badly or poorly behave are removed from the peer set (not banned).
352+
// Bad peers are excluded from the available peer set and therefor won't be
353+
// reused. XXX We could re-introduce peers after X time.
354+
badPeers := d.queue.Expire(blockTtl)
355+
for _, pid := range badPeers {
356+
// XXX We could make use of a reputation system here ranking peers
357+
// in their performance
358+
// 1) Time for them to respond;
359+
// 2) Measure their speed;
360+
// 3) Amount and availability.
361+
if peer := d.peers[pid]; peer != nil {
362+
peer.demote()
363+
peer.reset()
364+
}
365+
}
366+
// After removing bad peers make sure we actually have sufficient peer left to keep downloading
350367
if len(d.peers) == 0 {
351368
d.queue.Reset()
352-
353369
return errNoPeers
354370
}
355-
356371
// If there are unrequested hashes left start fetching
357372
// from the available peers.
358373
if d.queue.Pending() > 0 {
@@ -392,25 +407,6 @@ out:
392407
// safely assume we're done. Another part of the process will check
393408
// for parent errors and will re-request anything that's missing
394409
break out
395-
} else {
396-
// Check for bad peers. Bad peers may indicate a peer not responding
397-
// to a `getBlocks` message. A timeout of 5 seconds is set. Peers
398-
// that badly or poorly behave are removed from the peer set (not banned).
399-
// Bad peers are excluded from the available peer set and therefor won't be
400-
// reused. XXX We could re-introduce peers after X time.
401-
badPeers := d.queue.Expire(blockTtl)
402-
for _, pid := range badPeers {
403-
// XXX We could make use of a reputation system here ranking peers
404-
// in their performance
405-
// 1) Time for them to respond;
406-
// 2) Measure their speed;
407-
// 3) Amount and availability.
408-
if peer := d.peers[pid]; peer != nil {
409-
peer.demote()
410-
peer.reset()
411-
}
412-
}
413-
414410
}
415411
}
416412
}

eth/downloader/queue.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
)
1313

1414
const (
15-
blockCacheLimit = 4096 // Maximum number of blocks to cache before throttling the download
15+
blockCacheLimit = 1024 // Maximum number of blocks to cache before throttling the download
1616
)
1717

1818
// fetchRequest is a currently running block retrieval operation.
@@ -28,8 +28,7 @@ type queue struct {
2828
hashQueue *prque.Prque // Priority queue of the block hashes to fetch
2929
hashCounter int // Counter indexing the added hashes to ensure retrieval order
3030

31-
pendPool map[string]*fetchRequest // Currently pending block retrieval operations
32-
pendCount int // Number of pending block fetches (to throttle the download)
31+
pendPool map[string]*fetchRequest // Currently pending block retrieval operations
3332

3433
blockPool map[common.Hash]int // Hash-set of the downloaded data blocks, mapping to cache indexes
3534
blockCache []*types.Block // Downloaded but not yet delivered blocks
@@ -58,7 +57,6 @@ func (q *queue) Reset() {
5857
q.hashCounter = 0
5958

6059
q.pendPool = make(map[string]*fetchRequest)
61-
q.pendCount = 0
6260

6361
q.blockPool = make(map[common.Hash]int)
6462
q.blockOffset = 0
@@ -106,7 +104,13 @@ func (q *queue) Throttle() bool {
106104
q.lock.RLock()
107105
defer q.lock.RUnlock()
108106

109-
return q.pendCount >= len(q.blockCache)-len(q.blockPool)
107+
// Calculate the currently in-flight block requests
108+
pending := 0
109+
for _, request := range q.pendPool {
110+
pending += len(request.Hashes)
111+
}
112+
// Throttle if more blocks are in-flight than free space in the cache
113+
return pending >= len(q.blockCache)-len(q.blockPool)
110114
}
111115

112116
// Has checks if a hash is within the download queue or not.
@@ -206,10 +210,14 @@ func (q *queue) Reserve(p *peer, max int) *fetchRequest {
206210
q.lock.Lock()
207211
defer q.lock.Unlock()
208212

209-
// Short circuit if the pool has been depleted
213+
// Short circuit if the pool has been depleted, or if the peer's already
214+
// downloading something (sanity check not to corrupt state)
210215
if q.hashQueue.Empty() {
211216
return nil
212217
}
218+
if _, ok := q.pendPool[p.id]; ok {
219+
return nil
220+
}
213221
// Retrieve a batch of hashes, skipping previously failed ones
214222
send := make(map[common.Hash]int)
215223
skip := make(map[common.Hash]int)
@@ -236,7 +244,6 @@ func (q *queue) Reserve(p *peer, max int) *fetchRequest {
236244
Time: time.Now(),
237245
}
238246
q.pendPool[p.id] = request
239-
q.pendCount += len(request.Hashes)
240247

241248
return request
242249
}
@@ -250,7 +257,6 @@ func (q *queue) Cancel(request *fetchRequest) {
250257
q.hashQueue.Push(hash, float32(index))
251258
}
252259
delete(q.pendPool, request.Peer.id)
253-
q.pendCount -= len(request.Hashes)
254260
}
255261

256262
// Expire checks for in flight requests that exceeded a timeout allowance,
@@ -266,7 +272,6 @@ func (q *queue) Expire(timeout time.Duration) []string {
266272
for hash, index := range request.Hashes {
267273
q.hashQueue.Push(hash, float32(index))
268274
}
269-
q.pendCount -= len(request.Hashes)
270275
peers = append(peers, id)
271276
}
272277
}
@@ -289,9 +294,6 @@ func (q *queue) Deliver(id string, blocks []*types.Block) (err error) {
289294
}
290295
delete(q.pendPool, id)
291296

292-
// Mark all the hashes in the request as non-pending
293-
q.pendCount -= len(request.Hashes)
294-
295297
// If no blocks were retrieved, mark them as unavailable for the origin peer
296298
if len(blocks) == 0 {
297299
for hash, _ := range request.Hashes {

0 commit comments

Comments
 (0)