diff --git a/libtransmission/peer-mgr.c b/libtransmission/peer-mgr.c index 7116ebc47..725cdf992 100644 --- a/libtransmission/peer-mgr.c +++ b/libtransmission/peer-mgr.c @@ -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; iuploadSlotsPerTorrent; ++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 && (idoUnchoke = 1; + c->isChoked = FALSE; t->optimistic = c->peer; } @@ -2729,7 +2745,7 @@ rechokeUploads( Torrent * t, const uint64_t now ) } for( i=0; imsgs, !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 )