func pieceOrderLess(i, j *PieceRequestOrderItem) multiless.Computation {
return multiless.New().Int(
int(j.State.Priority), int(i.State.Priority),
- // TODO: Should we match on complete here to prevent churn when availability changes?
+ // TODO: Should we match on complete here to prevent churn when availability changes? (Answer: Yes).
).Bool(
j.State.Partial, i.State.Partial,
).Int(
})
}
-// Returns true if the piece should be considered against the unverified bytes limit. This is
-// based on whether the callee intends to request from the piece. Pieces submitted to this
-// callback passed Piece.Request and so are ready for immediate download.
+// This did return true if the piece should be considered against the unverified bytes limit. But
+// that would cause thrashing on completion: The order should be stable. This is now a 3-tuple
+// iterator.
type RequestPieceFunc func(ih metainfo.Hash, pieceIndex int, orderState PieceRequestOrderState) bool
// Calls f with requestable pieces in order.
func GetRequestablePieces(
input Input, pro *PieceRequestOrder,
- // Returns true if the piece should be considered against the unverified bytes limit. This is
- // based on whether the callee intends to request from the piece. Pieces submitted to this
- // callback passed Piece.Request and so are ready for immediate download.
+ // Pieces submitted to this callback passed Piece.Request and so are ready for immediate
+ // download.
requestPiece RequestPieceFunc,
) {
// Storage capacity left for this run, keyed by the storage capacity pointer on the storage
if !requestPiece(ih, item.Key.Index, item.State) {
// No blocks are being considered from this piece, so it won't result in unverified
// bytes.
- return true
+ return false
}
} else if !piece.CountUnverified() {
// The piece is pristine, and we're not considering it for requests.
t.getRequestablePieces(
func(ih metainfo.Hash, pieceIndex int, pieceExtra requestStrategy.PieceRequestOrderState) bool {
if ih != *t.canonicalShortInfohash() {
- return false
+ return true
}
if !p.peerHasPiece(pieceIndex) {
- return false
+ return true
}
requestHeap.pieceStates[pieceIndex].Set(pieceExtra)
allowedFast := p.peerAllowedFast.Contains(pieceIndex)
func(ih metainfo.Hash, pieceIndex int, orderState requestStrategy.PieceRequestOrderState) bool {
t := cl.torrentsByShortHash[ih]
if len(t.webSeeds) == 0 {
- return false
+ return true
}
p := t.piece(pieceIndex)
cleanOpt := p.firstCleanChunk()
if !cleanOpt.Ok {
- // Could almost return true here, as clearly something is going on with the piece.
- return false
+ return true
}
// Pretty sure we want this and not the order state priority. That one is for
// client piece request order and ignores other states like hashing, marking
for url, ws := range t.webSeeds {
// Return value from this function (RequestPieceFunc) doesn't terminate
// iteration, so propagate that to not handling the yield return value.
- yield(
+ if !yield(
webseedUniqueRequestKey{
aprioriWebseedRequestKey{
t: t,
priority: priority,
costKey: ws.hostKey,
},
- )
+ ) {
+ return false
+ }
}
// Pieces iterated here are only to select webseed requests. There's no guarantee they're chosen.
return false