}
// Pieces in the range [begin, end) may have partially complete files. Note we only check for dirty chunks and either all or no pieces being complete.
-func (t *Torrent) filesInForWebseedRequestSliceMightBePartial(firstRequest RequestIndex) bool {
- beginPiece := t.pieceIndexOfRequestIndex(firstRequest)
- endRequest := t.endRequestForAlignedWebseedResponse(firstRequest)
+func (t *Torrent) filesInRequestRangeMightBePartial(beginRequest, endRequest RequestIndex) bool {
+ if beginRequest == endRequest {
+ return false
+ }
+ beginPiece := t.pieceIndexOfRequestIndex(beginRequest)
endPiece := pieceIndex(intCeilDiv(endRequest, t.chunksPerRegularPiece()))
return t.filesInPieceRangeMightBePartial(beginPiece, endPiece)
}
webseedRequestOrderValue{
aprioriMapValue: value,
},
- key.t.filesInForWebseedRequestSliceMightBePartial(value.startRequest),
+ key.t.filesInRequestRangeMightBePartial(
+ value.startRequest,
+ key.t.endRequestForAlignedWebseedResponse(value.startRequest),
+ ),
})
}
// Add remaining existing requests.
if key.t.dataDownloadDisallowed.IsSet() {
continue
}
+ wr := value.existingWebseedRequest
heapSlice = append(heapSlice, heapElem{
key,
existingRequests[key],
- key.t.filesInForWebseedRequestSliceMightBePartial(value.startRequest),
+ key.t.filesInRequestRangeMightBePartial(wr.next, wr.end),
})
}
aprioriHeap := heap.InterfaceForSlice(
// smaller will allow requests to complete a smaller set of files faster.
var webseedRequestChunkSize = initUIntFromEnv[uint64]("TORRENT_WEBSEED_REQUEST_CHUNK_SIZE", 64<<20, 64)
+// Can return the same as start if the request is at the end of the torrent.
func (t *Torrent) endRequestForAlignedWebseedResponse(start RequestIndex) RequestIndex {
end := min(t.maxEndRequest(), nextMultiple(start, t.chunksPerAlignedWebseedResponse()))
- panicif.LessThanOrEqual(end, start)
return end
}
return RequestIndex(webseedRequestChunkSize / t.chunkSize.Uint64())
}
+func (t *Torrent) requestIndexToWebseedSliceIndex(requestIndex RequestIndex) webseedSliceIndex {
+ return webseedSliceIndex(requestIndex / t.chunksPerAlignedWebseedResponse())
+}
+
func (cl *Client) dumpCurrentWebseedRequests() {
if webseed.PrintDebug {
fmt.Println("current webseed requests:")
startIndex RequestIndex
}
-func (me *plannedWebseedRequest) sliceIndex() RequestIndex {
- return me.startIndex / me.t.chunksPerAlignedWebseedResponse()
+func (me *plannedWebseedRequest) sliceIndex() webseedSliceIndex {
+ return me.t.requestIndexToWebseedSliceIndex(me.startIndex)
}
func (me *plannedWebseedRequest) toChunkedWebseedRequestKey() webseedUniqueRequestKey {
type webseedUniqueRequestKey struct {
url webseedUrlKey
t *Torrent
- sliceIndex RequestIndex
+ sliceIndex webseedSliceIndex
}
type aprioriMapValue struct {
// etc. Order state priority would be faster otherwise.
priority := p.effectivePriority()
firstRequest := p.requestIndexBegin() + cleanOpt.Value
- webseedSliceIndex := firstRequest / t.chunksPerAlignedWebseedResponse()
+ panicif.GreaterThanOrEqual(firstRequest, t.maxEndRequest())
+ webseedSliceIndex := t.requestIndexToWebseedSliceIndex(firstRequest)
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.
if !yield(
webseedUniqueRequestKey{
t: t,
- sliceIndex: ar.next / t.chunksPerAlignedWebseedResponse(),
+ sliceIndex: t.requestIndexToWebseedSliceIndex(ar.next),
url: url,
},
webseedRequestOrderValue{