diff --git a/libtransmission/internal.h b/libtransmission/internal.h index be370a361..812a7634b 100644 --- a/libtransmission/internal.h +++ b/libtransmission/internal.h @@ -139,10 +139,10 @@ typedef enum { TR_OK, TR_ERROR, TR_WAIT } tr_tristate_t; struct tr_torrent_s { + tr_handle_t * handle; tr_info_t info; - tr_ratecontrol_t * globalUpload; - tr_ratecontrol_t * globalDownload; + int customSpeedLimit; tr_ratecontrol_t * upload; tr_ratecontrol_t * download; tr_ratecontrol_t * swarmspeed; @@ -201,8 +201,8 @@ struct tr_handle_s int torrentCount; tr_torrent_t * torrentList; - tr_ratecontrol_t * upload; - tr_ratecontrol_t * download; + int uploadLimit; + int downloadLimit; tr_fd_t * fdlimit; tr_choking_t * choking; tr_natpmp_t * natpmp; diff --git a/libtransmission/peer.c b/libtransmission/peer.c index 93f28fac6..e7c44cb33 100644 --- a/libtransmission/peer.c +++ b/libtransmission/peer.c @@ -266,8 +266,8 @@ int tr_peerRead( tr_torrent_t * tor, tr_peer_t * peer ) /* Try to read */ for( ;; ) { - if( tor && (!tr_rcCanTransfer( tor->globalDownload ) - || !tr_rcCanTransfer( tor->download ) ) ) + if( tor && ( ( !tor->customSpeedLimit && !tr_rcCanGlobalTransfer( tor->handle, 0 ) ) + || ( tor->customSpeedLimit && !tr_rcCanTransfer( tor->download ) ) ) ) { break; } @@ -301,7 +301,6 @@ int tr_peerRead( tr_torrent_t * tor, tr_peer_t * peer ) { tr_rcTransferred( peer->download, ret ); tr_rcTransferred( tor->download, ret ); - tr_rcTransferred( tor->globalDownload, ret ); if( parseBuf( tor, peer ) ) { return 1; @@ -437,8 +436,8 @@ writeBegin: /* Send pieces if we can */ while( ( p = blockPending( tor, peer, &size ) ) ) { - if( !tr_rcCanTransfer( tor->globalUpload ) - || !tr_rcCanTransfer( tor->upload ) ) + if( ( !tor->customSpeedLimit && !tr_rcCanGlobalTransfer( tor->handle, 1 ) ) + || ( tor->customSpeedLimit && !tr_rcCanTransfer( tor->upload ) ) ) { break; } @@ -456,7 +455,6 @@ writeBegin: blockSent( peer, ret ); tr_rcTransferred( peer->upload, ret ); tr_rcTransferred( tor->upload, ret ); - tr_rcTransferred( tor->globalUpload, ret ); tor->uploadedCur += ret; peer->outTotal += ret; diff --git a/libtransmission/ratecontrol.c b/libtransmission/ratecontrol.c index 8b00b3d80..1b4e847f5 100644 --- a/libtransmission/ratecontrol.c +++ b/libtransmission/ratecontrol.c @@ -90,6 +90,32 @@ tr_ratecontrol_t * tr_rcInit() return r; } +int tr_rcCanGlobalTransfer( tr_handle_t * h, int isUpload ) +{ + tr_torrent_t * tor; + tr_ratecontrol_t * r; + float rate = 0; + int limit = isUpload ? h->uploadLimit : h->downloadLimit; + + if( limit < 0 ) + { + return 1; + } + + for( tor = h->torrentList; tor && rate < (float)limit; tor = tor->next ) + { + if( !tor->customSpeedLimit ) + { + r = isUpload ? tor->upload : tor->download; + tr_lockLock( &r->lock ); + rate += rateForInterval( r, 1000 ); + tr_lockUnlock( &r->lock ); + } + } + + return rate < (float)limit; +} + void tr_rcSetLimit( tr_ratecontrol_t * r, int limit ) { tr_lockLock( &r->lock ); diff --git a/libtransmission/ratecontrol.h b/libtransmission/ratecontrol.h index f2077eea7..06f82a26c 100644 --- a/libtransmission/ratecontrol.h +++ b/libtransmission/ratecontrol.h @@ -25,6 +25,7 @@ typedef struct tr_ratecontrol_s tr_ratecontrol_t; tr_ratecontrol_t * tr_rcInit(); +int tr_rcCanGlobalTransfer( tr_handle_t * h, int isUpload ); void tr_rcSetLimit( tr_ratecontrol_t *, int ); int tr_rcCanTransfer( tr_ratecontrol_t * ); void tr_rcTransferred( tr_ratecontrol_t *, int ); diff --git a/libtransmission/transmission.c b/libtransmission/transmission.c index ae9226d70..9280e025f 100644 --- a/libtransmission/transmission.c +++ b/libtransmission/transmission.c @@ -70,8 +70,9 @@ tr_handle_t * tr_init() signal( SIGPIPE, SIG_IGN ); /* Initialize rate and file descripts controls */ - h->upload = tr_rcInit(); - h->download = tr_rcInit(); + h->uploadLimit = -1; + h->downloadLimit = -1; + h->fdlimit = tr_fdInit(); h->choking = tr_chokingInit( h ); h->natpmp = tr_natpmpInit( h->fdlimit ); @@ -192,13 +193,18 @@ int tr_natTraversalStatus( tr_handle_t * h ) void tr_setGlobalUploadLimit( tr_handle_t * h, int limit ) { - tr_rcSetLimit( h->upload, limit ); + h->uploadLimit = limit; tr_chokingSetLimit( h->choking, limit ); } void tr_setGlobalDownloadLimit( tr_handle_t * h, int limit ) { - tr_rcSetLimit( h->download, limit ); + h->downloadLimit = limit; +} + +void tr_setUseCustomLimit( tr_torrent_t * tor, int limit ) +{ + tor->customSpeedLimit = limit; } void tr_setUploadLimit( tr_torrent_t * tor, int limit ) @@ -272,7 +278,7 @@ static tr_torrent_t * torrentRealInit( tr_handle_t * h, tr_torrent_t * tor, tr_torrent_t * tor_tmp; tr_info_t * inf; int i; - + inf = &tor->info; inf->flags = flags; @@ -289,6 +295,7 @@ static tr_torrent_t * torrentRealInit( tr_handle_t * h, tr_torrent_t * tor, } } + tor->handle = h; tor->status = TR_STATUS_PAUSE; tor->id = h->id; tor->key = h->key; @@ -309,8 +316,6 @@ static tr_torrent_t * torrentRealInit( tr_handle_t * h, tr_torrent_t * tor, tr_lockInit( &tor->lock ); - tor->globalUpload = h->upload; - tor->globalDownload = h->download; tor->fdlimit = h->fdlimit; tor->upload = tr_rcInit(); tor->download = tr_rcInit(); @@ -738,8 +743,6 @@ void tr_close( tr_handle_t * h ) tr_upnpClose( h->upnp ); tr_chokingClose( h->choking ); tr_fdClose( h->fdlimit ); - tr_rcClose( h->upload ); - tr_rcClose( h->download ); free( h ); tr_netResolveThreadClose(); diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 4a2c32cb4..e9c8f7a7b 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -160,6 +160,10 @@ typedef struct tr_torrent_s tr_torrent_t; typedef void (*tr_callback_t) ( tr_torrent_t *, void * ); void tr_torrentIterate( tr_handle_t *, tr_callback_t, void * ); +void tr_setUseCustomLimit( tr_torrent_t * tor, int limit ); +void tr_setUploadLimit( tr_torrent_t * tor, int limit ); +void tr_setDownloadLimit( tr_torrent_t * tor, int limit ); + /*********************************************************************** * tr_torrentRates *********************************************************************** diff --git a/macosx/Torrent.m b/macosx/Torrent.m index 462eee1e5..058fd0ce5 100644 --- a/macosx/Torrent.m +++ b/macosx/Torrent.m @@ -592,8 +592,9 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80 - (void) updateSpeedSetting { - tr_setUploadLimit(fHandle, fLimitCustom && fCheckUpload ? fUploadLimit : -1); - tr_setDownloadLimit(fHandle, fLimitCustom && fCheckDownload ? fDownloadLimit : -1); + tr_setUseCustomLimit(fHandle, fLimitCustom); + tr_setUploadLimit(fHandle, fCheckUpload ? fUploadLimit : -1); + tr_setDownloadLimit(fHandle, fCheckDownload ? fDownloadLimit : -1); } - (void) setWaitToStart: (BOOL) wait