From: Matt Joiner Date: Thu, 14 Aug 2025 02:36:12 +0000 (+1000) Subject: Track activeWebseedRequests in Client too X-Git-Tag: v1.59.0~2^2~11 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=ae96fa4638c38bac4669e9ce36b2ca28093f08c4;p=btrtrc.git Track activeWebseedRequests in Client too --- diff --git a/client.go b/client.go index f2b4aefd..99494b2c 100644 --- a/client.go +++ b/client.go @@ -113,8 +113,9 @@ type Client struct { upnpMappings []*upnpMapping - webseedRequestTimer *time.Timer - webseedUpdateReason updateRequestReason + webseedRequestTimer *time.Timer + webseedUpdateReason updateRequestReason + activeWebseedRequests map[webseedUniqueRequestKey]*webseedRequest activePieceHashers int } diff --git a/torrent.go b/torrent.go index 44961c2b..2f6b7b98 100644 --- a/torrent.go +++ b/torrent.go @@ -1115,6 +1115,13 @@ func (t *Torrent) close(wg *sync.WaitGroup) { t.pieceStateChanges.Close() t.updateWantPeersEvent() g.MustDelete(t.cl.torrents, t) + // This doesn't work yet because requests remove themselves after they close, and we don't + // remove them synchronously. + if false { + if len(t.cl.torrents) == 0 { + panicif.NotZero(len(t.cl.activeWebseedRequests)) + } + } return } @@ -3085,7 +3092,8 @@ func (t *Torrent) addWebSeed(url string, opts ...AddWebSeedsOpt) bool { if t.cl.config.DisableWebseeds { return false } - if _, ok := t.webSeeds[webseedUrlKey(unique.Make(url))]; ok { + urlKey := webseedUrlKey(unique.Make(url)) + if _, ok := t.webSeeds[urlKey]; ok { return false } // I don't think Go http supports pipelining requests. However, we can have more ready to go @@ -3113,6 +3121,7 @@ func (t *Torrent) addWebSeed(url string, opts ...AddWebSeedsOpt) bool { ResponseBodyRateLimiter: t.cl.config.DownloadRateLimiter, }, hostKey: t.deriveWebSeedHostKey(url), + url: urlKey, } ws.peer.initClosedCtx() for _, opt := range opts { @@ -3136,7 +3145,7 @@ func (t *Torrent) addWebSeed(url string, opts ...AddWebSeedsOpt) bool { if t.haveInfo() { ws.onGotInfo(t.info) } - t.webSeeds[webseedUrlKey(unique.Make(url))] = &ws + t.webSeeds[urlKey] = &ws ws.peer.onNeedUpdateRequests("Torrent.addWebSeed") return true } diff --git a/webseed-peer.go b/webseed-peer.go index 4f84a5fa..19ace314 100644 --- a/webseed-peer.go +++ b/webseed-peer.go @@ -30,6 +30,8 @@ type webseedPeer struct { locker sync.Locker lastUnhandledErr time.Time hostKey webseedHostKeyHandle + // We need this to look ourselves up in the Client.activeWebseedRequests map. + url webseedUrlKey } func (*webseedPeer) allConnStatsImplField(stats *AllConnStats) *ConnStats { @@ -132,6 +134,10 @@ func (ws *webseedPeer) spawnRequest(begin, end RequestIndex, logger *slog.Logger ws.peer.t.cl.dumpCurrentWebseedRequests() } ws.activeRequests[&wsReq] = struct{}{} + t := ws.peer.t + cl := t.cl + g.MakeMapIfNil(&cl.activeWebseedRequests) + g.MapMustAssignNew(cl.activeWebseedRequests, ws.getRequestKey(&wsReq), &wsReq) ws.peer.updateExpectingChunks() panicif.Zero(ws.hostKey) ws.peer.t.cl.numWebSeedRequests[ws.hostKey]++ @@ -144,6 +150,15 @@ func (ws *webseedPeer) spawnRequest(begin, end RequestIndex, logger *slog.Logger go ws.runRequest(&wsReq) } +func (me *webseedPeer) getRequestKey(wr *webseedRequest) webseedUniqueRequestKey { + // This is used to find the request in the Client's active requests map. + return webseedUniqueRequestKey{ + url: me.url, + t: me.peer.t, + sliceIndex: me.peer.t.requestIndexToWebseedSliceIndex(wr.begin), + } +} + func (me *webseedPeer) hasOverlappingRequests(begin, end RequestIndex) bool { for req := range me.activeRequests { if req.cancelled.Load() { @@ -210,7 +225,9 @@ func (ws *webseedPeer) runRequest(webseedRequest *webseedRequest) { func (ws *webseedPeer) deleteActiveRequest(wr *webseedRequest) { g.MustDelete(ws.activeRequests, wr) - ws.peer.t.cl.numWebSeedRequests[ws.hostKey]-- + cl := ws.peer.cl + cl.numWebSeedRequests[ws.hostKey]-- + g.MustDelete(cl.activeWebseedRequests, ws.getRequestKey(wr)) ws.peer.updateExpectingChunks() }