]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Cease networking on a torrent if it's finished and we're not going to seed
authorMatt Joiner <anacrolix@gmail.com>
Wed, 27 Aug 2014 23:39:27 +0000 (09:39 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Wed, 27 Aug 2014 23:39:27 +0000 (09:39 +1000)
client.go
torrent.go

index ae20854a0f92f66045dc4dbe2a66e546fe15c5ef..31b7cabee8b4eca0bbf4a19e83dced50c8dc9c17 100644 (file)
--- a/client.go
+++ b/client.go
@@ -924,6 +924,11 @@ func (me *Client) addConnection(t *torrent, c *connection) bool {
        if me.stopped() {
                return false
        }
+       select {
+       case <-t.ceasingNetworking:
+               return false
+       default:
+       }
        for _, c0 := range t.Conns {
                if c.PeerID == c0.PeerID {
                        // Already connected to a client with that ID.
@@ -936,6 +941,11 @@ func (me *Client) addConnection(t *torrent, c *connection) bool {
 
 func (me *Client) openNewConns() {
        for _, t := range me.torrents {
+               select {
+               case <-t.ceasingNetworking:
+                       continue
+               default:
+               }
                for len(t.Peers) != 0 {
                        if me.halfOpen >= me.halfOpenLimit {
                                return
@@ -994,7 +1004,8 @@ func newTorrent(ih InfoHash, announceList [][]string) (t *torrent, err error) {
                InfoHash: ih,
                Peers:    make(map[peersKey]Peer, 2000),
 
-               closing: make(chan struct{}),
+               closing:           make(chan struct{}),
+               ceasingNetworking: make(chan struct{}),
        }
        t.Trackers = make([][]tracker.Client, len(announceList))
        for tierIndex := range announceList {
@@ -1149,7 +1160,7 @@ func (cl *Client) announceTorrentDHT(t *torrent) {
                                        log.Printf("error adding peers from dht for torrent %q: %s", t, err)
                                        break getPeers
                                }
-                       case <-t.closing:
+                       case <-t.ceasingNetworking:
                                ps.Close()
                                return
                        }
@@ -1168,10 +1179,12 @@ func (cl *Client) announceTorrent(t *torrent) {
        }
 newAnnounce:
        for {
-               cl.mu.Lock()
-               if t.isClosed() {
+               select {
+               case <-t.ceasingNetworking:
                        return
+               default:
                }
+               cl.mu.Lock()
                req.Left = t.BytesLeft()
                cl.mu.Unlock()
                for _, tier := range t.Trackers {
@@ -1365,6 +1378,9 @@ func (me *Client) pieceHashed(t *torrent, piece pp.Integer, correct bool) {
                        }
                }
        }
+       if t.haveAllPieces() && me.noUpload {
+               t.CeaseNetworking()
+       }
        me.event.Broadcast()
 }
 
index 0585a5f1dd4835750d7d34d1128b8a3fd39c3939..1dc6cd6c962fe173b1f8ad362eba40368ab629c0 100644 (file)
@@ -44,7 +44,10 @@ type peersKey struct {
 }
 
 type torrent struct {
-       closing                     chan struct{}
+       stateMu           sync.Mutex
+       closing           chan struct{}
+       ceasingNetworking chan struct{}
+
        InfoHash                    InfoHash
        Pieces                      []*torrentPiece
        IncompletePiecesByBytesLeft *OrderedList
@@ -64,6 +67,20 @@ type torrent struct {
        metadataHave []bool
 }
 
+func (t *torrent) CeaseNetworking() {
+       t.stateMu.Lock()
+       defer t.stateMu.Unlock()
+       select {
+       case <-t.ceasingNetworking:
+               return
+       default:
+       }
+       close(t.ceasingNetworking)
+       for _, c := range t.Conns {
+               c.Close()
+       }
+}
+
 func (t *torrent) assertIncompletePiecesByBytesLeftOrdering() {
        allIndexes := make(map[int]struct{}, t.NumPieces())
        for i := 0; i < t.NumPieces(); i++ {
@@ -346,6 +363,7 @@ func (t *torrent) Close() (err error) {
        if t.isClosed() {
                return
        }
+       t.CeaseNetworking()
        close(t.closing)
        t.dataLock.Lock()
        t.Data.Close()