From 0dc0ddea32279452aa52d3ee9590087ac5724fba Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Thu, 14 Aug 2025 12:25:54 +1000 Subject: [PATCH] Maybe partial file for existing webseed requests that are finished would panic --- requesting.go | 3 ++- torrent.go | 8 +++++--- webseed-requesting.go | 25 +++++++++++++++++-------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/requesting.go b/requesting.go index 3dd40c52..44327445 100644 --- a/requesting.go +++ b/requesting.go @@ -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 { diff --git a/torrent.go b/torrent.go index e3516f20..44961c2b 100644 --- a/torrent.go +++ b/torrent.go @@ -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) } diff --git a/webseed-requesting.go b/webseed-requesting.go index ff84becb..e1b85a35 100644 --- a/webseed-requesting.go +++ b/webseed-requesting.go @@ -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{ -- 2.51.0