Changeset 2303
- Timestamp:
- Jul 7, 2007, 4:13:13 AM (16 years ago)
- Location:
- trunk/libtransmission
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/peer.c
r2297 r2303 378 378 peer->buf = realloc( peer->buf, peer->size ); 379 379 } 380 #if 0 381 /* Never read more than 1K each time, otherwise the rate382 control is no use*/380 381 /* Read in smallish chunks, otherwise we might read more 382 * than the download cap is supposed to allow us */ 383 383 ret = tr_netRecv( peer->socket, &peer->buf[peer->pos], 384 384 MIN( 1024, peer->size - peer->pos ) ); 385 #else386 /* Hm, it doesn't *seem* to break rate control... */387 ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],388 peer->size - peer->pos );389 #endif390 385 391 386 if( ret & TR_NET_CLOSE ) … … 569 564 { 570 565 if( SWIFT_ENABLED && !isSeeding && (peer->credit<0) ) 571 {572 566 break; 573 }574 567 575 568 if( tor->customUploadLimit 576 569 ? !tr_rcCanTransfer( tor->upload ) 577 570 : !tr_rcCanTransfer( tor->handle->upload ) ) 578 {579 571 break; 580 }581 572 582 573 ret = tr_netSend( peer->socket, p, size ); 583 574 if( ret & TR_NET_CLOSE ) 584 {585 575 return TR_ERROR; 586 } 587 else if( ret & TR_NET_BLOCK ) 588 { 576 577 if( ret & TR_NET_BLOCK ) 589 578 break; 590 }591 579 592 580 blockSent( peer, ret ); … … 602 590 603 591 if( !tr_peerAmChoking( peer ) ) 604 {605 592 tor->activityDate = date; 606 }607 593 608 594 /* In case this block is done, you may have messages -
trunk/libtransmission/ratecontrol.c
r2231 r2303 26 26 #include "shared.h" 27 27 28 /* Maximum number of packets we keep track of. Since most packets are 29 * 1 KB, it means we remember the last 2 MB transferred */ 30 #define HISTORY_SIZE 2048 28 #define GRANULARITY_MSEC 200 29 #define SHORT_INTERVAL_MSEC 1000 30 #define LONG_INTERVAL_MSEC 10000 31 #define HISTORY_SIZE (LONG_INTERVAL_MSEC / GRANULARITY_MSEC) 31 32 32 /* How far back we go to calculate rates to be displayed in the 33 * interface */ 34 #define LONG_INTERVAL 30000 /* 30 secs */ 35 36 /* How far back we go to calculate pseudo-instantaneous transfer rates, 37 * for the actual rate control */ 38 #define SHORT_INTERVAL 1000 /* 1 sec */ 39 40 41 /*********************************************************************** 42 * Structures 43 **********************************************************************/ 44 typedef struct tr_transfer_s 33 typedef struct 45 34 { 46 35 uint64_t date; … … 51 40 struct tr_ratecontrol_s 52 41 { 53 tr_lock_t lock; 54 int limit; 55 56 /* Circular history: it's empty if transferStop == transferStart, 57 * full if ( transferStop + 1 ) % HISTORY_SIZE == transferStart */ 42 tr_rwlock_t lock; 43 int limit; 44 int newest; 58 45 tr_transfer_t transfers[HISTORY_SIZE]; 59 int transferStart;60 int transferStop;61 46 }; 62 47 48 /* return the xfer rate over the last `interval' seconds in KiB/sec */ 49 static float 50 rateForInterval( const tr_ratecontrol_t * r, int interval_msec ) 51 { 52 uint64_t bytes = 0; 53 const uint64_t now = tr_date (); 54 int i = r->newest; 55 int real_interval_msec = 0; 56 for( ;; ) 57 { 58 if( r->transfers[i].date + interval_msec < now ) 59 break; 63 60 64 /*********************************************************************** 65 * Local prototypes 66 **********************************************************************/ 67 static float rateForInterval( tr_ratecontrol_t * r, int interval ); 61 bytes += r->transfers[i].size; 62 real_interval_msec = now - r->transfers[i].date; 68 63 64 if( --i == -1 ) i = HISTORY_SIZE - 1; /* circular history */ 65 if( i == r->newest ) break; /* we've come all the way around */ 66 } 69 67 70 /*********************************************************************** 71 * Exported functions 72 **********************************************************************/ 68 return !bytes || !real_interval_msec 69 ? 0.0 70 : (bytes/1024.0) * (1000.0/real_interval_msec); 71 } 73 72 74 tr_ratecontrol_t * tr_rcInit() 73 /*** 74 **** 75 ***/ 76 77 tr_ratecontrol_t* 78 tr_rcInit( void ) 75 79 { 76 tr_ratecontrol_t * r; 77 78 r = calloc( 1, sizeof( tr_ratecontrol_t ) ); 80 tr_ratecontrol_t * r = tr_new0( tr_ratecontrol_t, 1 ); 79 81 r->limit = -1; 80 tr_lockInit( &r->lock ); 81 82 tr_rwInit( &r->lock ); 82 83 return r; 83 84 } 84 85 85 void tr_rcSetLimit( tr_ratecontrol_t * r, int limit ) 86 void 87 tr_rcClose( tr_ratecontrol_t * r ) 86 88 { 87 tr_ lockLock( &r->lock);88 r->limit = limit;89 tr_ lockUnlock( &r->lock);89 tr_rcReset( r ); 90 tr_rwClose( &r->lock ); 91 tr_free( r ); 90 92 } 91 93 92 int tr_rcCanTransfer( tr_ratecontrol_t * r ) 94 /*** 95 **** 96 ***/ 97 98 int 99 tr_rcCanTransfer( const tr_ratecontrol_t * r ) 93 100 { 94 101 int ret; 102 tr_rwReaderLock( (tr_rwlock_t*)&r->lock ); 95 103 96 tr_lockLock( &r->lock ); 97 ret = ( r->limit <= 0 ) ? ( r->limit < 0 ) : 98 ( rateForInterval( r, SHORT_INTERVAL ) < r->limit ); 99 tr_lockUnlock( &r->lock ); 104 if( r->limit < 0 ) /* unbounded */ 105 ret = TRUE; 106 else if( !r->limit ) /* off */ 107 ret = FALSE; 108 else 109 ret = rateForInterval( r, SHORT_INTERVAL_MSEC ) < r->limit; 100 110 111 tr_rwReaderUnlock( (tr_rwlock_t*)&r->lock ); 101 112 return ret; 102 113 } 103 114 104 void tr_rcTransferred( tr_ratecontrol_t * r, int size ) 105 { 106 tr_transfer_t * t; 107 108 if( size < 100 ) 109 { 110 /* Don't count small messages */ 111 return; 112 } 113 114 tr_lockLock( &r->lock ); 115 116 r->transferStop = ( r->transferStop + 1 ) % HISTORY_SIZE; 117 if( r->transferStop == r->transferStart ) 118 /* History is full, forget about the first (oldest) item */ 119 r->transferStart = ( r->transferStart + 1 ) % HISTORY_SIZE; 120 121 t = &r->transfers[r->transferStop]; 122 t->date = tr_date(); 123 t->size = size; 124 125 tr_lockUnlock( &r->lock ); 126 } 127 128 float tr_rcRate( tr_ratecontrol_t * r ) 115 float 116 tr_rcRate( const tr_ratecontrol_t * r ) 129 117 { 130 118 float ret; 119 tr_rwReaderLock( (tr_rwlock_t*)&r->lock ); 131 120 132 tr_lockLock( &r->lock ); 133 ret = rateForInterval( r, LONG_INTERVAL ); 134 tr_lockUnlock( &r->lock ); 121 ret = rateForInterval( r, LONG_INTERVAL_MSEC ); 135 122 123 tr_rwReaderUnlock( (tr_rwlock_t*)&r->lock ); 136 124 return ret; 137 125 } 138 126 139 void tr_rcReset( tr_ratecontrol_t * r ) 127 /*** 128 **** 129 ***/ 130 131 void 132 tr_rcTransferred( tr_ratecontrol_t * r, int size ) 140 133 { 141 tr_lockLock( &r->lock ); 142 r->transferStart = 0; 143 r->transferStop = 0; 144 tr_lockUnlock( &r->lock ); 134 uint64_t now; 135 136 if( size < 100 ) /* don't count small messages */ 137 return; 138 139 tr_rwWriterLock( &r->lock ); 140 141 now = tr_date (); 142 if( r->transfers[r->newest].date + GRANULARITY_MSEC >= now ) 143 r->transfers[r->newest].size += size; 144 else { 145 if( ++r->newest == HISTORY_SIZE ) r->newest = 0; 146 r->transfers[r->newest].date = now; 147 r->transfers[r->newest].size = size; 148 } 149 150 tr_rwWriterUnlock( &r->lock ); 145 151 } 146 152 147 void tr_rcClose( tr_ratecontrol_t * r ) 153 void 154 tr_rcReset( tr_ratecontrol_t * r ) 148 155 { 149 tr_rcReset( r ); 150 tr_lockClose( &r->lock ); 151 free( r ); 156 tr_rwWriterLock( &r->lock ); 157 r->newest = 0; 158 memset( r->transfers, 0, sizeof(tr_transfer_t) * HISTORY_SIZE ); 159 tr_rwWriterUnlock( &r->lock ); 152 160 } 153 161 154 155 /*********************************************************************** 156 * Local functions 157 **********************************************************************/ 158 159 /*********************************************************************** 160 * rateForInterval 161 *********************************************************************** 162 * Returns the transfer rate in KB/s on the last 'interval' 163 * milliseconds 164 **********************************************************************/ 165 static float rateForInterval( tr_ratecontrol_t * r, int interval ) 162 void 163 tr_rcSetLimit( tr_ratecontrol_t * r, int limit ) 166 164 { 167 tr_transfer_t * t = NULL; 168 uint64_t now, then, start; 169 float total = 0; 170 int i; 171 172 now = then = tr_date(); 173 start = now - interval; 174 175 /* Browse the history back in time */ 176 for( i = r->transferStop; i != r->transferStart; i-- ) 177 { 178 t = &r->transfers[i]; 179 then = t->date; 180 if( then < start ) 181 break; 182 183 total += t->size; 184 185 if( !i ) 186 i = HISTORY_SIZE; /* Loop */ 187 } 188 #if 0 189 if( ( r->transferStop + 1 ) % HISTORY_SIZE == r->transferStart 190 && i == r->transferStart ) 191 { 192 /* High bandwidth -> the history isn't big enough to remember 193 * everything transferred since 'interval' ms ago. Correct the 194 * interval so that we return the correct rate */ 195 interval = now - t->date; 196 } 197 #endif 198 199 if( now == then ) 200 return 0.0; 201 return ( 1000.0f / 1024.0f ) * total / (now - then); 165 tr_rwWriterLock( &r->lock ); 166 r->limit = limit; 167 tr_rwWriterUnlock( &r->lock ); 202 168 } 203 -
trunk/libtransmission/ratecontrol.h
r1869 r2303 25 25 typedef struct tr_ratecontrol_s tr_ratecontrol_t; 26 26 27 tr_ratecontrol_t * tr_rcInit( );27 tr_ratecontrol_t * tr_rcInit( void ); 28 28 void tr_rcSetLimit( tr_ratecontrol_t *, int ); 29 int tr_rcCanTransfer( tr_ratecontrol_t * );29 int tr_rcCanTransfer( const tr_ratecontrol_t * ); 30 30 void tr_rcTransferred( tr_ratecontrol_t *, int ); 31 float tr_rcRate( tr_ratecontrol_t * );31 float tr_rcRate( const tr_ratecontrol_t * ); 32 32 void tr_rcReset( tr_ratecontrol_t * ); 33 33 void tr_rcClose( tr_ratecontrol_t * );
Note: See TracChangeset
for help on using the changeset viewer.