1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-12 23:23:54 +00:00

(trunk libT) improve piece verification speed by providing a larger buffer, and add a mechanism to reuse it when verifying an entire torrent at once.

This commit is contained in:
Charles Kerr 2008-12-31 18:08:13 +00:00
parent 2ea88f30f5
commit 5381e20e9b
4 changed files with 51 additions and 30 deletions

View file

@ -210,31 +210,42 @@ tr_ioWrite( const tr_torrent * tor,
*****
****/
static int
static tr_bool
recalculateHash( const tr_torrent * tor,
tr_piece_index_t pieceIndex,
void * buffer,
size_t buflen,
uint8_t * setme )
{
size_t bytesLeft;
uint32_t offset = 0;
int success = TRUE;
tr_bool success = TRUE;
uint8_t stackbuf[MAX_STACK_ARRAY_SIZE];
SHA_CTX sha;
assert( tor );
assert( setme );
/* fallback buffer */
if( ( buffer == NULL ) || ( buflen < 1 ) )
{
buffer = stackbuf;
buflen = sizeof( stackbuf );
}
assert( tor != NULL );
assert( pieceIndex < tor->info.pieceCount );
assert( buffer != NULL );
assert( buflen > 0 );
assert( setme != NULL );
SHA1_Init( &sha );
bytesLeft = tr_torPieceCountBytes( tor, pieceIndex );
while( bytesLeft )
{
uint8_t buf[MAX_STACK_ARRAY_SIZE];
const int len = MIN( bytesLeft, sizeof( buf ) );
success = !tr_ioRead( tor, pieceIndex, offset, len, buf );
const int len = MIN( bytesLeft, buflen );
success = !tr_ioRead( tor, pieceIndex, offset, len, buffer );
if( !success )
break;
SHA1_Update( &sha, buf, len );
SHA1_Update( &sha, buffer, len );
offset += len;
bytesLeft -= len;
}
@ -245,12 +256,14 @@ recalculateHash( const tr_torrent * tor,
return success;
}
int
tr_ioTestPiece( const tr_torrent * tor,
int pieceIndex )
tr_bool
tr_ioTestPiece( const tr_torrent * tor,
tr_piece_index_t pieceIndex,
void * buffer,
size_t buflen )
{
uint8_t hash[SHA_DIGEST_LENGTH];
const int recalculated = recalculateHash( tor, pieceIndex, hash );
return recalculated && !memcmp( hash, tor->info.pieces[pieceIndex].hash, SHA_DIGEST_LENGTH );
}
return recalculateHash( tor, pieceIndex, buffer, buflen, hash )
&& !memcmp( hash, tor->info.pieces[pieceIndex].hash, SHA_DIGEST_LENGTH );
}

View file

@ -52,10 +52,16 @@ int tr_ioWrite( const struct tr_torrent * tor,
const uint8_t * writeme );
/**
* returns nonzero if the piece matches its metainfo's SHA1 checksum.
* @brief Test to see if the piece matches its metainfo's SHA1 checksum.
*
* @param optionalBuffer if calling tr_ioTestPiece() repeatedly, you can
* get best performance by providing a buffer with
* tor->info.pieceSize bytes.
*/
int tr_ioTestPiece( const tr_torrent*,
int piece );
tr_bool tr_ioTestPiece( const tr_torrent * tor,
tr_piece_index_t piece,
void * optionalBuffer,
size_t optionalBufferLen );
/**

View file

@ -1089,7 +1089,7 @@ peerCallbackFunc( void * vpeer, void * vevent, void * vt )
if( tr_cpPieceIsComplete( tor->completion, e->pieceIndex ) )
{
const tr_piece_index_t p = e->pieceIndex;
const tr_bool ok = tr_ioTestPiece( tor, p );
const tr_bool ok = tr_ioTestPiece( tor, p, NULL, 0 );
if( !ok )
{

View file

@ -60,9 +60,11 @@ getVerifyLock( void )
}
static int
checkFile( tr_torrent * tor,
tr_file_index_t fileIndex,
int * abortFlag )
checkFile( tr_torrent * tor,
void * buffer,
size_t buflen,
tr_file_index_t fileIndex,
int * abortFlag )
{
tr_piece_index_t i;
int changed = FALSE;
@ -84,10 +86,9 @@ checkFile( tr_torrent * tor,
}
else if( !tr_torrentIsPieceChecked( tor, i ) )
{
const int wasComplete = tr_cpPieceIsComplete(
tor->completion, i );
const int wasComplete = tr_cpPieceIsComplete( tor->completion, i );
if( tr_ioTestPiece( tor, i ) ) /* yay */
if( tr_ioTestPiece( tor, i, buffer, buflen ) ) /* yay */
{
tr_torrentSetHasPiece( tor, i, TRUE );
if( !wasComplete )
@ -119,12 +120,13 @@ checkFile( tr_torrent * tor,
static void
verifyThreadFunc( void * unused UNUSED )
{
for( ; ; )
for( ;; )
{
int changed = 0;
tr_file_index_t i;
tr_torrent * tor;
tr_torrent * tor;
struct verify_node * node;
void * buffer;
tr_lockLock( getVerifyLock( ) );
stopCurrent = FALSE;
@ -141,12 +143,12 @@ verifyThreadFunc( void * unused UNUSED )
tr_free( node );
tr_lockUnlock( getVerifyLock( ) );
tor->verifyState = TR_VERIFY_NOW;
tr_torinf( tor, _( "Verifying torrent" ) );
tor->verifyState = TR_VERIFY_NOW;
buffer = tr_new( uint8_t, tor->info.pieceSize );
for( i = 0; i < tor->info.fileCount && !stopCurrent; ++i )
changed |= checkFile( tor, i, &stopCurrent );
changed |= checkFile( tor, buffer, tor->info.pieceSize, i, &stopCurrent );
tr_free( buffer );
tor->verifyState = TR_VERIFY_NONE;
if( !stopCurrent )