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:
parent
2ea88f30f5
commit
5381e20e9b
4 changed files with 51 additions and 30 deletions
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Add table
Reference in a new issue