(libT) maybe fix the hangs reported by users in the recent nightlies.

This commit is contained in:
Charles Kerr 2008-08-27 18:50:21 +00:00
parent 9d35118808
commit 64e08510f0
4 changed files with 48 additions and 37 deletions

View File

@ -268,7 +268,8 @@ tr_cryptoHasTorrentHash( const tr_crypto * crypto )
return crypto->torrentHashIsSet ? 1 : 0;
}
int tr_cryptoRandInt( int sup )
int
tr_cryptoRandInt( int sup )
{
int r;
@ -277,6 +278,21 @@ int tr_cryptoRandInt( int sup )
return ((int) (sup * (abs(r) / (INT_MAX + 1.0))));
}
int
tr_cryptoWeakRandInt( int sup )
{
static int init = 0;
assert( sup > 0 );
if( !init )
{
srand( tr_date( ) );
init = 1;
}
return rand() % sup;
}
void tr_cryptoRandBuf ( unsigned char *buf, size_t len )
{
RAND_pseudo_bytes ( buf, len );

View File

@ -79,6 +79,12 @@ void tr_sha1 ( uint8_t * setme,
/** Returns a random number in the range of [0...n) */
int tr_cryptoRandInt ( int n );
/** Returns a vaguely random number in the range of [0...n).
This is faster -- BUT WEAKER -- than tr_cryptoRandInt()
and should only be used when tr_cryptoRandInt() is too
slow, and NEVER in sensitive cases */
int tr_cryptoWeakRandInt( int n );
/** Fills a buffer with random bytes */
void tr_cryptoRandBuf ( unsigned char *buf, size_t len );

View File

@ -130,27 +130,6 @@ struct tr_peerMgr
***
**/
/* The following is not a very high quality random number generator. It
* is mainly used as a simple stupid random number generator inside some
* functions below. Please don't use it for anything else unless you
* know what you're doing. Use tr_cryptoRandInt() instead.
*/
static int
tr_stupidRandInt( int sup )
{
static int init = 0;
assert( sup > 0 );
if( !init )
{
srand( tr_date() );
init = 1;
}
return rand() % sup;
}
static void
managerLock( const struct tr_peerMgr * manager )
{
@ -626,7 +605,7 @@ getPreferredPieces( Torrent * t,
setme->piece = piece;
setme->priority = inf->pieces[piece].priority;
setme->peerCount = 0;
setme->random = tr_stupidRandInt( INT_MAX );
setme->random = tr_cryptoWeakRandInt( INT_MAX );
for( k=0; k<peerCount; ++k ) {
const tr_peer * peer = peers[k];
@ -667,7 +646,7 @@ getPeersUploadingToClient( Torrent * t, int * setmeCount )
* get a chance at the first blocks in the queue */
if( retCount ) {
tr_peer ** tmp = tr_new( tr_peer*, retCount );
i = tr_stupidRandInt( retCount );
i = tr_cryptoWeakRandInt( retCount );
memcpy( tmp, ret, sizeof(tr_peer*) * retCount );
memcpy( ret, tmp+i, sizeof(tr_peer*) * (retCount-i) );
memcpy( ret+(retCount-i), tmp, sizeof(tr_peer*) * i );
@ -1663,7 +1642,7 @@ rechoke( Torrent * t )
if(( n = tr_ptrArraySize( randPool )))
{
c = tr_ptrArrayNth( randPool, tr_stupidRandInt( n ));
c = tr_ptrArrayNth( randPool, tr_cryptoWeakRandInt( n ));
c->doUnchoke = 1;
t->optimistic = c->peer;
}

View File

@ -1766,28 +1766,38 @@ static void
sendBitfield( tr_peermsgs * msgs )
{
struct evbuffer * out = msgs->outMessages;
const tr_piece_index_t pieceCount = msgs->torrent->info.pieceCount;
tr_bitfield * field;
tr_piece_index_t lazyPieces[LAZY_PIECE_COUNT];
int i;
int lazyCount = 0;
size_t i;
size_t lazyCount = 0;
field = tr_bitfieldDup( tr_cpPieceBitfield( msgs->torrent->completion ) );
if( tr_sessionIsLazyBitfieldEnabled( msgs->session ) )
{
const int maxLazyCount = MIN( LAZY_PIECE_COUNT, pieceCount );
/** Lazy bitfields aren't a high priority or secure, so I'm opting for
speed over a truly random sample -- let's limit the pool size to
the first 1000 pieces so large torrents don't bog things down */
size_t poolSize = MIN( msgs->torrent->info.pieceCount, 1000 );
tr_piece_index_t * pool = tr_new( tr_piece_index_t, poolSize );
while( lazyCount < maxLazyCount )
/* build the pool */
for( i=0; i<poolSize; ++i )
pool[i] = i;
poolSize = i;
/* pull random piece indices from the pool */
while( ( poolSize > 0 ) && ( lazyCount < LAZY_PIECE_COUNT ) )
{
const size_t pos = tr_cryptoRandInt ( pieceCount );
if( !tr_bitfieldHas( field, pos ) ) /* already removed it */
continue;
dbgmsg( msgs, "lazy bitfield #%d: piece %d of %d",
(int)(lazyCount+1), (int)pos, (int)pieceCount );
tr_bitfieldRem( field, pos );
lazyPieces[lazyCount++] = pos;
const int pos = tr_cryptoWeakRandInt( poolSize );
const tr_piece_index_t piece = pool[pos];
tr_bitfieldRem( field, piece );
lazyPieces[lazyCount++] = piece;
pool[pos] = pool[--poolSize];
}
/* cleanup */
tr_free( pool );
}
tr_peerIoWriteUint32( msgs->io, out, sizeof(uint8_t) + field->byteCount );