Ticket #3596: choke-2.diff

File choke-2.diff, 9.3 KB (added by charles, 12 years ago)
  • libtransmission/peer-msgs.c

     
    7171
    7272    MAX_PEX_PEER_COUNT      = 50,
    7373
    74     MIN_CHOKE_PERIOD_SEC    = 10,
    75 
    7674    /* idle seconds before we send a keepalive */
    7775    KEEPALIVE_INTERVAL_SECS = 100,
    7876
     
    737735}
    738736
    739737void
    740 tr_peerMsgsSetChoke( tr_peermsgs * msgs,
    741                      int           choke )
     738tr_peerMsgsSetChoke( tr_peermsgs * msgs, uint8_t state )
    742739{
    743     const time_t now = tr_time( );
    744     const time_t fibrillationTime = now - MIN_CHOKE_PERIOD_SEC;
     740    tr_peer * peer;
    745741
    746742    assert( msgs );
    747     assert( msgs->peer );
    748     assert( choke == 0 || choke == 1 );
     743    peer = msgs->peer;
     744    assert( peer );
     745    assert( choke==PEER_CHOKE_STATE_CHOKED ||
     746            choke==PEER_CHOKE_STATE_UNCHOKED ||
     747            choke==PEER_CHOKE_STATE_UNCHOKED_OPTIMISTIC );
    749748
    750     if( msgs->peer->chokeChangedAt > fibrillationTime )
     749    /* if the state's changed... */
     750    if( peer->peerChokeState != state )
    751751    {
    752         dbgmsg( msgs, "Not changing choke to %d to avoid fibrillation", choke );
     752        tr_bool was_choked;
     753        tr_bool is_choked;
     754
     755        /* change the state... */
     756        was_choked = tr_peerIsChoked( peer );
     757        peer->peerChokeState = state;
     758        peer->peerChokeChangedAt = tr_time( );
     759        is_choked = tr_peerIsChoked( peer );
     760
     761        if( is_choked != was_choked ) {
     762            if( is_choked )
     763                cancelAllRequestsToClient( msgs );
     764            protocolSendChoke( msgs, is_choked  );
     765        }
    753766    }
    754     else if( msgs->peer->peerIsChoked != choke )
    755     {
    756         msgs->peer->peerIsChoked = choke;
    757         if( choke )
    758             cancelAllRequestsToClient( msgs );
    759         protocolSendChoke( msgs, choke );
    760         msgs->peer->chokeChangedAt = now;
    761     }
    762767}
    763768
    764769/**
     
    12251230    const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io );
    12261231    const int reqIsValid = requestIsValid( msgs, req );
    12271232    const int clientHasPiece = reqIsValid && tr_cpPieceIsComplete( &msgs->torrent->completion, req->index );
    1228     const int peerIsChoked = msgs->peer->peerIsChoked;
     1233    const int peerIsChoked = tr_peerIsChoked( msgs->peer );
    12291234
    12301235    int allow = FALSE;
    12311236
     
    23332338    m->peer = peer;
    23342339    m->torrent = torrent;
    23352340    m->peer->clientIsChoked = 1;
    2336     m->peer->peerIsChoked = 1;
     2341    m->peer->peerChokeState = PEER_CHOKE_STATE_CHOKED;
     2342    m->peer->peerChokeChangedAt = 0;
    23372343    m->peer->clientIsInterested = 0;
    23382344    m->peer->peerIsInterested = 0;
    23392345    m->state = AWAITING_BT_LENGTH;
  • libtransmission/peer-msgs.h

     
    3636                             tr_peer_callback     * callback,
    3737                             void                 * callback_data );
    3838
    39 void         tr_peerMsgsSetChoke( tr_peermsgs *, int doChoke );
     39void         tr_peerMsgsSetChoke( tr_peermsgs *, uint8_t peer_choke_state );
    4040
    4141int          tr_peerMsgsIsReadingBlock( const tr_peermsgs * msgs, tr_block_index_t block );
    4242
  • libtransmission/peer-mgr.c

     
    5151    /* how frequently to reallocate bandwidth */
    5252    BANDWIDTH_PERIOD_MSEC = 500,
    5353
     54    /* how long an optimistic unchoke is immune from being rechoked */
     55    UNCHOKE_PERIOD_OPTIMISTIC_SEC = 30,
     56
     57    /* how long a non-optimistic unchoke is immune from being rechoked */
     58    UNCHOKE_PERIOD_SEC = 20,
     59
    5460    /* how frequently to age out old piece request lists */
    5561    REFILL_UPKEEP_PERIOD_MSEC = ( 10 * 1000 ),
    5662
     
    546552static int
    547553clientIsUploadingTo( const tr_peer * peer )
    548554{
    549     return peer->peerIsInterested && !peer->peerIsChoked;
     555    return peer->peerIsInterested && !tr_peerIsChoked( peer );
    550556}
    551557
    552558/***
     
    23412347        stat->isEncrypted         = tr_peerIoIsEncrypted( peer->io ) ? 1 : 0;
    23422348        stat->rateToPeer_KBps     = toSpeedKBps( tr_peerGetPieceSpeed_Bps( peer, now, TR_CLIENT_TO_PEER ) );
    23432349        stat->rateToClient_KBps   = toSpeedKBps( tr_peerGetPieceSpeed_Bps( peer, now, TR_PEER_TO_CLIENT ) );
    2344         stat->peerIsChoked        = peer->peerIsChoked;
     2350        stat->peerIsChoked        = tr_peerIsChoked( peer );
    23452351        stat->peerIsInterested    = peer->peerIsInterested;
    23462352        stat->clientIsChoked      = peer->clientIsChoked;
    23472353        stat->clientIsInterested  = peer->clientIsInterested;
     
    26972703}
    26982704
    26992705static void
    2700 rechokeUploads( Torrent * t, const uint64_t now )
     2706rechokeUploads( Torrent * t, const uint64_t now_msec )
    27012707{
    27022708    int i, size, unchokedInterested;
     2709    tr_bool have_optimistic = FALSE;
    27032710    const int peerCount = tr_ptrArraySize( &t->peers );
    27042711    tr_peer ** peers = (tr_peer**) tr_ptrArrayBase( &t->peers );
    27052712    struct ChokeData * choke = tr_new0( struct ChokeData, peerCount );
    27062713    const tr_session * session = t->manager->session;
    2707     const int chokeAll = !tr_torrentIsPieceTransferAllowed( t->tor, TR_CLIENT_TO_PEER );
    2708     const tr_bool isMaxedOut = isBandwidthMaxedOut( t->tor->bandwidth, now, TR_UP );
     2714    const int choke_all = !tr_torrentIsPieceTransferAllowed( t->tor, TR_CLIENT_TO_PEER );
     2715    const tr_bool is_maxed_out = isBandwidthMaxedOut( t->tor->bandwidth, now_msec, TR_UP );
    27092716
    27102717    assert( torrentIsLocked( t ) );
    27112718
    27122719    /* sort the peers by preference and rate */
    2713     for( i = 0, size = 0; i < peerCount; ++i )
     2720    for( i=size=0; i<peerCount; ++i )
    27142721    {
    27152722        tr_peer * peer = peers[i];
    27162723        struct peer_atom * atom = peer->atom;
     
    27232730        {
    27242731            tr_peerMsgsSetChoke( peer->msgs, TRUE );
    27252732        }
    2726         else if( chokeAll ) /* choke everyone if we're not uploading */
     2733        else if( choke_all ) /* choke everyone if we're not uploading */
    27272734        {
    27282735            tr_peerMsgsSetChoke( peer->msgs, TRUE );
    27292736        }
    27302737        else
    27312738        {
    2732             struct ChokeData * n = &choke[size++];
    2733             n->peer         = peer;
    2734             n->isInterested = peer->peerIsInterested;
    2735             n->wasChoked    = peer->peerIsChoked;
    2736             n->rate         = getRate( t->tor, atom, now );
    2737             n->salt         = tr_cryptoWeakRandInt( INT_MAX );
    2738             n->isChoked     = TRUE;
     2739            tr_bool can_change = TRUE;
     2740            const tr_bool is_choked = tr_peerIsChoked( peer );
     2741
     2742            if( !is_choked )
     2743            {
     2744                const tr_bool is_optimistic = peer->peerChokeState == PEER_CHOKE_STATE_UNCHOKED_OPTIMISTIC;
     2745                const int period = is_optimistic ? UNCHOKE_PERIOD_OPTIMISTIC_SEC : UNCHOKE_PERIOD_SEC;
     2746                const time_t can_choke_at = peer->peerChokeChangedAt + period;
     2747
     2748                can_change = tr_time() >= can_choke_at;
     2749
     2750                if( is_optimistic && !can_change )
     2751                    have_optimistic = TRUE;
     2752            }
     2753
     2754            if( can_change )
     2755            {
     2756                struct ChokeData * n = &choke[size++];
     2757                n->peer         = peer;
     2758                n->isInterested = peer->peerIsInterested;
     2759                n->wasChoked    = is_choked;
     2760                n->rate         = getRate( t->tor, atom, now_msec );
     2761                n->salt         = tr_cryptoWeakRandInt( INT_MAX );
     2762                n->isChoked     = TRUE;
     2763            }
    27392764        }
    27402765    }
    27412766
     
    27582783     */
    27592784    unchokedInterested = 0;
    27602785    for( i=0; i<size && unchokedInterested<session->uploadSlotsPerTorrent; ++i ) {
    2761         choke[i].isChoked = isMaxedOut ? choke[i].wasChoked : FALSE;
     2786        choke[i].isChoked = is_maxed_out ? choke[i].wasChoked : FALSE;
    27622787        if( choke[i].isInterested )
    27632788            ++unchokedInterested;
    27642789    }
    27652790
    27662791    /* optimistic unchoke */
    2767     if( !isMaxedOut && (i<size) )
     2792    if( !have_optimistic && !is_maxed_out && (i<size) )
    27682793    {
    27692794        int n;
    27702795        struct ChokeData * c;
  • libtransmission/peer-mgr.h

     
    7070/* opaque forward declaration */
    7171struct peer_atom;
    7272
     73enum
     74{
     75    PEER_CHOKE_STATE_CHOKED,
     76    PEER_CHOKE_STATE_UNCHOKED,
     77    PEER_CHOKE_STATE_UNCHOKED_OPTIMISTIC
     78};
     79
    7380/**
    7481 * State information about a connected peer.
    7582 *
     
    7885 */
    7986typedef struct tr_peer
    8087{
    81     tr_bool                  peerIsChoked;
     88    uint8_t                  peerChokeState;
    8289    tr_bool                  peerIsInterested;
    8390    tr_bool                  clientIsChoked;
    8491    tr_bool                  clientIsInterested;
     
    108115    /* the client name from the `v' string in LTEP's handshake dictionary */
    109116    char                   * client;
    110117
    111     time_t                   chokeChangedAt;
     118    time_t                   peerChokeChangedAt;
    112119
    113120    tr_recentHistory       * blocksSentToClient;
    114121    tr_recentHistory       * blocksSentToPeer;
     
    120127}
    121128tr_peer;
    122129
     130static inline tr_bool tr_peerIsChoked( const tr_peer * peer )
     131{
     132    return peer->peerChokeState == PEER_CHOKE_STATE_CHOKED;
     133}
     134
    123135const tr_address * tr_peerAddress( const tr_peer * );
    124136
    125137int tr_pexCompare( const void * a, const void * b );