(trunk libT) #3427 "use shortest-job-first scheduling for verifying local data" -- patch from wateenellende and sadface

This commit is contained in:
Charles Kerr 2010-07-19 14:44:24 +00:00
parent e323d34dda
commit e7cf05a6ba
3 changed files with 97 additions and 38 deletions

View File

@ -144,6 +144,35 @@ tr_list_find( tr_list * list,
return NULL;
}
void
tr_list_insert_sorted( tr_list ** list,
void * data,
TrListCompareFunc compare )
{
/* find l, the node that we'll insert this data before */
tr_list * l;
for( l = *list; l != NULL; l = l->next )
{
const int c = (compare)( data, l->data );
if( c <= 0 )
break;
}
if( l == NULL )
tr_list_append( list, data );
else if( l == *list )
tr_list_prepend( list, data );
else {
tr_list * node = node_alloc( );
node->data = data;
node->prev = l->prev;
node->next = l;
node->prev->next = node;
node->next->prev = node;
}
}
int
tr_list_size( const tr_list * list )
{

View File

@ -100,6 +100,17 @@ tr_list* tr_list_find( tr_list * list,
const void * b,
TrListCompareFunc compare_func );
/**
* @brief Insert in an ordered list
* @param list pointer to the list
* @param item the item to be inserted
* @param compare the comparison function.
*/
void tr_list_insert_sorted( tr_list ** list,
void * data,
TrListCompareFunc compare );
/* @} */
#endif /* TR_LIST_H */

View File

@ -184,6 +184,7 @@ struct verify_node
{
tr_torrent * torrent;
tr_verify_done_cb verify_done_cb;
uint64_t current_size;
};
static void
@ -252,27 +253,39 @@ verifyThreadFunc( void * unused UNUSED )
tr_lockUnlock( getVerifyLock( ) );
}
static tr_bool
torrentHasAnyLocalData( const tr_torrent * tor )
static uint64_t
getCurrentSize( tr_torrent * tor )
{
tr_file_index_t i;
tr_bool hasAny = FALSE;
uint64_t byte_count = 0;
const tr_file_index_t n = tor->info.fileCount;
assert( tr_isTorrent( tor ) );
for( i=0; i<n && !hasAny; ++i )
for( i=0; i<n; ++i )
{
struct stat sb;
char * path = tr_torrentFindFile( tor, i );
if( ( path != NULL ) && !stat( path, &sb ) && ( sb.st_size > 0 ) )
hasAny = TRUE;
tr_free( path );
char * filename = tr_torrentFindFile( tor, i );
sb.st_size = 0;
if( filename && !stat( filename, &sb ) )
byte_count += sb.st_size;
tr_free( filename );
}
return hasAny;
return byte_count;
}
static int
compareVerifyBySize( const void * va, const void * vb )
{
const struct verify_node * a = va;
const struct verify_node * b = vb;
if( a->current_size < b->current_size ) return -1;
if( a->current_size > b->current_size ) return 1;
return 0;
}
void
tr_verifyAdd( tr_torrent * tor,
tr_verify_done_cb verify_done_cb )
@ -284,38 +297,44 @@ tr_verifyAdd( tr_torrent * tor,
/* doesn't need to be checked... */
fireCheckDone( tor, verify_done_cb );
}
else if( !torrentHasAnyLocalData( tor ) )
{
/* we haven't downloaded anything for this torrent yet...
* no need to leave it waiting in the back of the queue.
* we can mark it as all-missing from here and fire
* the "done" callback */
const tr_bool hadAny = tr_cpHaveTotal( &tor->completion ) != 0;
tr_piece_index_t i;
for( i=0; i<tor->info.pieceCount; ++i ) {
tr_torrentSetHasPiece( tor, i, FALSE );
tr_torrentSetPieceChecked( tor, i, TRUE );
}
if( hadAny ) /* if we thought we had some, flag as dirty */
tr_torrentSetDirty( tor );
fireCheckDone( tor, verify_done_cb );
}
else
{
struct verify_node * node;
const uint64_t current_size = getCurrentSize( tor );
tr_torinf( tor, "%s", _( "Queued for verification" ) );
if( !current_size )
{
/* we haven't downloaded anything for this torrent yet...
* no need to leave it waiting in the back of the queue.
* we can mark it as all-missing from here and fire
* the "done" callback */
const tr_bool hadAny = tr_cpHaveTotal( &tor->completion ) != 0;
tr_piece_index_t i;
for( i=0; i<tor->info.pieceCount; ++i ) {
tr_torrentSetHasPiece( tor, i, FALSE );
tr_torrentSetPieceChecked( tor, i, TRUE );
}
if( hadAny ) /* if we thought we had some, flag as dirty */
tr_torrentSetDirty( tor );
fireCheckDone( tor, verify_done_cb );
}
else
{
struct verify_node * node;
node = tr_new( struct verify_node, 1 );
node->torrent = tor;
node->verify_done_cb = verify_done_cb;
tr_torinf( tor, "%s", _( "Queued for verification" ) );
tr_lockLock( getVerifyLock( ) );
tr_torrentSetVerifyState( tor, TR_VERIFY_WAIT );
tr_list_append( &verifyList, node );
if( verifyThread == NULL )
verifyThread = tr_threadNew( verifyThreadFunc, NULL );
tr_lockUnlock( getVerifyLock( ) );
node = tr_new( struct verify_node, 1 );
node->torrent = tor;
node->verify_done_cb = verify_done_cb;
node->current_size = current_size;
tr_lockLock( getVerifyLock( ) );
tr_torrentSetVerifyState( tor, TR_VERIFY_WAIT );
tr_list_insert_sorted( &verifyList, node, compareVerifyBySize );
if( verifyThread == NULL )
verifyThread = tr_threadNew( verifyThreadFunc, NULL );
tr_lockUnlock( getVerifyLock( ) );
}
}
}