]> granicus.if.org Git - transmission/commitdiff
(trunk libT) #3568 "don't optimistically unchoke torrents when our bandwidth is maxed...
authorCharles Kerr <charles@transmissionbt.com>
Sun, 19 Sep 2010 01:04:49 +0000 (01:04 +0000)
committerCharles Kerr <charles@transmissionbt.com>
Sun, 19 Sep 2010 01:04:49 +0000 (01:04 +0000)
libtransmission/peer-mgr.c

index 7116ebc474bbcb86ecab60025307ba1d5f0468cc..725cdf99279e09f420f2bcf1956abae8a0c1b5e1 100644 (file)
@@ -2579,8 +2579,8 @@ rechokeDownloads( Torrent * t )
 
 struct ChokeData
 {
-    tr_bool         doUnchoke;
     tr_bool         isInterested;
+    tr_bool         wasChoked;
     tr_bool         isChoked;
     int             rate;
     int             salt;
@@ -2597,8 +2597,8 @@ compareChoke( const void * va,
     if( a->rate != b->rate ) /* prefer higher overall speeds */
         return a->rate > b->rate ? -1 : 1;
 
-    if( a->isChoked != b->isChoked ) /* prefer unchoked */
-        return a->isChoked ? 1 : -1;
+    if( a->wasChoked != b->wasChoked ) /* prefer unchoked */
+        return a->wasChoked ? 1 : -1;
 
     if( a->salt != b->salt ) /* random order */
         return a->salt - b->salt;
@@ -2636,6 +2636,19 @@ getRate( const tr_torrent * tor, struct peer_atom * atom, uint64_t now )
     return Bps;
 }
 
+static inline tr_bool
+isBandwidthMaxedOut( const tr_bandwidth * b,
+                     const uint64_t now_msec, tr_direction dir )
+{
+    if( !tr_bandwidthIsLimited( b, dir ) )
+        return FALSE;
+    else {
+        const int got = tr_bandwidthGetPieceSpeed_Bps( b, now_msec, dir );
+        const int want = tr_bandwidthGetDesiredSpeed_Bps( b, dir );
+        return got >= want;
+    }
+}
+
 static void
 rechokeUploads( Torrent * t, const uint64_t now )
 {
@@ -2645,6 +2658,7 @@ rechokeUploads( Torrent * t, const uint64_t now )
     struct ChokeData * choke = tr_new0( struct ChokeData, peerCount );
     const tr_session * session = t->manager->session;
     const int chokeAll = !tr_torrentIsPieceTransferAllowed( t->tor, TR_CLIENT_TO_PEER );
+    const tr_bool isMaxedOut = isBandwidthMaxedOut( t->tor->bandwidth, now, TR_UP );
 
     assert( torrentIsLocked( t ) );
 
@@ -2671,7 +2685,7 @@ rechokeUploads( Torrent * t, const uint64_t now )
             struct ChokeData * n = &choke[size++];
             n->peer         = peer;
             n->isInterested = peer->peerIsInterested;
-            n->isChoked     = peer->peerIsChoked;
+            n->wasChoked    = peer->peerIsChoked;
             n->rate         = getRate( t->tor, atom, now );
             n->salt         = tr_cryptoWeakRandInt( INT_MAX );
         }
@@ -2691,16 +2705,18 @@ rechokeUploads( Torrent * t, const uint64_t now )
      * downloader with the worst upload rate gets choked. If a client has
      * a complete file, it uses its upload rate rather than its download
      * rate to decide which peers to unchoke.
+     *
+     * If our bandwidth is maxed out, don't unchoke any more peers.
      */
     unchokedInterested = 0;
     for( i=0; i<size && unchokedInterested<session->uploadSlotsPerTorrent; ++i ) {
-        choke[i].doUnchoke = 1;
+        choke[i].isChoked = isMaxedOut ? choke[i].wasChoked : FALSE;
         if( choke[i].isInterested )
             ++unchokedInterested;
     }
 
     /* optimistic unchoke */
-    if( i < size )
+    if( !isMaxedOut && (i<size) )
     {
         int n;
         struct ChokeData * c;
@@ -2721,7 +2737,7 @@ rechokeUploads( Torrent * t, const uint64_t now )
         if(( n = tr_ptrArraySize( &randPool )))
         {
             c = tr_ptrArrayNth( &randPool, tr_cryptoWeakRandInt( n ));
-            c->doUnchoke = 1;
+            c->isChoked = FALSE;
             t->optimistic = c->peer;
         }
 
@@ -2729,7 +2745,7 @@ rechokeUploads( Torrent * t, const uint64_t now )
     }
 
     for( i=0; i<size; ++i )
-        tr_peerMsgsSetChoke( choke[i].peer->msgs, !choke[i].doUnchoke );
+        tr_peerMsgsSetChoke( choke[i].peer->msgs, choke[i].isChoked );
 
     /* cleanup */
     tr_free( choke );
@@ -3312,19 +3328,6 @@ atomPulse( int foo UNUSED, short bar UNUSED, void * vmgr )
 ****
 ***/
 
-static inline tr_bool
-isBandwidthMaxedOut( const tr_bandwidth * b,
-                     const uint64_t now_msec, tr_direction dir )
-{
-    if( !tr_bandwidthIsLimited( b, dir ) )
-        return FALSE;
-    else {
-        const int got = tr_bandwidthGetPieceSpeed_Bps( b, now_msec, dir );
-        const int want = tr_bandwidthGetDesiredSpeed_Bps( b, dir );
-        return got >= want;
-    }
-}
-
 /* is this atom someone that we'd want to initiate a connection to? */
 static tr_bool
 isPeerCandidate( const tr_torrent * tor, struct peer_atom * atom, const time_t now )