]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Maybe partial file for existing webseed requests that are finished would panic
authorMatt Joiner <anacrolix@gmail.com>
Thu, 14 Aug 2025 02:25:54 +0000 (12:25 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 14 Aug 2025 02:25:54 +0000 (12:25 +1000)
requesting.go
torrent.go
webseed-requesting.go

index 3dd40c52f8327a5a19ccfe0dddc96756565b1801..44327445959cec45ec99e1006fda64f90c826a11 100644 (file)
@@ -79,7 +79,8 @@ type (
        // be converted to a protocol request. TODO: This should be private.
        RequestIndex = requestStrategy.RequestIndex
        // This is request index but per-piece.
-       chunkIndexType = requestStrategy.ChunkIndex
+       chunkIndexType    = requestStrategy.ChunkIndex
+       webseedSliceIndex RequestIndex
 )
 
 type desiredPeerRequests struct {
index e3516f20b3d3fc937e8fbaa5baaeb9226598a16a..44961c2b2f3562366b9e80715444ee07ac3fe6f6 100644 (file)
@@ -3625,9 +3625,11 @@ func (t *Torrent) filesInPieceRangeMightBePartial(begin, end pieceIndex) bool {
 }
 
 // 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)
 }
index ff84becbd3e633904b77789a1c262bb92d1d9b68..e1b85a35a4e1f26c01f413a3a85376d83535272e 100644 (file)
@@ -103,7 +103,10 @@ func (cl *Client) updateWebseedRequests() {
                        webseedRequestOrderValue{
                                aprioriMapValue: value,
                        },
-                       key.t.filesInForWebseedRequestSliceMightBePartial(value.startRequest),
+                       key.t.filesInRequestRangeMightBePartial(
+                               value.startRequest,
+                               key.t.endRequestForAlignedWebseedResponse(value.startRequest),
+                       ),
                })
        }
        // Add remaining existing requests.
@@ -112,10 +115,11 @@ func (cl *Client) updateWebseedRequests() {
                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(
@@ -267,9 +271,9 @@ func (t *Torrent) getWebseedRequestEnd(begin RequestIndex, debugLogger *slog.Log
 // 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
 }
 
@@ -278,6 +282,10 @@ func (t *Torrent) chunksPerAlignedWebseedResponse() RequestIndex {
        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:")
@@ -298,8 +306,8 @@ type plannedWebseedRequest struct {
        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 {
@@ -325,7 +333,7 @@ func (me webseedRequestPlan) String() string {
 type webseedUniqueRequestKey struct {
        url        webseedUrlKey
        t          *Torrent
-       sliceIndex RequestIndex
+       sliceIndex webseedSliceIndex
 }
 
 type aprioriMapValue struct {
@@ -373,7 +381,8 @@ func (cl *Client) iterPossibleWebseedRequests() iter.Seq2[webseedUniqueRequestKe
                                        // 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.
@@ -425,7 +434,7 @@ func (cl *Client) iterCurrentWebseedRequests() iter.Seq2[webseedUniqueRequestKey
                                        if !yield(
                                                webseedUniqueRequestKey{
                                                        t:          t,
-                                                       sliceIndex: ar.next / t.chunksPerAlignedWebseedResponse(),
+                                                       sliceIndex: t.requestIndexToWebseedSliceIndex(ar.next),
                                                        url:        url,
                                                },
                                                webseedRequestOrderValue{