struct ChokeData
{
- tr_bool doUnchoke;
tr_bool isInterested;
+ tr_bool wasChoked;
tr_bool isChoked;
int rate;
int salt;
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;
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 )
{
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 ) );
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 );
}
* 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;
if(( n = tr_ptrArraySize( &randPool )))
{
c = tr_ptrArrayNth( &randPool, tr_cryptoWeakRandInt( n ));
- c->doUnchoke = 1;
+ c->isChoked = FALSE;
t->optimistic = c->peer;
}
}
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 );
****
***/
-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 )