Changeset 3 for trunk/libtransmission


Ignore:
Timestamp:
Jan 12, 2006, 6:29:20 PM (16 years ago)
Author:
root
Message:

Update 2005-11-17

Location:
trunk/libtransmission
Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/Jamfile

    r1 r3  
    33LIBTRANSMISSION_SRC =
    44    transmission.c bencode.c net.c tracker.c peer.c inout.c
    5     metainfo.c sha1.c utils.c upload.c fdlimit.c clients.c ;
     5    metainfo.c sha1.c utils.c upload.c fdlimit.c clients.c
     6    completion.c ;
    67
    78Library       libtransmission.a       : $(LIBTRANSMISSION_SRC) ;
  • trunk/libtransmission/fastresume.h

    r2 r3  
    102102    char    * path;
    103103    int     * fileMTimes;
    104     int       i;
    105104    uint8_t * blockBitfield;
    106105
     
    131130
    132131    /* Build and write the bitfield for blocks */
    133     blockBitfield = calloc( ( tor->blockCount + 7 ) / 8, 1 );
    134     for( i = 0; i < tor->blockCount; i++ )
    135     {
    136         if( tor->blockHave[i] < 0 )
    137         {
    138             tr_bitfieldAdd( blockBitfield, i );
    139         }
    140     }
     132    blockBitfield = tr_cpBlockBitfield( tor->completion );
    141133    fwrite( blockBitfield, ( tor->blockCount + 7 ) / 8, 1, file );
    142     free( blockBitfield );
    143134
    144135    /* Write the 'slotPiece' table */
     
    223214    blockBitfield = calloc( ( tor->blockCount + 7 ) / 8, 1 );
    224215    fread( blockBitfield, ( tor->blockCount + 7 ) / 8, 1, file );
    225     tor->blockHaveCount = 0;
    226     for( i = 0; i < tor->blockCount; i++ )
    227     {
    228         if( tr_bitfieldHas( blockBitfield, i ) )
    229         {
    230             tor->blockHave[i] = -1;
    231             (tor->blockHaveCount)++;
    232         }
    233     }
     216    tr_cpBlockBitfieldSet( tor->completion, blockBitfield );
    234217    free( blockBitfield );
    235218
     
    254237            }
    255238        }
    256 
    257         for( j = tr_pieceStartBlock( i );
    258              j < tr_pieceStartBlock( i ) + tr_pieceCountBlocks( i );
    259              j++ )
    260         {
    261             if( tor->blockHave[j] > -1 )
    262             {
    263                 break;
    264             }
    265         }
    266         if( j >= tr_pieceStartBlock( i ) + tr_pieceCountBlocks( i ) )
    267         {
    268             // tr_dbg( "Piece %d is complete", i );
    269             tr_bitfieldAdd( tor->bitfield, i );
    270         }
    271239    }
    272240    // tr_dbg( "Slot used: %d", io->slotsUsed );
  • trunk/libtransmission/fdlimit.c

    r1 r3  
    3535#define STATUS_UNUSED  2
    3636#define STATUS_USED    4
     37#define STATUS_CLOSING 8
    3738    int        status;
    3839
     
    112113            !strcmp( path, f->open[i].path ) )
    113114        {
     115            if( f->open[i].status & STATUS_CLOSING )
     116            {
     117                /* Wait until the file is closed */
     118                tr_lockUnlock( f->lock );
     119                tr_wait( 10 );
     120                tr_lockLock( f->lock );
     121                i = -1;
     122                continue;
     123            }
    114124            winner = i;
    115125            goto done;
     
    135145        for( i = 0; i < TR_MAX_OPEN_FILES; i++ )
    136146        {
    137             if( f->open[i].status & STATUS_USED )
     147            if( !( f->open[i].status & STATUS_UNUSED ) )
    138148            {
    139149                continue;
     
    148158        if( winner >= 0 )
    149159        {
     160            /* Close the file: we mark it as closing then release the
     161               lock while doing so, because fclose may take same time
     162               and we don't want to block other threads */
    150163            tr_dbg( "Closing %s", f->open[winner].path );
     164            f->open[winner].status = STATUS_CLOSING;
     165            tr_lockUnlock( f->lock );
    151166            fclose( f->open[winner].file );
     167            tr_lockLock( f->lock );
    152168            goto open;
    153169        }
  • trunk/libtransmission/inout.c

    r1 r3  
    137137    for( i = startBlock; i < endBlock; i++ )
    138138    {
    139         if( tor->blockHave[i] >= 0 )
     139        if( !tr_cpBlockIsComplete( tor->completion, i ) )
    140140        {
    141141            /* The piece is not complete */
     
    160160        for( i = startBlock; i < endBlock; i++ )
    161161        {
    162             tor->blockHave[i]    = 0;
    163             tor->blockHaveCount -= 1;
     162            tr_cpBlockRem( tor->completion, i );
    164163        }
    165164    }
     
    168167        tr_inf( "Piece %d (slot %d): hash OK", index,
    169168                io->pieceSlot[index] );
    170         tr_bitfieldAdd( tor->bitfield, index );
     169        tr_cpPieceAdd( tor->completion, index );
    171170    }
    172171
     
    267266    uint8_t * buf;
    268267    uint8_t hash[SHA_DIGEST_LENGTH];
    269     int startBlock, endBlock;
    270268
    271269    io->pieceSlot = malloc( inf->pieceCount * sizeof( int ) );
     
    282280    memset( io->pieceSlot, 0xFF, inf->pieceCount * sizeof( int ) );
    283281    memset( io->slotPiece, 0xFF, inf->pieceCount * sizeof( int ) );
    284     memset( tor->bitfield, 0, ( inf->pieceCount + 7 ) / 8 );
    285     memset( tor->blockHave, 0, tor->blockCount );
    286     tor->blockHaveCount = 0;
    287282
    288283    /* Check pieces */
     
    305300            if( !memcmp( hash, &inf->pieces[20*j], SHA_DIGEST_LENGTH ) )
    306301            {
    307                 int k;
    308302                io->pieceSlot[j] = i;
    309303                io->slotPiece[i] = j;
    310                 tr_bitfieldAdd( tor->bitfield, j );
    311 
    312                 startBlock = tr_pieceStartBlock( j );
    313                 endBlock   = startBlock + tr_pieceCountBlocks( j );
    314                 for( k = startBlock; k < endBlock; k++ )
    315                 {
    316                     tor->blockHave[k] = -1;
    317                     tor->blockHaveCount++;
    318                 }
     304
     305                tr_cpPieceAdd( tor->completion, j );
    319306                break;
    320307            }
     
    333320            io->pieceSlot[inf->pieceCount - 1] = i;
    334321            io->slotPiece[i]                   = inf->pieceCount - 1;
    335             tr_bitfieldAdd( tor->bitfield, inf->pieceCount - 1 );
    336 
    337             startBlock = tr_pieceStartBlock( inf->pieceCount - 1 );
    338             endBlock   = startBlock +
    339                 tr_pieceCountBlocks( inf->pieceCount - 1 );
    340             for( j = startBlock; j < endBlock; j++ )
    341             {
    342                 tor->blockHave[j] = -1;
    343                 tor->blockHaveCount++;
    344             }
     322
     323            tr_cpPieceAdd( tor->completion, inf->pieceCount - 1 );
    345324        }
    346325    }
     
    411390    {
    412391        asprintf( &path, "%s/%s", tor->destination, inf->files[i].name );
     392        tr_lockUnlock( tor->lock );
    413393        file = tr_fdFileOpen( tor->fdlimit, path );
     394        tr_lockLock( tor->lock );
    414395        free( path );
    415396
     
    422403                          (uint64_t) size );
    423404
     405        tr_lockUnlock( tor->lock );
    424406        if( fseeko( file, posInFile, SEEK_SET ) )
    425407        {
     408            tr_lockLock( tor->lock );
    426409            return 1;
    427410        }
     
    430413            if( fwrite( buf, willRead, 1, file ) != 1 )
    431414            {
     415                tr_lockLock( tor->lock );
    432416                return 1;
    433417            }
     
    437421            if( fread( buf, willRead, 1, file ) != 1 )
    438422            {
     423                tr_lockLock( tor->lock );
    439424                return 1;
    440425            }
    441426        }
    442 
     427        tr_lockLock( tor->lock );
    443428        tr_fdFileRelease( tor->fdlimit, file );
    444429
  • trunk/libtransmission/internal.h

    r2 r3  
    108108
    109109typedef struct tr_torrent_s tr_torrent_t;
     110typedef struct tr_completion_s tr_completion_t;
    110111
    111112#include "bencode.h"
     
    130131
    131132    char            * id;
     133    char            * key;
    132134
    133135    /* An escaped string used to include the hash in HTTP queries */
     
    143145    int               blockCount;
    144146   
     147#if 0
    145148    /* Status for each block
    146149       -1 = we have it
     
    149152    int               blockHaveCount;
    150153    uint8_t         * bitfield;
     154#endif
     155    tr_completion_t * completion;
    151156
    152157    volatile char     die;
     
    171176
    172177#include "utils.h"
     178#include "completion.h"
    173179
    174180struct tr_handle_s
     
    183189
    184190    char           id[21];
     191    char           key[21];
    185192    char           prefsDirectory[256];
    186193};
  • trunk/libtransmission/peer.c

    r2 r3  
    170170        r     = &peer->inRequests[j];
    171171        block = tr_block( r->index,r->begin );
    172         if( tor->blockHave[block] > 0 )
    173         {
    174           (tor->blockHave[block])--;
    175         }
     172        tr_cpDownloaderRem( tor->completion, block );
    176173    }
    177174    if( !peer->amChoking )
     
    272269        peer = tor->peers[i];
    273270
    274         /* Connect */
    275         if( ( peer->status & PEER_STATUS_IDLE ) &&
    276             !tr_fdSocketWillCreate( tor->fdlimit, 0 ) )
    277         {
    278             peer->socket = tr_netOpen( peer->addr, peer->port );
    279             if( peer->socket < 0 )
    280             {
    281                 peer_dbg( "connection failed" );
    282                 goto dropPeer;
    283             }
    284             peer->status = PEER_STATUS_CONNECTING;
    285         }
    286 
    287         /* Try to send handshake */
    288         if( peer->status & PEER_STATUS_CONNECTING )
    289         {
    290             uint8_t buf[68];
    291             tr_info_t * inf = &tor->info;
    292 
    293             buf[0] = 19;
    294             memcpy( &buf[1], "BitTorrent protocol", 19 );
    295             memset( &buf[20], 0, 8 );
    296             memcpy( &buf[28], inf->hash, 20 );
    297             memcpy( &buf[48], tor->id, 20 );
    298 
    299             ret = tr_netSend( peer->socket, buf, 68 );
     271        if( peer->status < PEER_STATUS_HANDSHAKE )
     272        {
     273            i++;
     274            continue;
     275        }
     276
     277        /* Try to read */
     278        for( ;; )
     279        {
     280            if( peer->size < 1 )
     281            {
     282                peer->size = 1024;
     283                peer->buf  = malloc( peer->size );
     284            }
     285            else if( peer->pos >= peer->size )
     286            {
     287                peer->size *= 2;
     288                peer->buf   = realloc( peer->buf, peer->size );
     289            }
     290            ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
     291                              peer->size - peer->pos );
    300292            if( ret & TR_NET_CLOSE )
    301293            {
     
    303295                goto dropPeer;
    304296            }
    305             else if( !( ret & TR_NET_BLOCK ) )
    306             {
    307                 peer_dbg( "SEND handshake" );
    308                 peer->status = PEER_STATUS_HANDSHAKE;
    309             }
    310         }
    311 
    312         /* Try to read */
    313         if( peer->status >= PEER_STATUS_HANDSHAKE )
    314         {
    315             for( ;; )
    316             {
    317                 if( peer->size < 1 )
    318                 {
    319                     peer->size = 1024;
    320                     peer->buf  = malloc( peer->size );
    321                 }
    322                 else if( peer->pos >= peer->size )
    323                 {
    324                     peer->size *= 2;
    325                     peer->buf   = realloc( peer->buf, peer->size );
    326                 }
    327                 ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
    328                                   peer->size - peer->pos );
    329                 if( ret & TR_NET_CLOSE )
    330                 {
    331                     peer_dbg( "connection closed" );
    332                     goto dropPeer;
    333                 }
    334                 else if( ret & TR_NET_BLOCK )
     297            else if( ret & TR_NET_BLOCK )
     298            {
     299                break;
     300            }
     301            peer->date  = tr_date();
     302            peer->pos  += ret;
     303            if( parseBuf( tor, peer, ret ) )
     304            {
     305                goto dropPeer;
     306            }
     307        }
     308
     309        if( peer->status < PEER_STATUS_CONNECTED )
     310        {
     311            i++;
     312            continue;
     313        }
     314
     315        /* Try to write */
     316writeBegin:
     317
     318        /* Send all smaller messages regardless of the upload cap */
     319        while( ( p = messagesPending( peer, &size ) ) )
     320        {
     321            ret = tr_netSend( peer->socket, p, size );
     322            if( ret & TR_NET_CLOSE )
     323            {
     324                goto dropPeer;
     325            }
     326            else if( ret & TR_NET_BLOCK )
     327            {
     328                goto writeEnd;
     329            }
     330            messagesSent( peer, ret );
     331        }
     332
     333        /* Send pieces if we can */
     334        while( ( p = blockPending( tor, peer, &size ) ) )
     335        {
     336            if( !tr_uploadCanUpload( tor->upload ) )
     337            {
     338                break;
     339            }
     340
     341            ret = tr_netSend( peer->socket, p, size );
     342            if( ret & TR_NET_CLOSE )
     343            {
     344                goto dropPeer;
     345            }
     346            else if( ret & TR_NET_BLOCK )
     347            {
     348                break;
     349            }
     350
     351            blockSent( peer, ret );
     352            tr_uploadUploaded( tor->upload, ret );
     353
     354            tor->uploaded[9] += ret;
     355            peer->outTotal   += ret;
     356            peer->outDate     = tr_date();
     357
     358            /* In case this block is done, you may have messages
     359               pending. Send them before we start the next block */
     360            goto writeBegin;
     361        }
     362writeEnd:
     363
     364        /* Ask for a block whenever possible */
     365        if( !tr_cpIsSeeding( tor->completion ) &&
     366            !peer->amInterested && tor->peerCount > TR_MAX_PEER_COUNT - 2 )
     367        {
     368            /* This peer is no use to us, and it seems there are
     369               more */
     370            peer_dbg( "not interesting" );
     371            tr_peerRem( tor, i );
     372            continue;
     373        }
     374
     375        if( peer->amInterested && !peer->peerChoking )
     376        {
     377            int block;
     378            while( peer->inRequestCount < OUR_REQUEST_COUNT )
     379            {
     380                block = chooseBlock( tor, peer );
     381                if( block < 0 )
    335382                {
    336383                    break;
    337384                }
    338                 peer->date  = tr_date();
    339                 peer->pos  += ret;
    340                 if( parseBuf( tor, peer, ret ) )
    341                 {
    342                     goto dropPeer;
    343                 }
    344             }
    345         }
    346 
    347         /* Try to write */
    348 writeBegin:
    349 
    350         /* Send all smaller messages regardless of the upload cap */
    351         while( ( p = messagesPending( peer, &size ) ) )
    352         {
    353             ret = tr_netSend( peer->socket, p, size );
    354             if( ret & TR_NET_CLOSE )
    355             {
    356                 goto dropPeer;
    357             }
    358             else if( ret & TR_NET_BLOCK )
    359             {
    360                 goto writeEnd;
    361             }
    362             messagesSent( peer, ret );
    363         }
    364 
    365         /* Send pieces if we can */
    366         while( ( p = blockPending( tor, peer, &size ) ) )
    367         {
    368             if( !tr_uploadCanUpload( tor->upload ) )
    369             {
    370                 break;
    371             }
    372 
    373             ret = tr_netSend( peer->socket, p, size );
    374             if( ret & TR_NET_CLOSE )
    375             {
    376                 goto dropPeer;
    377             }
    378             else if( ret & TR_NET_BLOCK )
    379             {
    380                 break;
    381             }
    382 
    383             blockSent( peer, ret );
    384             tr_uploadUploaded( tor->upload, ret );
    385 
    386             tor->uploaded[9] += ret;
    387             peer->outTotal   += ret;
    388             peer->outDate     = tr_date();
    389 
    390             /* In case this block is done, you may have messages
    391                pending. Send them before we start the next block */
    392             goto writeBegin;
    393         }
    394 writeEnd:
    395 
    396         /* Connected peers: ask for a block whenever possible */
    397         if( peer->status & PEER_STATUS_CONNECTED )
    398         {
    399             if( tor->blockHaveCount < tor->blockCount &&
    400                 !peer->amInterested && tor->peerCount > TR_MAX_PEER_COUNT - 2 )
    401             {
    402                 /* This peer is no use to us, and it seems there are
    403                    more */
    404                 peer_dbg( "not interesting" );
    405                 tr_peerRem( tor, i );
    406                 continue;
    407             }
    408 
    409             if( peer->amInterested && !peer->peerChoking )
    410             {
    411                 int block;
    412                 while( peer->inRequestCount < OUR_REQUEST_COUNT )
    413                 {
    414                     block = chooseBlock( tor, peer );
    415                     if( block < 0 )
    416                     {
    417                         break;
    418                     }
    419                     sendRequest( tor, peer, block );
    420                 }
     385                sendRequest( tor, peer, block );
    421386            }
    422387        }
  • trunk/libtransmission/peermessages.h

    r2 r3  
    216216    TR_HTONL( 1 + bitfieldSize, p );
    217217    p[4] = 5;
    218     memcpy( &p[5], tor->bitfield, bitfieldSize );
     218    memcpy( &p[5], tr_cpPieceBitfield( tor->completion ), bitfieldSize );
    219219
    220220    peer_dbg( "SEND bitfield" );
     
    258258    TR_HTONL( r->length, p + 13 );
    259259
    260     /* Remember that we have one more uploader for this block */
    261     (tor->blockHave[block])++;
     260    tr_cpDownloaderAdd( tor->completion, block );
    262261
    263262    peer_dbg( "SEND request %d/%d (%d bytes)",
  • trunk/libtransmission/peerparse.h

    r2 r3  
    5252        {
    5353            r = &peer->inRequests[i];
    54             if( tor->blockHave[tr_block(r->index,r->begin)] > 0 )
    55             {
    56                 tor->blockHave[tr_block(r->index,r->begin)]--;
    57             }
     54            tr_cpDownloaderRem( tor->completion, tr_block(r->index,r->begin) );
    5855        }
    5956        peer->inRequestCount = 0;
     
    246243            {
    247244                r = &peer->inRequests[j];
    248                 if( tor->blockHave[tr_block(r->index,r->begin)] > 0 )
    249                 {
    250                     tor->blockHave[tr_block(r->index,r->begin)]--;
    251                 }
     245                tr_cpDownloaderRem( tor->completion,
     246                                    tr_block(r->index,r->begin) );
    252247            }
    253248            suckyClient = 1;
     
    275270
    276271    block = tr_block( r->index, r->begin );
    277     if( tor->blockHave[block] < 0 )
     272    if( tr_cpBlockIsComplete( tor->completion, block ) )
    278273    {
    279274        peer_dbg( "have this block already" );
     
    284279    }
    285280
    286     tor->blockHave[block]  = -1;
    287     tor->blockHaveCount   +=  1;
     281    tr_cpBlockAdd( tor->completion, block );
    288282    tr_ioWrite( tor->io, index, begin, len - 9, &p[8] );
     283    tr_cpDownloaderRem( tor->completion, block );
    289284
    290285    sendCancel( tor, block );
    291286
    292     if( tr_bitfieldHas( tor->bitfield, index ) )
     287    if( tr_cpPieceIsComplete( tor->completion, index ) )
    293288    {
    294289        tr_peer_t * otherPeer;
  • trunk/libtransmission/peerutils.h

    r2 r3  
    164164    }
    165165
     166    /* Connect */
     167    if( ( peer->status & PEER_STATUS_IDLE ) &&
     168        !tr_fdSocketWillCreate( tor->fdlimit, 0 ) )
     169    {
     170        peer->socket = tr_netOpen( peer->addr, peer->port );
     171        if( peer->socket < 0 )
     172        {
     173            peer_dbg( "connection failed" );
     174            tr_fdSocketClosed( tor->fdlimit, 0 );
     175            return 1;
     176        }
     177        peer->status = PEER_STATUS_CONNECTING;
     178    }
     179
     180    /* Try to send handshake */
     181    if( peer->status & PEER_STATUS_CONNECTING )
     182    {
     183        uint8_t buf[68];
     184        tr_info_t * inf = &tor->info;
     185        int ret;
     186
     187        buf[0] = 19;
     188        memcpy( &buf[1], "BitTorrent protocol", 19 );
     189        memset( &buf[20], 0, 8 );
     190        memcpy( &buf[28], inf->hash, 20 );
     191        memcpy( &buf[48], tor->id, 20 );
     192
     193        ret = tr_netSend( peer->socket, buf, 68 );
     194        if( ret & TR_NET_CLOSE )
     195        {
     196            peer_dbg( "connection closed" );
     197            return 1;
     198        }
     199        else if( !( ret & TR_NET_BLOCK ) )
     200        {
     201            peer_dbg( "SEND handshake" );
     202            peer->status = PEER_STATUS_HANDSHAKE;
     203        }
     204    }
     205
    166206    return 0;
    167207}
     
    179219    int i;
    180220    int bitfieldSize = ( inf->pieceCount + 7 ) / 8;
     221    uint8_t * bitfield = tr_cpPieceBitfield( tor->completion );
    181222
    182223    if( !peer->bitfield )
     
    188229    for( i = 0; i < bitfieldSize; i++ )
    189230    {
    190         if( ( peer->bitfield[i] & ~(tor->bitfield[i]) ) & 0xFF )
     231        if( ( peer->bitfield[i] & ~(bitfield[i]) ) & 0xFF )
    191232        {
    192233            return 1;
     
    223264    tr_info_t * inf = &tor->info;
    224265
    225     int i, j;
    226     int startBlock, endBlock, countBlocks;
     266    int i;
    227267    int missingBlocks, minMissing;
    228268    int poolSize, * pool;
     
    235275    for( i = 0; i < inf->pieceCount; i++ )
    236276    {
     277        missingBlocks = tr_cpMissingBlocksForPiece( tor->completion, i );
     278        if( missingBlocks < 1 )
     279        {
     280            /* We already have or are downloading all blocks */
     281            continue;
     282        }
    237283        if( !tr_bitfieldHas( peer->bitfield, i ) )
    238284        {
    239285            /* The peer doesn't have this piece */
    240             continue;
    241         }
    242         if( tr_bitfieldHas( tor->bitfield, i ) )
    243         {
    244             /* We already have it */
    245             continue;
    246         }
    247 
    248         /* Count how many blocks from this piece are missing */
    249         startBlock    = tr_pieceStartBlock( i );
    250         countBlocks   = tr_pieceCountBlocks( i );
    251         endBlock      = startBlock + countBlocks;
    252         missingBlocks = countBlocks;
    253         for( j = startBlock; j < endBlock; j++ )
    254         {
    255             /* TODO: optimize */
    256             if( tor->blockHave[j] )
    257             {
    258                 missingBlocks--;
    259             }
    260             if( missingBlocks > minMissing )
    261             {
    262                 break;
    263             }
    264         }
    265 
    266         if( missingBlocks < 1 )
    267         {
    268             /* We are already downloading all blocks */
    269286            continue;
    270287        }
     
    332349
    333350        /* Pick a block in this piece */
    334         startBlock = tr_pieceStartBlock( piece );
    335         endBlock   = startBlock + tr_pieceCountBlocks( piece );
    336         for( i = startBlock; i < endBlock; i++ )
    337         {
    338             if( !tor->blockHave[i] )
    339             {
    340                 block = i;
    341                 goto check;
    342             }
    343         }
    344 
     351        block = tr_cpMissingBlockInPiece( tor->completion, piece );
     352        goto check;
     353    }
     354
     355    free( pool );
     356
     357    /* "End game" mode */
     358    minDownloading = 255;
     359    block = -1;
     360    for( i = 0; i < inf->pieceCount; i++ )
     361    {
     362        int downloaders, block2;
     363        if( !tr_bitfieldHas( peer->bitfield, i ) )
     364        {
     365            /* The peer doesn't have this piece */
     366            continue;
     367        }
     368        if( tr_cpPieceIsComplete( tor->completion, i ) )
     369        {
     370            /* We already have it */
     371            continue;
     372        }
     373        block2 = tr_cpMostMissingBlockInPiece( tor->completion, i, &downloaders );
     374        if( block2 > -1 && downloaders < minDownloading )
     375        {
     376            block = block2;
     377            minDownloading = downloaders;
     378        }
     379    }
     380
     381check:
     382    if( block < 0 )
     383    {
    345384        /* Shouldn't happen */
    346385        return -1;
    347386    }
    348387
    349     free( pool );
    350 
    351     /* "End game" mode */
    352     block          = -1;
    353     minDownloading = TR_MAX_PEER_COUNT + 1;
    354     for( i = 0; i < tor->blockCount; i++ )
    355     {
    356         /* TODO: optimize */
    357         if( tr_bitfieldHas( peer->bitfield, tr_blockPiece( i ) ) &&
    358             tor->blockHave[i] >= 0 && tor->blockHave[i] < minDownloading )
    359         {
    360             block          = i;
    361             minDownloading = tor->blockHave[i];
    362         }
    363     }
    364 
    365     if( block < 0 )
    366     {
    367         /* Shouldn't happen */
    368         return -1;
    369     }
    370 
    371 check:
    372388    for( i = 0; i < peer->inRequestCount; i++ )
    373389    {
  • trunk/libtransmission/tracker.c

    r1 r3  
    246246        event = "";
    247247
    248     left  = (uint64_t) ( tor->blockCount - tor->blockHaveCount ) *
    249             (uint64_t) tor->blockSize;
    250     left  = MIN( left, inf->totalSize );
     248    left = tr_cpLeftBytes( tor->completion );
    251249
    252250    ret = snprintf( (char *) tc->buf, tc->size,
    253               "GET %s?info_hash=%s&peer_id=%s&port=%d&uploaded=%lld&"
    254               "downloaded=%lld&left=%lld&compact=1&numwant=50%s "
    255               "HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",
    256               inf->trackerAnnounce, tor->hashString, tc->id,
    257               tor->bindPort, tor->uploaded[9], tor->downloaded[9],
    258               left, event, inf->trackerAddress );
     251            "GET %s?"
     252            "info_hash=%s&"
     253            "peer_id=%s&"
     254            "port=%d&"
     255            "uploaded=%lld&"
     256            "downloaded=%lld&"
     257            "left=%lld&"
     258            "compact=1&"
     259            "numwant=50&"
     260            "key=%s"
     261            "%s "
     262            "HTTP/1.1\r\n"
     263            "Host: %s\r\n"
     264            "User-Agent: Transmission/%d.%d\r\n"
     265            "Connection: close\r\n\r\n",
     266            inf->trackerAnnounce, tor->hashString, tc->id,
     267            tor->bindPort, tor->uploaded[9], tor->downloaded[9],
     268            left, tor->key, event, inf->trackerAddress,
     269            VERSION_MAJOR, VERSION_MINOR );
    259270
    260271    ret = tr_netSend( tc->socket, tc->buf, ret );
     
    382393        tc->leechers = beFoo->val.i;
    383394    }
    384     if( tc->seeders + tc->seeders >= 50 )
     395    if( tc->seeders + tc->leechers >= 50 )
    385396    {
    386397        tc->hasManyPeers = 1;
  • trunk/libtransmission/transmission.c

    r2 r3  
    5252    }
    5353
     54    /* Random key */
     55    for( i = 0; i < 20; i++ )
     56    {
     57        r         = tr_rand( 36 );
     58        h->key[i] = ( r < 26 ) ? ( 'a' + r ) : ( '0' + r - 26 ) ;
     59    }
     60
    5461    /* Don't exit when writing on a broken socket */
    5562    signal( SIGPIPE, SIG_IGN );
     
    165172    tor->status = TR_STATUS_PAUSE;
    166173    tor->id     = h->id;
     174    tor->key    = h->key;
    167175
    168176    /* Guess scrape URL */
     
    192200    tor->blockCount = ( inf->totalSize + tor->blockSize - 1 ) /
    193201                        tor->blockSize;
    194     tor->blockHave  = calloc( tor->blockCount, 1 );
    195     tor->bitfield   = calloc( ( inf->pieceCount + 7 ) / 8, 1 );
     202    tor->completion = tr_cpInit( tor );
    196203
    197204    tr_lockInit( &tor->lock );
     
    331338        inf = &tor->info;
    332339
    333         tr_lockLock( tor->lock );
    334 
    335340        if( ( tor->status & TR_STATUS_STOPPED ) ||
    336341            ( ( tor->status & TR_STATUS_STOPPING ) &&
     
    340345            tor->status = TR_STATUS_PAUSE;
    341346        }
     347
     348        tr_lockLock( tor->lock );
    342349
    343350        memcpy( &s[i].info, &tor->info, sizeof( tr_info_t ) );
     
    365372        }
    366373
    367         s[i].progress = (float) tor->blockHaveCount / (float) tor->blockCount;
    368 
     374        s[i].progress     = tr_cpCompletionAsFloat( tor->completion );
    369375        s[i].rateDownload = rateDownload( tor );
    370376        s[i].rateUpload   = rateUpload( tor );
     
    376382        else
    377383        {
    378             s[i].eta = (float) (tor->blockCount - tor->blockHaveCount ) *
    379                 (float) tor->blockSize / s[i].rateDownload / 1024.0;
     384            s[i].eta = (float) ( 1.0 - s[i].progress ) *
     385                (float) inf->totalSize / s[i].rateDownload / 1024.0;
    380386            if( s[i].eta > 99 * 3600 + 59 * 60 + 59 )
    381387            {
     
    388394            piece = j * inf->pieceCount / 120;
    389395
    390             if( tr_bitfieldHas( tor->bitfield, piece ) )
     396            if( tr_cpPieceIsComplete( tor->completion, piece ) )
    391397            {
    392398                s[i].pieces[j] = -1;
     
    431437    {
    432438        /* Join the thread first */
    433         tr_lockLock( tor->lock );
    434439        torrentReallyStop( h, t );
    435         tr_lockUnlock( tor->lock );
    436440    }
    437441
     
    439443
    440444    tr_lockClose( tor->lock );
     445    tr_cpClose( tor->completion );
    441446
    442447    if( tor->destination )
     
    446451    free( inf->pieces );
    447452    free( inf->files );
    448     free( tor->blockHave );
    449     free( tor->bitfield );
    450453    free( tor );
    451454
     
    477480#endif
    478481
     482    tr_lockLock( tor->lock );
     483
    479484    tor->io     = tr_ioInit( tor );
    480     tor->status = ( tor->blockHaveCount < tor->blockCount ) ?
    481                       TR_STATUS_DOWNLOAD : TR_STATUS_SEED;
    482    
     485    tor->status = tr_cpIsSeeding( tor->completion ) ?
     486                      TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
     487
    483488    while( !tor->die )
    484489    {
    485490        date1 = tr_date();
    486 
    487         tr_lockLock( tor->lock );
    488491
    489492        /* Are we finished ? */
    490493        if( ( tor->status & TR_STATUS_DOWNLOAD ) &&
    491             tor->blockHaveCount >= tor->blockCount )
     494            tr_cpIsSeeding( tor->completion ) )
    492495        {
    493496            /* Done */
     
    502505        tr_trackerPulse( tor->tracker );
    503506
    504         tr_lockUnlock( tor->lock );
    505 
    506507        if( tor->status & TR_STATUS_STOPPED )
    507508        {
     
    513514        if( date2 < date1 + 20 )
    514515        {
     516            tr_lockUnlock( tor->lock );
    515517            tr_wait( date1 + 20 - date2 );
    516         }
    517     }
     518            tr_lockLock( tor->lock );
     519        }
     520    }
     521
     522    tr_lockUnlock( tor->lock );
    518523
    519524    tr_ioClose( tor->io );
  • trunk/libtransmission/utils.h

    r1 r3  
    7676}
    7777
     78static inline void tr_bitfieldRem( uint8_t * bitfield, int piece )
     79{
     80    bitfield[ piece / 8 ] &= ~( 1 << ( 7 - ( piece % 8 ) ) );
     81}
     82
    7883#define tr_blockPiece(a) _tr_blockPiece(tor,a)
    7984static inline int _tr_blockPiece( tr_torrent_t * tor, int block )
Note: See TracChangeset for help on using the changeset viewer.