Skip to content

Commit 2043210

Browse files
committed
webseed improvements
1 parent 4704b4b commit 2043210

File tree

2 files changed

+39
-35
lines changed

2 files changed

+39
-35
lines changed

internal/piecepicker/piecepicker.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,12 @@ func (p *myPiece) StalledDownloads() int {
6464
return p.Snubbed.Len() + p.Choked.Len()
6565
}
6666

67-
// AvailableForWebseed returns true if the piece can be downloaded from a webseed source.
68-
// If the piece is already requested from a peer, it does not become eligible for downloading from webseed until entering the endgame mode.
69-
func (p *myPiece) AvailableForWebseed(duplicate bool) bool {
70-
if p.Done || p.Writing || p.RequestedWebseed != nil {
67+
// AvailableForWebseed returns true if the piece is allowed to be downloaded from a webseed source.
68+
func (p *myPiece) AvailableForWebseed() bool {
69+
if p.Done || p.Writing {
7170
return false
7271
}
73-
if !duplicate {
74-
return p.RequestedWebseed != nil
75-
}
76-
return true
72+
return p.RequestedWebseed == nil
7773
}
7874

7975
// New returns a new PiecePicker.

internal/piecepicker/webseed.go

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package piecepicker
22

33
import (
4+
"math/rand"
45
"sort"
56

67
"github.com/cenkalti/rain/internal/peer"
@@ -16,21 +17,21 @@ type WebseedDownloadSpec struct {
1617

1718
// PickWebseed returns the next spec for downloading files from webseed sources.
1819
func (p *PiecePicker) PickWebseed(src *webseedsource.WebseedSource) *WebseedDownloadSpec {
19-
begin, end := p.findPieceRangeForWebseed()
20-
if begin == end {
20+
r := p.findPieceRangeForWebseed()
21+
if r == nil {
2122
return nil
2223
}
2324
// Mark selected range as being downloaded so we won't select it again.
24-
for i := begin; i < end; i++ {
25+
for i := r.Begin; i < r.End; i++ {
2526
if p.pieces[i].RequestedWebseed != nil {
2627
panic("already downloading from webseed url")
2728
}
2829
p.pieces[i].RequestedWebseed = src
2930
}
3031
return &WebseedDownloadSpec{
3132
Source: src,
32-
Begin: begin,
33-
End: end,
33+
Begin: r.Begin,
34+
End: r.End,
3435
}
3536
}
3637

@@ -43,14 +44,24 @@ func (p *PiecePicker) downloadingWebseed() bool {
4344
return false
4445
}
4546

46-
func (p *PiecePicker) findPieceRangeForWebseed() (begin, end uint32) {
47+
func (p *PiecePicker) findPieceRangeForWebseed() *Range {
4748
gaps := p.findGaps()
4849
if len(gaps) == 0 {
49-
gap := p.webseedStealsFromAnotherWebseed()
50-
return gap.Begin, gap.End
50+
return p.webseedStealsFromAnotherWebseed()
5151
}
52+
gap := selectRandomLargestGap(gaps)
53+
return &gap
54+
}
55+
56+
func selectRandomLargestGap(gaps []Range) Range {
5257
sort.Slice(gaps, func(i, j int) bool { return gaps[i].Len() > gaps[j].Len() })
53-
return gaps[0].Begin, gaps[0].End
58+
length := gaps[0].Len()
59+
for i := range gaps {
60+
if gaps[i].Len() != length {
61+
return gaps[rand.Intn(i)]
62+
}
63+
}
64+
return gaps[rand.Intn(len(gaps))]
5465
}
5566

5667
func (p *PiecePicker) getDownloadingSources() []*webseedsource.WebseedSource {
@@ -63,17 +74,22 @@ func (p *PiecePicker) getDownloadingSources() []*webseedsource.WebseedSource {
6374
return ret
6475
}
6576

66-
func (p *PiecePicker) webseedStealsFromAnotherWebseed() (r Range) {
77+
func (p *PiecePicker) webseedStealsFromAnotherWebseed() *Range {
6778
downloading := p.getDownloadingSources()
6879
if len(downloading) == 0 {
69-
return
80+
return nil
7081
}
7182
sort.Slice(downloading, func(i, j int) bool { return downloading[i].Remaining() > downloading[j].Remaining() })
7283
src := downloading[0]
73-
r.End = src.Downloader.End
74-
r.Begin = (src.Downloader.ReadCurrent() + src.Downloader.End + 1) / 2
84+
r := &Range{
85+
Begin: (src.Downloader.ReadCurrent() + src.Downloader.End + 1) / 2,
86+
End: src.Downloader.End,
87+
}
88+
if r.Begin >= r.End {
89+
return nil
90+
}
7591
p.WebseedStopAt(src, r.Begin)
76-
return
92+
return r
7793
}
7894

7995
func (p *PiecePicker) peerStealsFromWebseed(pe *peer.Peer) *myPiece {
@@ -101,31 +117,23 @@ func (p *PiecePicker) peerStealsFromWebseed(pe *peer.Peer) *myPiece {
101117
}
102118

103119
func (p *PiecePicker) findGaps() []Range {
104-
gaps := p.findGapsWithDuplicate(false)
105-
if len(gaps) == 0 {
106-
gaps = p.findGapsWithDuplicate(true)
107-
}
108-
return gaps
109-
}
110-
111-
func (p *PiecePicker) findGapsWithDuplicate(duplicate bool) []Range {
112120
a := make([]Range, 0, len(p.pieces)/2)
113121
var inGap bool // See BEP19 for definition of "gap".
114122
var begin uint32
115123
for _, pi := range p.pieces {
116124
if !inGap {
117-
if pi.AvailableForWebseed(duplicate) {
125+
if pi.AvailableForWebseed() {
118126
begin = pi.Index
119127
inGap = true
120128
}
121129
} else {
122130
r := Range{Begin: begin, End: pi.Index}
123-
if r.Len() == p.maxWebseedPieces {
124-
a = append(a, r)
125-
begin = pi.Index
126-
} else if !pi.AvailableForWebseed(duplicate) {
131+
if !pi.AvailableForWebseed() {
127132
a = append(a, r)
128133
inGap = false
134+
} else if r.Len() == p.maxWebseedPieces {
135+
a = append(a, r)
136+
begin = pi.Index
129137
}
130138
}
131139
}

0 commit comments

Comments
 (0)