(trunk libT) #3427 "use shortest-job-first scheduling for verifying local data" -- patch from wateenellende and sadface
This commit is contained in:
parent
e323d34dda
commit
e7cf05a6ba
|
@ -144,6 +144,35 @@ tr_list_find( tr_list * list,
|
||||||
return NULL;
|
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
|
int
|
||||||
tr_list_size( const tr_list * list )
|
tr_list_size( const tr_list * list )
|
||||||
{
|
{
|
||||||
|
|
|
@ -100,6 +100,17 @@ tr_list* tr_list_find( tr_list * list,
|
||||||
const void * b,
|
const void * b,
|
||||||
TrListCompareFunc compare_func );
|
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 */
|
#endif /* TR_LIST_H */
|
||||||
|
|
|
@ -184,6 +184,7 @@ struct verify_node
|
||||||
{
|
{
|
||||||
tr_torrent * torrent;
|
tr_torrent * torrent;
|
||||||
tr_verify_done_cb verify_done_cb;
|
tr_verify_done_cb verify_done_cb;
|
||||||
|
uint64_t current_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -252,27 +253,39 @@ verifyThreadFunc( void * unused UNUSED )
|
||||||
tr_lockUnlock( getVerifyLock( ) );
|
tr_lockUnlock( getVerifyLock( ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static tr_bool
|
static uint64_t
|
||||||
torrentHasAnyLocalData( const tr_torrent * tor )
|
getCurrentSize( tr_torrent * tor )
|
||||||
{
|
{
|
||||||
tr_file_index_t i;
|
tr_file_index_t i;
|
||||||
tr_bool hasAny = FALSE;
|
uint64_t byte_count = 0;
|
||||||
const tr_file_index_t n = tor->info.fileCount;
|
const tr_file_index_t n = tor->info.fileCount;
|
||||||
|
|
||||||
assert( tr_isTorrent( tor ) );
|
for( i=0; i<n; ++i )
|
||||||
|
|
||||||
for( i=0; i<n && !hasAny; ++i )
|
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
char * path = tr_torrentFindFile( tor, i );
|
char * filename = tr_torrentFindFile( tor, i );
|
||||||
if( ( path != NULL ) && !stat( path, &sb ) && ( sb.st_size > 0 ) )
|
|
||||||
hasAny = TRUE;
|
sb.st_size = 0;
|
||||||
tr_free( path );
|
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
|
void
|
||||||
tr_verifyAdd( tr_torrent * tor,
|
tr_verifyAdd( tr_torrent * tor,
|
||||||
tr_verify_done_cb verify_done_cb )
|
tr_verify_done_cb verify_done_cb )
|
||||||
|
@ -284,38 +297,44 @@ tr_verifyAdd( tr_torrent * tor,
|
||||||
/* doesn't need to be checked... */
|
/* doesn't need to be checked... */
|
||||||
fireCheckDone( tor, verify_done_cb );
|
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
|
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 );
|
tr_torinf( tor, "%s", _( "Queued for verification" ) );
|
||||||
node->torrent = tor;
|
|
||||||
node->verify_done_cb = verify_done_cb;
|
|
||||||
|
|
||||||
tr_lockLock( getVerifyLock( ) );
|
node = tr_new( struct verify_node, 1 );
|
||||||
tr_torrentSetVerifyState( tor, TR_VERIFY_WAIT );
|
node->torrent = tor;
|
||||||
tr_list_append( &verifyList, node );
|
node->verify_done_cb = verify_done_cb;
|
||||||
if( verifyThread == NULL )
|
node->current_size = current_size;
|
||||||
verifyThread = tr_threadNew( verifyThreadFunc, NULL );
|
|
||||||
tr_lockUnlock( getVerifyLock( ) );
|
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( ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue