Changeset 7402


Ignore:
Timestamp:
Dec 15, 2008, 9:22:08 PM (12 years ago)
Author:
charles
Message:

(trunk libT) probable fix for the "greedy peer" bug

Location:
trunk/libtransmission
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/bandwidth.c

    r7367 r7402  
    250250                   tr_direction    dir,
    251251                   int             period_msec,
    252                    tr_ptrArray   * addme_buffers )
     252                   tr_ptrArray   * iobuf_pool )
    253253{
    254254    assert( isBandwidth( b ) );
     
    269269    }
    270270
    271     /* notify the io buffers that there's more bandwidth available */
    272271    {
    273272        int i;
    274273        const int n = tr_ptrArraySize( b->iobufs );
    275274        for( i=0; i<n; ++i )
    276             tr_ptrArrayAppend( addme_buffers, tr_ptrArrayNth( b->iobufs, i ) );
     275            tr_ptrArrayAppend( iobuf_pool, tr_ptrArrayNth( b->iobufs, i ) );
    277276    }
    278277
     
    287286        struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayPeek( b->children, &n );
    288287        for( i=0; i<n; ++i )
    289             tr_bandwidthAllocate( children[i], dir, period_msec );
     288            allocateBandwidth( children[i], dir, period_msec, iobuf_pool );
    290289    }
    291290}
     
    299298    tr_ptrArray * tmp;
    300299    struct tr_iobuf ** buffers;
    301     const short what = dir==TR_UP ? EV_WRITE : EV_READ;
     300    const size_t chunkSize = 1024; /* arbitrary */
    302301
    303302    tmp = tr_ptrArrayNew( );
     
    305304    buffers = (struct tr_iobuf**) tr_ptrArrayPeek( tmp, &n );
    306305
    307     /* notify the io buffers in a random order s.t. no
    308        particular peer gets to hog all the bandwidth */
    309     while( n > 0 ) {
    310         const int i = tr_cryptoRandInt( n );
    311         tr_iobuf_enable( buffers[i], what );
    312         buffers[i] = buffers[n-1];
    313         --n;
    314     }
    315 
     306    /* loop through all the peers, reading and writing in small chunks,
     307     * until we run out of bandwidth or peers. we do it this way to
     308     * prevent one peer from using up all the bandwidth */
     309    while( n > 0 )
     310    {
     311        int i;
     312        for( i=0; i<n; )
     313        {
     314            int byteCount;
     315            if( dir == TR_UP )
     316                byteCount = tr_iobuf_flush_output_buffer( buffers[i], chunkSize );
     317            else
     318                byteCount = tr_iobuf_tryread( buffers[i], chunkSize );
     319            if( byteCount == (int)chunkSize )
     320                ++i;
     321            else
     322                buffers[i] = buffers[--n];
     323        }
     324    }
     325
     326    /* cleanup */
    316327    tr_ptrArrayFree( tmp, NULL );
    317328}
  • trunk/libtransmission/iobuf.c

    r7385 r7402  
    7070    int magicNumber;
    7171
     72    int fd;
     73
    7274    int timeout_read;  /* in seconds */
    7375    int timeout_write; /* in seconds */
     
    8991
    9092static int
    91 tr_evbuffer_write( struct evbuffer *buffer, int fd, size_t maxlen )
    92 {
    93     int n = MIN( EVBUFFER_LENGTH( buffer ), maxlen );
     93tr_evbuffer_write( struct evbuffer *buffer, int fd, size_t howmuch )
     94{
     95    int n = MIN( EVBUFFER_LENGTH( buffer ), howmuch );
    9496
    9597#ifdef WIN32
     
    107109}
    108110
     111int
     112tr_iobuf_flush_output_buffer( struct tr_iobuf * b, size_t howmuch )
     113{
     114    int res;
     115
     116    assert( isBuf( b ) );
     117
     118    howmuch = tr_bandwidthClamp( b->bandwidth, TR_UP, howmuch );
     119    howmuch = MIN( howmuch, EVBUFFER_LENGTH( b->output ) );
     120
     121    res = howmuch ? tr_evbuffer_write( b->output, b->fd, howmuch ) : 0;
     122
     123    if( ( res > 0 ) && ( b->writecb != NULL ) )
     124        (*b->writecb)( b, (size_t)res, b->cbarg );
     125
     126    if( ( res < 0 ) && ( b->errorcb != NULL ) && ( errno != EAGAIN && errno != EINTR && errno != EINPROGRESS ) )
     127        (*b->errorcb)( b, (short)res, b->cbarg );
     128
     129    return res;
     130}
     131
     132int
     133tr_iobuf_tryread( struct tr_iobuf * b, size_t howmuch )
     134{
     135    int res;
     136
     137    assert( isBuf( b ) );
     138
     139    howmuch = tr_bandwidthClamp( b->bandwidth, TR_DOWN, howmuch );
     140
     141    res = howmuch ? evbuffer_read( b->input, b->fd, howmuch ) : 0;
     142
     143    if( ( res > 0 ) && ( b->readcb != NULL ) )
     144        (*b->readcb)( b, (size_t)res, b->cbarg );
     145
     146    if( ( res < 0 ) && ( b->errorcb != NULL ) && ( errno != EAGAIN && errno != EINTR ) )
     147        (*b->errorcb)( b, (short)res, b->cbarg );
     148
     149    return res;
     150}
     151
     152
    109153static int
    110154tr_iobuf_add(struct event *ev, int timeout)
     
    259303    b = tr_new0( struct tr_iobuf, 1 );
    260304    b->magicNumber = MAGIC_NUMBER;
     305    b->fd = fd;
    261306    b->session = session;
    262307    b->bandwidth = bandwidth;
  • trunk/libtransmission/iobuf.h

    r7385 r7402  
    4545 * 2. the up/down speeds are directly constrained by our `bandwidth' object
    4646 * 3. the implementation is hidden in the .c file
     47 *
     48 * 4. a late addition nasty hack to read/write on demand, called from
     49 *    bandwidth. this actually seems to make a lot of this class redundant
     50 *    and probably should be refactored.
    4751 */
    4852struct tr_iobuf;
     
    105109int tr_iobuf_disable( struct tr_iobuf * iobuf, short event );
    106110
     111int tr_iobuf_flush_output_buffer( struct tr_iobuf * iobuf, size_t max );
     112
     113int tr_iobuf_tryread( struct tr_iobuf * iobuf, size_t max );
     114
    107115#endif
  • trunk/libtransmission/peer-io.c

    r7289 r7402  
    544544{
    545545    /* this is all kind of arbitrary, but what seems to work well is
    546      * being large enough to hold the next 15 seconds' worth of input,
    547      * or two and a half blocks, whichever is bigger.
     546     * being large enough to hold the next 20 seconds' worth of input,
     547     * or a few blocks, whichever is bigger.
    548548     * It's okay to tweak this as needed */
    549549    const double maxBlockSize = 16 * 1024; /* 16 KiB is from BT spec */
    550550    const double currentSpeed = tr_bandwidthGetPieceSpeed( io->bandwidth, TR_UP );
    551551    const double period = 20; /* arbitrary */
    552     return MAX( maxBlockSize*2.5, currentSpeed*1024*period );
     552    return MAX( maxBlockSize*5.5, currentSpeed*1024*period );
    553553}
    554554
  • trunk/libtransmission/peer-mgr.c

    r7397 r7402  
    11331133                addStrike( t, peer );
    11341134                peer->doPurge = 1;
     1135                tordbg( t, "setting doPurge because we got an EINVAL error" );
    11351136            }
    11361137            else if( ( e->err == ERANGE )
     
    11401141                /* some protocol error from the peer */
    11411142                peer->doPurge = 1;
     1143                tordbg( t, "setting doPurge because we got an ERANGE, EMSGSIZE, or ENOTCONN error" );
    11421144            }
    11431145            else /* a local error, such as an IO error */
     
    22902292            else
    22912293                ++atom->numFails;
     2294             
     2295            fprintf( stderr, "removing bad peer %s\n", tr_peerIoGetAddrStr( peer->io ) );
    22922296            tordbg( t, "removing bad peer %s", tr_peerIoGetAddrStr( peer->io ) );
    22932297            removePeer( t, peer );
Note: See TracChangeset for help on using the changeset viewer.