Changeset 108


Ignore:
Timestamp:
Feb 8, 2006, 9:26:27 PM (15 years ago)
Author:
titer
Message:

Randomly choke and unchoke peers who upload less than 0.1KB/s to us,
instead of trying to compare their upload rates

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/choking.c

    r95 r108  
    2828#endif
    2929
     30/* We may try to allocate and free tables of size 0. Quick and dirty
     31   way to handle it... */
     32void * __malloc( int size )
     33{
     34    if( !size )
     35        return NULL;
     36    return malloc( size );
     37}
     38void __free( void * p )
     39{
     40    if( p )
     41        free( p );
     42}
     43#define malloc __malloc
     44#define free   __free
     45
    3046struct tr_choking_s
    3147{
     
    6379}
    6480
    65 #define sortPeersAscending(p,c)  sortPeers(p,c,0)
    66 #define sortPeersDescending(p,c) sortPeers(p,c,1)
    67 static inline void sortPeers( tr_peer_t ** peers, int count, int order )
    68 {
    69     int i, j, sorted;
    70     float rate1, rate2;
    71     tr_peer_t * tmp;
    72 
    73     for( i = count - 1; i > 0; i-- )
    74     {
     81#define sortPeersAscending(a,ac,z,zc,n,nc)  sortPeers(a,ac,z,zc,n,nc,0)
     82#define sortPeersDescending(a,ac,z,zc,n,nc) sortPeers(a,ac,z,zc,n,nc,1)
     83static inline void sortPeers( tr_peer_t ** all, int allCount,
     84                              tr_peer_t ** zero, int * zeroCount,
     85                              tr_peer_t ** nonZero, int * nonZeroCount,
     86                              int order )
     87{
     88    int i, shuffle;
     89
     90    /* Seperate uploaders from non-uploaders */
     91    *zeroCount    = 0;
     92    *nonZeroCount = 0;
     93    for( i = 0; i < allCount; i++ )
     94    {
     95        if( tr_peerDownloadRate( all[i] ) < 0.1 )
     96            zero[(*zeroCount)++] = all[i];
     97        else
     98            nonZero[(*nonZeroCount)++] = all[i];
     99    }
     100
     101    /* Randomly shuffle non-uploaders, so they are treated equally */
     102    if( *zeroCount && ( shuffle = tr_rand( *zeroCount ) ) )
     103    {
     104        tr_peer_t ** bak;
     105        bak = malloc( shuffle * sizeof( tr_peer_t * ) );
     106        memcpy( bak, zero, shuffle * sizeof( tr_peer_t * ) );
     107        memmove( zero, &zero[shuffle],
     108                 ( *zeroCount - shuffle ) * sizeof( tr_peer_t * ) );
     109        memcpy( &zero[*zeroCount - shuffle], bak,
     110                 shuffle * sizeof( tr_peer_t * ) );
     111        free( bak );
     112    }
     113
     114    /* Sort uploaders by download rate */
     115    for( i = *nonZeroCount - 1; i > 0; i-- )
     116    {
     117        float rate1, rate2;
     118        tr_peer_t * tmp;
     119        int j, sorted;
     120
    75121        sorted = 1;
    76122        for( j = 0; j < i; j++ )
    77123        {
    78             rate1 = tr_peerDownloadRate( peers[j] );
    79             rate2 = tr_peerDownloadRate( peers[j+1] );
     124            rate1 = tr_peerDownloadRate( nonZero[j] );
     125            rate2 = tr_peerDownloadRate( nonZero[j+1] );
    80126            if( order ? ( rate1 < rate2 ) : ( rate1 > rate2 ) )
    81127            {
    82                 tmp        = peers[j];
    83                 peers[j]   = peers[j+1];
    84                 peers[j+1] = tmp;
    85                 sorted     = 0;
     128                tmp          = nonZero[j];
     129                nonZero[j]   = nonZero[j+1];
     130                nonZero[j+1] = tmp;
     131                sorted       = 0;
    86132            }
    87133        }
     
    93139void tr_chokingPulse( tr_choking_t * c )
    94140{
    95     int i, j, peersTotalCount;
    96     tr_peer_t * peer;
    97     tr_peer_t ** peersCanChoke, ** peersCanUnchoke;
    98     int peersCanChokeCount, peersCanUnchokeCount, unchokedCount;
     141    int i, peersTotalCount, unchoked;
     142    tr_peer_t ** canChoke, ** canUnchoke;
     143    tr_peer_t ** canChokeZero, ** canUnchokeZero;
     144    tr_peer_t ** canChokeNonZero, ** canUnchokeNonZero;
     145    int canChokeCount, canUnchokeCount;
     146    int canChokeZeroCount, canUnchokeZeroCount;
     147    int canChokeNonZeroCount, canUnchokeNonZeroCount;
    99148    tr_torrent_t * tor;
    100149    uint64_t now = tr_date();
     
    111160    }
    112161
    113     peersCanChoke   = malloc( peersTotalCount * sizeof( tr_peer_t * ) );
    114     peersCanUnchoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) );
    115     peersCanChokeCount   = 0;
    116     peersCanUnchokeCount = 0;
    117     unchokedCount        = 0;
     162    canChoke   = malloc( peersTotalCount * sizeof( tr_peer_t * ) );
     163    canUnchoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) );
     164    canChokeCount   = 0;
     165    canUnchokeCount = 0;
     166    unchoked        = 0;
    118167
    119168    for( i = 0; i < c->h->torrentCount; i++ )
    120169    {
     170        tr_peer_t * peer;
     171        int j;
     172
    121173        tor = c->h->torrents[i];
    122174        for( j = 0; j < tor->peerCount; j++ )
     
    141193            if( tr_peerIsUnchoked( peer ) )
    142194            {
    143                 unchokedCount++;
     195                unchoked++;
    144196                if( tr_peerLastChoke( peer ) + 10000 < now )
    145                     peersCanChoke[peersCanChokeCount++] = peer;
     197                    canChoke[canChokeCount++] = peer;
    146198            }
    147199            else
    148200            {
    149201                if( tr_peerLastChoke( peer ) + 10000 < now )
    150                     peersCanUnchoke[peersCanUnchokeCount++] = peer;
     202                    canUnchoke[canUnchokeCount++] = peer;
    151203            }
    152204        }
    153205    }
    154206
    155     /* Sort peers by the rate we are downloading from them. */
    156     sortPeersDescending( peersCanChoke, peersCanChokeCount );
    157     sortPeersAscending( peersCanUnchoke, peersCanUnchokeCount );
    158 
    159     if( unchokedCount > c->slots && peersCanChokeCount > 0 )
    160     {
    161         /* We have more open slots than what we should have (the user
    162            has just lowered his upload limit. We need to choke some of the
    163            peers we are uploading to. */
    164         int willChoke;
    165         willChoke = MIN( peersCanChokeCount, unchokedCount - c->slots );
    166         for( i = 0; i < willChoke; i++ )
    167             tr_peerChoke( peersCanChoke[--peersCanChokeCount] );
    168     }
    169     else if( unchokedCount < c->slots && peersCanUnchokeCount > 0 )
    170     {
    171         /* We have unused open slots. Let's unchoke some people. */
    172         int willUnchoke;
    173         willUnchoke = MIN( peersCanUnchokeCount, c->slots - unchokedCount );
    174         for( i = 0; i < willUnchoke; i++ )
    175             tr_peerUnchoke( peersCanUnchoke[--peersCanUnchokeCount] );
    176     }
    177 
    178     while( peersCanChokeCount > 0 && peersCanUnchokeCount > 0 )
    179     {
    180         /* All slots are used and more peers are waiting. If
    181            applicable, choke some peers in favor of others who are
    182            uploading more to us. */
    183         if( tr_peerDownloadRate( peersCanUnchoke[peersCanUnchokeCount - 1] )
    184                 < tr_peerDownloadRate( peersCanChoke[peersCanChokeCount - 1] ) )
     207    canChokeZero      = malloc( canChokeCount * sizeof( tr_peer_t * ) );
     208    canChokeNonZero   = malloc( canChokeCount * sizeof( tr_peer_t * ) );
     209    canUnchokeZero    = malloc( canUnchokeCount * sizeof( tr_peer_t * ) );
     210    canUnchokeNonZero = malloc( canUnchokeCount * sizeof( tr_peer_t * ) );
     211
     212    sortPeersDescending( canChoke, canChokeCount,
     213                         canChokeZero, &canChokeZeroCount,
     214                         canChokeNonZero, &canChokeNonZeroCount);
     215    sortPeersAscending( canUnchoke, canUnchokeCount,
     216                        canUnchokeZero, &canUnchokeZeroCount,
     217                        canUnchokeNonZero, &canUnchokeNonZeroCount);
     218
     219    free( canChoke );
     220    free( canUnchoke );
     221
     222    /* If we have more open slots than what we should have (the user has
     223       just lowered his upload limit), we need to choke some of the
     224       peers we are uploading to. We start with the peers who aren't
     225       uploading to us, then those we upload the least. */
     226    while( unchoked > c->slots && canChokeZeroCount > 0 )
     227    {
     228        tr_peerChoke( canChokeZero[--canChokeZeroCount] );
     229        unchoked--;
     230    }
     231    while( unchoked > c->slots && canChokeNonZeroCount > 0 )
     232    {
     233        tr_peerChoke( canChokeNonZero[--canChokeNonZeroCount] );
     234        unchoked--;
     235    }
     236
     237    /* If we have unused open slots, let's unchoke some people. We start
     238       with the peers who are uploading to us the most. */
     239    while( unchoked < c->slots && canUnchokeNonZeroCount > 0 )
     240    {
     241        tr_peerUnchoke( canUnchokeNonZero[--canUnchokeNonZeroCount] );
     242        unchoked++;
     243    }
     244    while( unchoked < c->slots && canUnchokeZeroCount > 0 )
     245    {
     246        tr_peerUnchoke( canUnchokeZero[--canUnchokeZeroCount] );
     247        unchoked++;
     248    }
     249
     250    /* Choke peers who aren't uploading if there are good peers waiting
     251       for an unchoke */
     252    while( canChokeZeroCount > 0 && canUnchokeNonZeroCount > 0 )
     253    {
     254        tr_peerChoke( canChokeZero[--canChokeZeroCount] );
     255        tr_peerUnchoke( canUnchokeNonZero[--canUnchokeNonZeroCount] );
     256    }
     257
     258    /* Choke peers who aren't uploading that much if there are choked
     259       peers who are uploading more */
     260    while( canChokeNonZeroCount > 0 && canUnchokeNonZeroCount > 0 )
     261    {
     262        if( tr_peerDownloadRate( canUnchokeNonZero[canUnchokeNonZeroCount - 1] )
     263            < tr_peerDownloadRate( canChokeNonZero[canChokeNonZeroCount - 1] ) )
    185264            break;
    186265
    187         tr_peerChoke( peersCanChoke[--peersCanChokeCount] );
    188         tr_peerUnchoke( peersCanUnchoke[--peersCanUnchokeCount] );
    189     }
    190 
    191     free( peersCanChoke );
    192     free( peersCanUnchoke );
     266        tr_peerChoke( canChokeNonZero[--canChokeNonZeroCount] );
     267        tr_peerUnchoke( canUnchokeNonZero[--canUnchokeNonZeroCount] );
     268    }
     269
     270    /* Some unchoked peers still aren't uploading to us, let's give a
     271       chance to other non-uploaders */
     272    while( canChokeZeroCount > 0 && canUnchokeZeroCount > 0 )
     273    {
     274        tr_peerChoke( canChokeZero[--canChokeZeroCount] );
     275        tr_peerUnchoke( canUnchokeZero[--canUnchokeZeroCount] );
     276    }
     277
     278    free( canChokeZero );
     279    free( canChokeNonZero );
     280    free( canUnchokeZero );
     281    free( canUnchokeNonZero );
    193282
    194283    /* Unlock all torrents */
Note: See TracChangeset for help on using the changeset viewer.