From 6c8f277d3471e4cd36a8fdeeb056cc78535c48b2 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Fri, 18 Jul 2025 23:08:15 +1000 Subject: [PATCH] Allocate Torrent file segments index just once --- piece.go | 2 +- torrent.go | 10 +++++++--- webseed-peer.go | 2 +- webseed/client.go | 7 +++---- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/piece.go b/piece.go index 597cd190..fc17714b 100644 --- a/piece.go +++ b/piece.go @@ -451,7 +451,7 @@ func (p *Piece) publishStateChange() { } func (p *Piece) fileExtents(offsetIntoPiece int64) iter.Seq2[int, segments.Extent] { - return p.t.info.FileSegmentsIndex().LocateIter(segments.Extent{ + return p.t.fileSegmentsIndex.Unwrap().LocateIter(segments.Extent{ p.torrentBeginOffset() + offsetIntoPiece, int64(p.length()) - offsetIntoPiece, }) diff --git a/torrent.go b/torrent.go index aab918a8..104733f9 100644 --- a/torrent.go +++ b/torrent.go @@ -35,6 +35,7 @@ import ( "github.com/anacrolix/missinggo/v2/pubsub" "github.com/anacrolix/multiless" "github.com/anacrolix/sync" + "github.com/anacrolix/torrent/segments" "github.com/pion/webrtc/v4" "golang.org/x/sync/errgroup" "golang.org/x/time/rate" @@ -115,8 +116,9 @@ type Torrent struct { // routines. Cancelled when the Torrent is Closed too. getInfoCtx context.Context // Put a nice reason in :) - getInfoCtxCancel context.CancelCauseFunc - files *[]*File + getInfoCtxCancel context.CancelCauseFunc + files *[]*File + fileSegmentsIndex g.Option[segments.Index] _chunksPerRegularPiece chunkIndexType @@ -380,7 +382,8 @@ func (t *Torrent) invalidateMetadata() { t.metadataCompletedChunks[i] = false } t.nameMu.Lock() - t.info = nil + // Why the fuck would info be set? + panicif.NotNil(t.info) t.nameMu.Unlock() } @@ -538,6 +541,7 @@ func (t *Torrent) setInfo(info *metainfo.Info) error { } t.nameMu.Lock() t.info = info + panicif.True(t.fileSegmentsIndex.Set(info.FileSegmentsIndex()).Ok) t.getInfoCtxCancel(errors.New("got info")) t.nameMu.Unlock() t._chunksPerRegularPiece = chunkIndexType(intCeilDiv(pp.Integer(t.usualPieceSize()), t.chunkSize)) diff --git a/webseed-peer.go b/webseed-peer.go index 1a131f12..b7c7a54f 100644 --- a/webseed-peer.go +++ b/webseed-peer.go @@ -90,7 +90,7 @@ func (ws *webseedPeer) String() string { } func (ws *webseedPeer) onGotInfo(info *metainfo.Info) { - ws.client.SetInfo(info) + ws.client.SetInfo(info, ws.peer.t.fileSegmentsIndex.UnwrapPtr()) // There should be probably be a callback in Client instead, so it can remove pieces at its whim // too. ws.client.Pieces.Iterate(func(x uint32) bool { diff --git a/webseed/client.go b/webseed/client.go index f6e03da5..a4d43274 100644 --- a/webseed/client.go +++ b/webseed/client.go @@ -67,8 +67,7 @@ type Client struct { // Max concurrent requests to a WebSeed for a given torrent. MaxRequests int - // TODO: Share this with Torrent. - fileIndex segments.Index + fileIndex *segments.Index info *metainfo.Info // The pieces we can request with the Url. We're more likely to ban/block at the file-level // given that's how requests are mapped to webseeds, but the torrent.Client works at the piece @@ -84,13 +83,13 @@ type Client struct { type ResponseBodyWrapper func(io.Reader) io.Reader -func (me *Client) SetInfo(info *metainfo.Info) { +func (me *Client) SetInfo(info *metainfo.Info, fileIndex *segments.Index) { if !strings.HasSuffix(me.Url, "/") && info.IsDir() { // In my experience, this is a non-conforming webseed. For example the // http://ia600500.us.archive.org/1/items URLs in archive.org torrents. return } - me.fileIndex = info.FileSegmentsIndex() + me.fileIndex = fileIndex me.info = info me.Pieces.AddRange(0, uint64(info.NumPieces())) } -- 2.51.0