2
0
mirror of synced 2025-02-23 22:28:11 +00:00

Try a state-delta function for updating request state

Also adds Torrent.networkingEnabled, though it isn't yet useful.
This commit is contained in:
Matt Joiner 2017-08-18 01:51:02 +10:00
parent 493916c279
commit 76c60ffa77
3 changed files with 71 additions and 16 deletions

View File

@ -1178,6 +1178,8 @@ func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (
storageOpener: storageClient,
maxEstablishedConns: defaultEstablishedConnsPerTorrent,
networkingEnabled: true,
}
t.setChunkSize(defaultChunkSize)
return

View File

@ -484,26 +484,67 @@ func (cn *connection) Bitfield(haves []bool) {
cn.sentHaves = append([]bool(nil), haves...)
}
func nextRequestState(
networkingEnabled bool,
currentRequests map[request]struct{},
peerChoking bool,
nextPieces prioritybitmap.PriorityBitmap,
pendingChunks func(piece int, f func(chunkSpec) bool) bool,
requestsLowWater int,
requestsHighWater int,
) (
requests map[request]struct{},
interested bool,
) {
if !networkingEnabled || nextPieces.IsEmpty() {
return nil, false
}
if peerChoking || len(currentRequests) > requestsLowWater {
return currentRequests, true
}
requests = make(map[request]struct{}, requestsHighWater)
for r := range currentRequests {
requests[r] = struct{}{}
}
nextPieces.IterTyped(func(piece int) bool {
return pendingChunks(piece, func(cs chunkSpec) bool {
if len(requests) >= requestsHighWater {
return false
}
r := request{pp.Integer(piece), cs}
requests[r] = struct{}{}
return true
})
})
return requests, true
}
func (cn *connection) updateRequests() {
if !cn.t.haveInfo() {
return
}
if cn.Interested {
if cn.PeerChoked {
return
}
if len(cn.Requests) > cn.requestsLowWater {
return
rs, i := nextRequestState(
cn.t.networkingEnabled,
cn.Requests,
cn.PeerChoked,
cn.pieceRequestOrder,
func(piece int, f func(chunkSpec) bool) bool {
return undirtiedChunks(piece, cn.t, f)
},
cn.requestsLowWater,
cn.nominalMaxRequests())
for r := range cn.Requests {
if _, ok := rs[r]; !ok {
if !cn.Cancel(r) {
panic("wat")
}
}
}
cn.fillRequests()
if len(cn.Requests) == 0 && !cn.PeerChoked {
// So we're not choked, but we don't want anything right now. We may
// have completed readahead, and the readahead window has not rolled
// over to the next piece. Better to stay interested in case we're
// going to want data in the near future.
cn.SetInterested(!cn.t.haveAllPieces())
for r := range rs {
if _, ok := cn.Requests[r]; !ok {
if !cn.Request(r) {
panic("how")
}
}
}
cn.SetInterested(i)
}
func (cn *connection) fillRequests() {
@ -526,6 +567,13 @@ func (c *connection) requestPiecePendingChunks(piece int) (again bool) {
})
}
func undirtiedChunks(piece int, t *Torrent, f func(chunkSpec) bool) bool {
chunkIndices := t.pieces[piece].undirtiedChunkIndices().ToSortedSlice()
return iter.ForPerm(len(chunkIndices), func(i int) bool {
return f(t.chunkIndexSpec(chunkIndices[i], piece))
})
}
func (cn *connection) stopRequestingPiece(piece int) {
cn.pieceRequestOrder.Remove(piece)
cn.updateRequests()

View File

@ -43,6 +43,8 @@ type peersKey struct {
type Torrent struct {
cl *Client
networkingEnabled bool
closed missinggo.Event
infoHash metainfo.Hash
pieces []piece
@ -1348,6 +1350,9 @@ func (t *Torrent) addConnection(c *connection, outgoing bool) bool {
}
func (t *Torrent) wantConns() bool {
if !t.networkingEnabled {
return false
}
if t.closed.IsSet() {
return false
}