From: Matt Joiner Date: Tue, 5 Aug 2025 13:59:44 +0000 (+1000) Subject: Sort webseed request heap deterministically X-Git-Tag: v1.59.0~2^2~46 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=e6588fd7a96cb35ce269abaea6a17ba316ca40cb;p=btrtrc.git Sort webseed request heap deterministically --- diff --git a/webseed-requesting.go b/webseed-requesting.go index 22d30160..abb297ad 100644 --- a/webseed-requesting.go +++ b/webseed-requesting.go @@ -1,6 +1,7 @@ package torrent import ( + "bytes" "cmp" "context" "fmt" @@ -72,6 +73,7 @@ func (cl *Client) updateWebseedRequests() { } aprioriMap[uniqueKey.aprioriWebseedRequestKey] = aprioriMapValue{uniqueKey.startRequest, value} } + // TODO: This should not be keyed on startRequest but only on sliceIndex. existingRequests := maps.Collect(cl.iterCurrentWebseedRequests()) // We don't need the value but maybe cloning is just faster anyway? unusedExistingRequests := maps.Clone(existingRequests) @@ -117,7 +119,7 @@ func (cl *Client) updateWebseedRequests() { &heapSlice, func(l heapElem, r heapElem) bool { // Not stable ordering but being sticky to existing webseeds should be enough. - return cmp.Or( + ret := cmp.Or( // Prefer highest priority -cmp.Compare(l.priority, r.priority), // Then existing requests @@ -129,7 +131,16 @@ func (cl *Client) updateWebseedRequests() { // No need to prefer longer files anymore now that we're using slices? //// Longer files first. //-cmp.Compare(l.longestFile().Unwrap(), r.longestFile().Unwrap()), - ) < 0 + // Easier to debug than infohashes... + cmp.Compare(l.t.info.Name, r.t.info.Name), + bytes.Compare(l.t.canonicalShortInfohash()[:], r.t.canonicalShortInfohash()[:]), + // It's possible for 2 heap elements to have the same slice index from the same + // torrent, but they'll differ in existingWebseedRequest and be sorted before this. + // Doing earlier chunks first means more compact files for partial file hashing. + cmp.Compare(l.sliceIndex, r.sliceIndex), + ) + panicif.Zero(ret) + return ret < 0 }, )