request-strategy/order.go | 7 +++++-- requesting.go | 19 +++++++++++-------- diff --git a/request-strategy/order.go b/request-strategy/order.go index c276da91587104087170d1b913cf9f10526c17cb..8bdfe188d159ab90d1d0fbd7c4a7635e90845080 100644 --- a/request-strategy/order.go +++ b/request-strategy/order.go @@ -43,7 +43,10 @@ var packageExpvarMap = expvar.NewMap("request-strategy") // Calls f with requestable pieces in order. -func GetRequestablePieces(input Input, pro *PieceRequestOrder, f func(ih metainfo.Hash, pieceIndex int)) { +func GetRequestablePieces( + input Input, pro *PieceRequestOrder, + f func(ih metainfo.Hash, pieceIndex int, orderState PieceRequestOrderState), +) { // Storage capacity left for this run, keyed by the storage capacity pointer on the storage // TorrentImpl. A nil value means no capacity limit. var storageLeft *int64 @@ -70,7 +73,7 @@ if input.MaxUnverifiedBytes() != 0 && allTorrentsUnverifiedBytes+pieceLength > input.MaxUnverifiedBytes() { return true } allTorrentsUnverifiedBytes += pieceLength - f(ih, _i.key.Index) + f(ih, _i.key.Index, _i.state) return true }) return diff --git a/requesting.go b/requesting.go index 7b6152fd9e33a570ce3c655b5b5e29b0b4824756..ece5dc398797cd92bc6956084299e6711443c2a3 100644 --- a/requesting.go +++ b/requesting.go @@ -70,6 +70,7 @@ type desiredPeerRequests struct { requestIndexes []RequestIndex peer *Peer + pieceStates map[pieceIndex]request_strategy.PieceRequestOrderState } func (p *desiredPeerRequests) Len() int { @@ -94,16 +95,16 @@ !p.peer.peerAllowedFast.Contains(leftPieceIndex), !p.peer.peerAllowedFast.Contains(rightPieceIndex), ) } - leftPiece := t.piece(leftPieceIndex) - rightPiece := t.piece(rightPieceIndex) + leftPiece := p.pieceStates[leftPieceIndex] + rightPiece := p.pieceStates[rightPieceIndex] // Putting this first means we can steal requests from lesser-performing peers for our first few // new requests. priority := func() piecePriority { // Technically we would be happy with the cached priority here, except we don't actually // cache it anymore, and Torrent.piecePriority just does another lookup of *Piece to resolve // the priority through Piece.purePriority, which is probably slower. - leftPriority := leftPiece.purePriority() - rightPriority := rightPiece.purePriority() + leftPriority := leftPiece.Priority + rightPriority := rightPiece.Priority ml = ml.Int( -int(leftPriority), -int(rightPriority), @@ -147,8 +148,8 @@ // it will be served and therefore is the best candidate to cancel. ml = ml.CmpInt64(rightLast.Sub(leftLast).Nanoseconds()) } ml = ml.Int( - leftPiece.relativeAvailability, - rightPiece.relativeAvailability) + leftPiece.Availability, + rightPiece.Availability) if priority == PiecePriorityReadahead { // TODO: For readahead in particular, it would be even better to consider distance from the // reader position so that reads earlier in a torrent don't starve reads later in the @@ -191,12 +192,13 @@ return } input := p.t.getRequestStrategyInput() requestHeap := desiredPeerRequests{ - peer: p, + peer: p, + pieceStates: make(map[pieceIndex]request_strategy.PieceRequestOrderState), } request_strategy.GetRequestablePieces( input, p.t.getPieceRequestOrder(), - func(ih InfoHash, pieceIndex int) { + func(ih InfoHash, pieceIndex int, pieceExtra request_strategy.PieceRequestOrderState) { if ih != p.t.infoHash { return } @@ -225,6 +227,7 @@ // Can't re-request while awaiting acknowledgement. return } requestHeap.requestIndexes = append(requestHeap.requestIndexes, r) + requestHeap.pieceStates[pieceIndex] = pieceExtra }) }, )