]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Remove extra Torrent closed context goroutine for trackers
authorMatt Joiner <anacrolix@gmail.com>
Wed, 7 May 2025 00:20:05 +0000 (10:20 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Wed, 7 May 2025 00:20:05 +0000 (10:20 +1000)
client.go
internal/testutil/greeting.go
internal/testutil/spec.go
torrent.go
torrent_test.go
tracker_scraper.go

index 62f6aadfff53f2d2f37df0ee4e29f9479a0da2ad..121bab2100ff2e0db540c065143b6caae3e90606 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1346,7 +1346,8 @@ func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (
        })
 }
 
-// Return a Torrent ready for insertion into a Client.
+// Return a Torrent ready for insertion into a Client. This is also the method to call to create
+// Torrents for testing.
 func (cl *Client) newTorrentOpt(opts AddTorrentOpts) (t *Torrent) {
        var v1InfoHash g.Option[infohash.T]
        if !opts.InfoHash.IsZero() {
@@ -1383,6 +1384,7 @@ func (cl *Client) newTorrentOpt(opts AddTorrentOpts) (t *Torrent) {
                webSeeds:     make(map[string]*Peer),
                gotMetainfoC: make(chan struct{}),
        }
+       t.closedCtx, t.closedCtxCancel = context.WithCancel(context.Background())
        var salt [8]byte
        rand.Read(salt[:])
        t.smartBanCache.Hash = func(b []byte) uint64 {
index 6544483c8b312690764518f4f8be1bfeb241d09f..dbdab5543f120ccc5321eeaa711cfa3914afa5bb 100644 (file)
@@ -33,7 +33,8 @@ func CreateDummyTorrentData(dirName string) string {
 }
 
 func GreetingMetaInfo() *metainfo.MetaInfo {
-       return Greeting.Metainfo(5)
+       mi, _ := Greeting.Generate(5)
+       return &mi
 }
 
 // Gives a temporary directory containing the completed "greeting" torrent,
index ad0e4074def5b72c06f825f26969a13b5fb7762f..c8727aa1840b437229d8d9b019c5b239a5e7da15 100644 (file)
@@ -15,6 +15,7 @@ type File struct {
        Data string
 }
 
+// High-level description of a torrent for testing purposes.
 type Torrent struct {
        Files []File
        Name  string
@@ -58,10 +59,11 @@ func (t *Torrent) Info(pieceLength int64) metainfo.Info {
        return info
 }
 
-func (t *Torrent) Metainfo(pieceLength int64) *metainfo.MetaInfo {
-       mi := metainfo.MetaInfo{}
+// Create an info and metainfo with bytes set for the torrent with the provided piece length.
+func (t *Torrent) Generate(pieceLength int64) (mi metainfo.MetaInfo, info metainfo.Info) {
        var err error
-       mi.InfoBytes, err = bencode.Marshal(t.Info(pieceLength))
+       info = t.Info(pieceLength)
+       mi.InfoBytes, err = bencode.Marshal(info)
        expect.Nil(err)
-       return &mi
+       return
 }
index 93e5b86814bcc74830aa66af3fcfa36216c0a808..b8ac02484c8a95e87a41b9bd08dcc7402e48016e 100644 (file)
@@ -72,8 +72,12 @@ type Torrent struct {
        dataUploadDisallowed   bool
        userOnWriteChunkErr    func(error)
 
-       closed  chansync.SetOnce
-       onClose []func()
+       closed chansync.SetOnce
+       // A background Context cancelled when the Torrent is closed. Added to minimize extra goroutines
+       // in tracker handlers.
+       closedCtx       context.Context
+       closedCtxCancel func()
+       onClose         []func()
 
        infoHash   g.Option[metainfo.Hash]
        infoHashV2 g.Option[infohash_v2.T]
@@ -1031,6 +1035,7 @@ func (t *Torrent) close(wg *sync.WaitGroup) (err error) {
                err = errors.New("already closed")
                return
        }
+       t.closedCtxCancel()
        for _, f := range t.onClose {
                f()
        }
index 663716df006b5437280aa8a44ceb9dd2290ab968..2b3a087dc3f69aeead534fc98544f0af1bf38e2e 100644 (file)
@@ -11,7 +11,6 @@ import (
        "testing"
 
        g "github.com/anacrolix/generics"
-       "github.com/anacrolix/log"
        "github.com/anacrolix/missinggo/v2"
        "github.com/anacrolix/missinggo/v2/bitmap"
        qt "github.com/frankban/quicktest"
@@ -226,25 +225,19 @@ func TestTorrentMetainfoIncompleteMetadata(t *testing.T) {
 func TestRelativeAvailabilityHaveNone(t *testing.T) {
        c := qt.New(t)
        var err error
-       cl := Client{
-               config: TestingConfig(t),
-       }
-       tt := Torrent{
-               cl:           &cl,
-               logger:       log.Default,
-               gotMetainfoC: make(chan struct{}),
-       }
+       cl := newTestingClient(t)
+       mi, info := testutil.Greeting.Generate(5)
+       tt := cl.newTorrentOpt(AddTorrentOpts{InfoHash: mi.HashInfoBytes()})
        tt.setChunkSize(2)
        g.MakeMapIfNil(&tt.conns)
        pc := PeerConn{}
-       pc.t = &tt
+       pc.t = tt
        pc.legacyPeerImpl = &pc
        pc.initRequestState()
        g.InitNew(&pc.callbacks)
        tt.conns[&pc] = struct{}{}
        err = pc.peerSentHave(0)
        c.Assert(err, qt.IsNil)
-       info := testutil.Greeting.Info(5)
        err = tt.setInfo(&info)
        c.Assert(err, qt.IsNil)
        tt.onSetInfo()
index 10fc87b2006c95e86dac540adf639a0b62e04ab6..b8d72e986e87f4e2d93f62357c7ef83d6bdf43c1 100644 (file)
@@ -219,22 +219,11 @@ func (me *trackerScraper) Stop() {
 func (me *trackerScraper) Run() {
        defer me.announceStopped()
 
-       ctx, cancel := context.WithCancel(context.Background())
-       defer cancel()
-       // TODO: Get rid of the need for this.
-       go func() {
-               defer cancel()
-               select {
-               case <-ctx.Done():
-               case <-me.t.Closed():
-               }
-       }()
-
        // make sure first announce is a "started"
        e := tracker.Started
 
        for {
-               ar := me.announce(ctx, e)
+               ar := me.announce(me.t.closedCtx, e)
                // after first announce, get back to regular "none"
                e = tracker.None
                me.t.cl.lock()