Changeset 1426
 Timestamp:
 Jan 22, 2007, 10:58:51 PM (16 years ago)
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

trunk/libtransmission/ratecontrol.c
r1372 r1426 25 25 #include "transmission.h" 26 26 27 #define MAX_HISTORY 30 28 29 typedef struct tr_transfer_s tr_transfer_t; 27 /* Maximum number of packets we keep track of. Since most packets are 28 * 1 KB, it means we remember the last 2 MB transferred */ 29 #define HISTORY_SIZE 2048 30 31 /* How far back we go to calculate rates to be displayed in the 32 * interface */ 33 #define LONG_INTERVAL 30000 /* 30 secs */ 34 35 /* How far back we go to calculate pseudoinstantaneous transfer rates, 36 * for the actual rate control */ 37 #define SHORT_INTERVAL 1000 /* 1 sec */ 38 39 40 /*********************************************************************** 41 * Structures 42 **********************************************************************/ 43 typedef struct tr_transfer_s 44 { 45 uint64_t date; 46 int size; 47 } 48 tr_transfer_t; 49 30 50 struct tr_ratecontrol_s 31 51 { 32 tr_lock_t lock; 33 int limit; 34 tr_transfer_t * first; 35 tr_transfer_t * last; 52 tr_lock_t lock; 53 int limit; 54 55 /* Circular history: it's empty if transferStop == transferStart, 56 * full if ( transferStop + 1 ) % HISTORY_SIZE == transferStart */ 57 tr_transfer_t transfers[HISTORY_SIZE]; 58 int transferStart; 59 int transferStop; 36 60 }; 37 struct tr_transfer_s 38 { 39 uint64_t date; 40 int size; 41 tr_transfer_t * next; 42 tr_transfer_t * prev; 43 }; 44 45 /*********************************************************************** 46 * rateForInterval 47 *********************************************************************** 48 * Returns the transfer rate on the last 'interval' milliseconds 49 **********************************************************************/ 50 static inline float rateForInterval( tr_ratecontrol_t * r, int interval ) 51 { 52 tr_transfer_t * t; 53 uint64_t start = tr_date()  interval; 54 int total = 0; 55 56 for( t = r>first; t && t>date > start; t = t>next ) 57 { 58 total += t>size; 59 } 60 61 return ( 1000.0 / 1024.0 ) * total / interval; 62 } 63 64 static inline void cleanOldTransfers( tr_ratecontrol_t * r ) 65 { 66 tr_transfer_t * t, * prev; 67 uint64_t old = tr_date()  MAX_HISTORY * 1000; 68 69 for( t = r>last; t && t>date < old; ) 70 { 71 prev = t>prev; 72 if( prev ) 73 prev>next = NULL; 74 else 75 r>first = NULL; 76 free( t ); 77 t = prev; 78 r>last = prev; 79 } 80 } 61 62 63 /*********************************************************************** 64 * Local prototypes 65 **********************************************************************/ 66 static float rateForInterval( tr_ratecontrol_t * r, int interval ); 67 68 69 /*********************************************************************** 70 * Exported functions 71 **********************************************************************/ 81 72 82 73 tr_ratecontrol_t * tr_rcInit() … … 112 103 r = isUpload ? tor>upload : tor>download; 113 104 tr_lockLock( &r>lock ); 114 rate += rateForInterval( r, 1000);105 rate += rateForInterval( r, SHORT_INTERVAL ); 115 106 tr_lockUnlock( &r>lock ); 116 107 … … 136 127 137 128 tr_lockLock( &r>lock ); 138 ret = ( r>limit <= 0 ) ? ( r>limit < 0 ) : ( rateForInterval( r, 1000 ) < r>limit ); 129 ret = ( r>limit <= 0 ) ? ( r>limit < 0 ) : 130 ( rateForInterval( r, SHORT_INTERVAL ) < r>limit ); 139 131 tr_lockUnlock( &r>lock ); 140 132 … … 148 140 if( size < 100 ) 149 141 { 142 /* Don't count small messages */ 150 143 return; 151 144 } 152 145 153 146 tr_lockLock( &r>lock ); 154 t = malloc( sizeof( tr_transfer_t ) ); 155 156 if( r>first ) 157 r>first>prev = t; 158 if( !r>last ) 159 r>last = t; 160 t>next = r>first; 161 t>prev = NULL; 162 r>first = t; 163 164 t>date = tr_date(); 165 t>size = size; 166 167 cleanOldTransfers( r ); 147 148 r>transferStop = ( r>transferStop + 1 ) % HISTORY_SIZE; 149 if( r>transferStop == r>transferStart ) 150 /* History is full, forget about the first (oldest) item */ 151 r>transferStart = ( r>transferStart + 1 ) % HISTORY_SIZE; 152 153 t = &r>transfers[r>transferStop]; 154 t>date = tr_date(); 155 t>size = size; 156 168 157 tr_lockUnlock( &r>lock ); 169 158 } … … 174 163 175 164 tr_lockLock( &r>lock ); 176 ret = rateForInterval( r, MAX_HISTORY * 1000);165 ret = rateForInterval( r, LONG_INTERVAL ); 177 166 tr_lockUnlock( &r>lock ); 178 167 … … 182 171 void tr_rcReset( tr_ratecontrol_t * r ) 183 172 { 184 tr_transfer_t * t, * next; 185 186 tr_lockLock( &r>lock ); 187 for( t = r>first; t; ) 188 { 189 next = t>next; 190 free( t ); 191 t = next; 192 } 193 r>first = NULL; 194 r>last = NULL; 173 tr_lockLock( &r>lock ); 174 r>transferStart = 0; 175 r>transferStop = 0; 195 176 tr_lockUnlock( &r>lock ); 196 177 } … … 202 183 free( r ); 203 184 } 185 186 187 /*********************************************************************** 188 * Local functions 189 **********************************************************************/ 190 191 /*********************************************************************** 192 * rateForInterval 193 *********************************************************************** 194 * Returns the transfer rate in KB/s on the last 'interval' 195 * milliseconds 196 **********************************************************************/ 197 static float rateForInterval( tr_ratecontrol_t * r, int interval ) 198 { 199 tr_transfer_t * t = NULL; 200 uint64_t now, start; 201 int i, total; 202 203 now = tr_date(); 204 start = now  interval; 205 206 /* Browse the history back in time */ 207 total = 0; 208 for( i = r>transferStop; i != r>transferStart; i ) 209 { 210 t = &r>transfers[i]; 211 if( t>date < start ) 212 break; 213 214 total += t>size; 215 216 if( !i ) 217 i = HISTORY_SIZE; /* Loop */ 218 } 219 if( ( r>transferStop + 1 ) % HISTORY_SIZE == r>transferStart 220 && i == r>transferStart ) 221 { 222 /* High bandwidth > the history isn't big enough to remember 223 * everything transferred since 'interval' ms ago. Correct the 224 * interval so that we return the correct rate */ 225 interval = now  t>date; 226 } 227 228 return ( 1000.0f / 1024.0f ) * total / interval; 229 } 230
Note: See TracChangeset
for help on using the changeset viewer.