From: Matt Joiner Date: Thu, 13 May 2021 08:35:49 +0000 (+1000) Subject: Move piece allocation to its own func X-Git-Tag: v1.29.0~31^2~31 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=4e9f707aeb9b1c37bb0a0481cc6ef017d43f557a;p=btrtrc.git Move piece allocation to its own func --- diff --git a/request-strategy/order.go b/request-strategy/order.go index 307e47ef..da6890e5 100644 --- a/request-strategy/order.go +++ b/request-strategy/order.go @@ -133,94 +133,7 @@ func (requestOrder *ClientPieceOrder) DoRequests(torrents []*Torrent) map[PeerId if !p.Request { continue } - peersForPiece := make([]*peersForPieceRequests, 0, len(allPeers[p.t])) - for _, peer := range allPeers[p.t] { - peersForPiece = append(peersForPiece, &peersForPieceRequests{ - requestsInPiece: 0, - requestsPeer: peer, - }) - } - sortPeersForPiece := func() { - sort.Slice(peersForPiece, func(i, j int) bool { - return multiless.New().Int( - peersForPiece[i].requestsInPiece, - peersForPiece[j].requestsInPiece, - ).Int( - peersForPiece[i].requestablePiecesRemaining, - peersForPiece[j].requestablePiecesRemaining, - ).Float64( - peersForPiece[j].DownloadRate, - peersForPiece[i].DownloadRate, - ).Int64( - int64(peersForPiece[j].Age), int64(peersForPiece[i].Age), - // TODO: Probably peer priority can come next - ).Uintptr( - peersForPiece[i].Id.Uintptr(), - peersForPiece[j].Id.Uintptr(), - ).MustLess() - }) - } - pendingChunksRemaining := int(p.NumPendingChunks) - if f := torrentPiece.IterPendingChunks; f != nil { - f(func(chunk types.ChunkSpec) { - req := Request{pp.Integer(p.index), chunk} - defer func() { pendingChunksRemaining-- }() - sortPeersForPiece() - skipped := 0 - // Try up to the number of peers that could legitimately receive the request equal to - // the number of chunks left. This should ensure that only the best peers serve the last - // few chunks in a piece. - lowestNumRequestsInPiece := math.MaxInt16 - for _, peer := range peersForPiece { - if !peer.canFitRequest() || !peer.HasPiece(p.index) || (!peer.pieceAllowedFastOrDefault(p.index) && peer.Choking) { - continue - } - if skipped+1 >= pendingChunksRemaining { - break - } - if f := peer.HasExistingRequest; f == nil || !f(req) { - skipped++ - lowestNumRequestsInPiece = peer.requestsInPiece - continue - } - if peer.requestsInPiece > lowestNumRequestsInPiece { - break - } - if !peer.pieceAllowedFastOrDefault(p.index) { - // We must stay interested for this. - peer.nextState.Interested = true - } - peer.addNextRequest(req) - return - } - for _, peer := range peersForPiece { - if !peer.canFitRequest() { - continue - } - if !peer.HasPiece(p.index) { - continue - } - if !peer.pieceAllowedFastOrDefault(p.index) { - // TODO: Verify that's okay to stay uninterested if we request allowed fast - // pieces. - peer.nextState.Interested = true - if peer.Choking { - continue - } - } - peer.addNextRequest(req) - return - } - }) - } - if pendingChunksRemaining != 0 { - panic(pendingChunksRemaining) - } - for _, peer := range peersForPiece { - if peer.canRequestPiece(p.index) { - peer.requestablePiecesRemaining-- - } - } + allocatePendingChunks(p, allPeers[p.t]) } ret := make(map[PeerId]PeerNextRequestState) for _, peers := range allPeers { @@ -233,3 +146,94 @@ func (requestOrder *ClientPieceOrder) DoRequests(torrents []*Torrent) map[PeerId } return ret } + +func allocatePendingChunks(p pieceRequestOrderPiece, peers []*requestsPeer) { + peersForPiece := make([]*peersForPieceRequests, 0, len(peers)) + for _, peer := range peers { + peersForPiece = append(peersForPiece, &peersForPieceRequests{ + requestsInPiece: 0, + requestsPeer: peer, + }) + } + sortPeersForPiece := func() { + sort.Slice(peersForPiece, func(i, j int) bool { + return multiless.New().Int( + peersForPiece[i].requestsInPiece, + peersForPiece[j].requestsInPiece, + ).Int( + peersForPiece[i].requestablePiecesRemaining, + peersForPiece[j].requestablePiecesRemaining, + ).Float64( + peersForPiece[j].DownloadRate, + peersForPiece[i].DownloadRate, + ).Int64( + int64(peersForPiece[j].Age), int64(peersForPiece[i].Age), + // TODO: Probably peer priority can come next + ).Uintptr( + peersForPiece[i].Id.Uintptr(), + peersForPiece[j].Id.Uintptr(), + ).MustLess() + }) + } + pendingChunksRemaining := int(p.NumPendingChunks) + if f := p.IterPendingChunks; f != nil { + f(func(chunk types.ChunkSpec) { + req := Request{pp.Integer(p.index), chunk} + defer func() { pendingChunksRemaining-- }() + sortPeersForPiece() + skipped := 0 + // Try up to the number of peers that could legitimately receive the request equal to + // the number of chunks left. This should ensure that only the best peers serve the last + // few chunks in a piece. + lowestNumRequestsInPiece := math.MaxInt16 + for _, peer := range peersForPiece { + if !peer.canFitRequest() || !peer.HasPiece(p.index) || (!peer.pieceAllowedFastOrDefault(p.index) && peer.Choking) { + continue + } + if skipped+1 >= pendingChunksRemaining { + break + } + if f := peer.HasExistingRequest; f == nil || !f(req) { + skipped++ + lowestNumRequestsInPiece = peer.requestsInPiece + continue + } + if peer.requestsInPiece > lowestNumRequestsInPiece { + break + } + if !peer.pieceAllowedFastOrDefault(p.index) { + // We must stay interested for this. + peer.nextState.Interested = true + } + peer.addNextRequest(req) + return + } + for _, peer := range peersForPiece { + if !peer.canFitRequest() { + continue + } + if !peer.HasPiece(p.index) { + continue + } + if !peer.pieceAllowedFastOrDefault(p.index) { + // TODO: Verify that's okay to stay uninterested if we request allowed fast + // pieces. + peer.nextState.Interested = true + if peer.Choking { + continue + } + } + peer.addNextRequest(req) + return + } + }) + } + if pendingChunksRemaining != 0 { + panic(pendingChunksRemaining) + } + for _, peer := range peersForPiece { + if peer.canRequestPiece(p.index) { + peer.requestablePiecesRemaining-- + } + } +}