test code for #575 (m1b's bug)
This commit is contained in:
parent
e504a26c66
commit
0e56fa0baf
|
@ -415,10 +415,9 @@ parseUnchoked( tr_torrent * tor, const uint8_t * buf, uint32_t len )
|
|||
}
|
||||
|
||||
static uint64_t
|
||||
parseProgress( const tr_torrent * tor,
|
||||
const uint8_t * buf,
|
||||
uint32_t len,
|
||||
tr_bitfield * uncheckedPieces )
|
||||
parseProgress( tr_torrent * tor,
|
||||
const uint8_t * buf,
|
||||
uint32_t len )
|
||||
{
|
||||
int i;
|
||||
uint64_t ret = 0;
|
||||
|
@ -433,12 +432,10 @@ parseProgress( const tr_torrent * tor,
|
|||
const uint8_t * walk = buf;
|
||||
const tr_time_t * oldMTimes = (const tr_time_t *) walk;
|
||||
for( i=0; i<n; ++i ) {
|
||||
if ( !curMTimes[i] || ( curMTimes[i] != oldMTimes[i] ) ) {
|
||||
if ( curMTimes[i] && ( curMTimes[i] == oldMTimes[i] ) ) {
|
||||
const tr_file * file = &tor->info.files[i];
|
||||
tr_dbg( "File '%s' mtimes differ-- flagging pieces [%d..%d] for recheck",
|
||||
file->name, file->firstPiece, file->lastPiece);
|
||||
tr_bitfieldAddRange( uncheckedPieces,
|
||||
file->firstPiece, file->lastPiece+1 );
|
||||
tr_dbg( "File '%s' mtimes match -- no recheck needed", file->name );
|
||||
tr_torrentSetFileChecked( tor, i, TRUE );
|
||||
}
|
||||
}
|
||||
free( curMTimes );
|
||||
|
@ -456,7 +453,7 @@ parseProgress( const tr_torrent * tor,
|
|||
/* the files whose mtimes are wrong,
|
||||
remove from completion pending a recheck... */
|
||||
for( i=0; i<tor->info.pieceCount; ++i )
|
||||
if( tr_bitfieldHas( uncheckedPieces, i ) )
|
||||
if( !tr_torrentIsPieceChecked( tor, i ) )
|
||||
tr_cpPieceRem( tor->completion, i );
|
||||
|
||||
return ret;
|
||||
|
@ -580,8 +577,7 @@ parseDestination( tr_torrent * tor, const uint8_t * buf, uint32_t len )
|
|||
|
||||
static uint64_t
|
||||
parseVersion1( tr_torrent * tor, const uint8_t * buf, const uint8_t * end,
|
||||
uint64_t fieldsToLoad,
|
||||
tr_bitfield * uncheckedPieces )
|
||||
uint64_t fieldsToLoad )
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
|
||||
|
@ -596,7 +592,7 @@ parseVersion1( tr_torrent * tor, const uint8_t * buf, const uint8_t * end,
|
|||
{
|
||||
case FR_ID_DOWNLOADED: ret |= parseDownloaded( tor, buf, len ); break;
|
||||
case FR_ID_UPLOADED: ret |= parseUploaded( tor, buf, len ); break;
|
||||
case FR_ID_PROGRESS: ret |= parseProgress( tor, buf, len, uncheckedPieces ); break;
|
||||
case FR_ID_PROGRESS: ret |= parseProgress( tor, buf, len ); break;
|
||||
case FR_ID_PRIORITY: ret |= parsePriorities( tor, buf, len ); break;
|
||||
case FR_ID_SPEED: ret |= parseSpeedLimit( tor, buf, len ); break;
|
||||
case FR_ID_RUN: ret |= parseRun( tor, buf, len ); break;
|
||||
|
@ -641,8 +637,7 @@ loadResumeFile( const tr_torrent * tor, size_t * len )
|
|||
|
||||
static uint64_t
|
||||
fastResumeLoadImpl ( tr_torrent * tor,
|
||||
uint64_t fieldsToLoad,
|
||||
tr_bitfield * uncheckedPieces )
|
||||
uint64_t fieldsToLoad )
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
size_t size = 0;
|
||||
|
@ -657,7 +652,7 @@ fastResumeLoadImpl ( tr_torrent * tor,
|
|||
uint32_t version;
|
||||
readBytes( &version, &walk, sizeof(version) );
|
||||
if( version == 1 )
|
||||
ret |= parseVersion1 ( tor, walk, end, fieldsToLoad, uncheckedPieces );
|
||||
ret |= parseVersion1 ( tor, walk, end, fieldsToLoad );
|
||||
else
|
||||
tr_inf( "Unsupported resume file %d for '%s'", version, tor->info.name );
|
||||
}
|
||||
|
@ -708,14 +703,13 @@ useFallbackFields( tr_torrent * tor, uint64_t fields, const tr_ctor * ctor )
|
|||
uint64_t
|
||||
tr_fastResumeLoad( tr_torrent * tor,
|
||||
uint64_t fieldsToLoad,
|
||||
tr_bitfield * uncheckedPieces,
|
||||
const tr_ctor * ctor )
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
|
||||
ret |= useManditoryFields( tor, fieldsToLoad, ctor );
|
||||
fieldsToLoad &= ~ret;
|
||||
ret |= fastResumeLoadImpl( tor, fieldsToLoad, uncheckedPieces );
|
||||
ret |= fastResumeLoadImpl( tor, fieldsToLoad );
|
||||
fieldsToLoad &= ~ret;
|
||||
ret |= useFallbackFields( tor, fieldsToLoad, ctor );
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ enum
|
|||
*/
|
||||
uint64_t tr_fastResumeLoad( tr_torrent * tor,
|
||||
uint64_t fieldsToLoad,
|
||||
struct tr_bitfield * uncheckedPieces,
|
||||
const tr_ctor * ctor );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -255,7 +255,6 @@ checkPiece( tr_torrent * tor, int pieceIndex )
|
|||
static void
|
||||
checkFile( tr_torrent * tor,
|
||||
int fileIndex,
|
||||
tr_bitfield * uncheckedPieces,
|
||||
int * abortFlag )
|
||||
{
|
||||
int i;
|
||||
|
@ -273,11 +272,11 @@ checkFile( tr_torrent * tor,
|
|||
{
|
||||
tr_torrentSetHasPiece( tor, i, 0 );
|
||||
}
|
||||
else if( tr_bitfieldHas( uncheckedPieces, i ) )
|
||||
else if( !tr_torrentIsPieceChecked( tor, i ) )
|
||||
{
|
||||
const int check = checkPiece( tor, i );
|
||||
tr_torrentSetHasPiece( tor, i, !check );
|
||||
tr_bitfieldRem( uncheckedPieces, i );
|
||||
tr_torrentSetPieceChecked( tor, i, TRUE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -368,29 +367,21 @@ recheckThreadFunc( void * unused UNUSED )
|
|||
tr_free( node );
|
||||
tr_lockUnlock( getRecheckLock( ) );
|
||||
|
||||
if( tor->uncheckedPieces == NULL ) {
|
||||
tor->recheckState = TR_RECHECK_NONE;
|
||||
fireCheckDone( tor, currentNode.recheck_done_cb );
|
||||
continue;
|
||||
}
|
||||
|
||||
tor->recheckState = TR_RECHECK_NOW;
|
||||
|
||||
/* remove the unchecked pieces from completion... */
|
||||
for( i=0; i<tor->info.pieceCount; ++i )
|
||||
if( tr_bitfieldHas( tor->uncheckedPieces, i ) )
|
||||
if( !tr_torrentIsPieceChecked( tor, i ) )
|
||||
tr_cpPieceRem( tor->completion, i );
|
||||
|
||||
tr_inf( "Verifying some pieces of \"%s\"", tor->info.name );
|
||||
for( i=0; i<tor->info.fileCount && !stopCurrent; ++i )
|
||||
checkFile( tor, i, tor->uncheckedPieces, &stopCurrent );
|
||||
checkFile( tor, i, &stopCurrent );
|
||||
|
||||
tor->recheckState = TR_RECHECK_NONE;
|
||||
|
||||
if( !stopCurrent )
|
||||
{
|
||||
tr_bitfieldFree( tor->uncheckedPieces );
|
||||
tor->uncheckedPieces = NULL;
|
||||
tr_fastResumeSave( tor );
|
||||
fireCheckDone( tor, currentNode.recheck_done_cb );
|
||||
}
|
||||
|
@ -404,7 +395,7 @@ void
|
|||
tr_ioRecheckAdd( tr_torrent * tor,
|
||||
tr_recheck_done_cb recheck_done_cb )
|
||||
{
|
||||
if( !tr_bitfieldCountTrueBits( tor->uncheckedPieces ) )
|
||||
if( tr_torrentCountUncheckedPieces( tor ) == 0 )
|
||||
{
|
||||
/* doesn't need to be checked... */
|
||||
recheck_done_cb( tor );
|
||||
|
|
|
@ -273,7 +273,6 @@ torrentRealInit( tr_handle * h,
|
|||
int doStart;
|
||||
uint64_t loaded;
|
||||
uint64_t t;
|
||||
tr_bitfield * uncheckedPieces;
|
||||
tr_info * info = &tor->info;
|
||||
|
||||
tr_globalLock( h );
|
||||
|
@ -345,20 +344,15 @@ torrentRealInit( tr_handle * h,
|
|||
|
||||
tor->error = TR_OK;
|
||||
|
||||
uncheckedPieces = tr_bitfieldNew( tor->info.pieceCount );
|
||||
|
||||
loaded = tr_fastResumeLoad( tor, ~0, uncheckedPieces, ctor );
|
||||
tor->checkedPieces = tr_bitfieldNew( tor->info.pieceCount );
|
||||
tr_torrentUncheck( tor );
|
||||
loaded = tr_fastResumeLoad( tor, ~0, ctor );
|
||||
|
||||
assert( tor->destination != NULL );
|
||||
|
||||
doStart = tor->isRunning;
|
||||
tor->isRunning = 0;
|
||||
|
||||
if( tr_bitfieldIsEmpty( uncheckedPieces ) )
|
||||
tr_bitfieldFree( uncheckedPieces );
|
||||
else
|
||||
tor->uncheckedPieces = uncheckedPieces;
|
||||
|
||||
if( !(loaded & TR_FR_SPEEDLIMIT ) ) {
|
||||
int limit, enabled;
|
||||
tr_getGlobalSpeedLimit( tor->handle, TR_UP, &enabled, &limit );
|
||||
|
@ -607,9 +601,8 @@ tr_torrentStat( tr_torrent * tor )
|
|||
else
|
||||
s->status = TR_STATUS_SEED;
|
||||
|
||||
s->recheckProgress = (tor->uncheckedPieces == NULL)
|
||||
? 0.0
|
||||
: 1.0 - ((double)tr_bitfieldCountTrueBits(tor->uncheckedPieces) / tor->info.pieceCount);
|
||||
s->recheckProgress =
|
||||
1.0 - (tr_torrentCountUncheckedPieces( tor ) / (double) tor->info.pieceCount);
|
||||
|
||||
tr_torrentGetRates( tor, &s->rateDownload, &s->rateUpload );
|
||||
|
||||
|
@ -850,6 +843,8 @@ freeTorrent( tr_torrent * tor )
|
|||
tr_trackerFree( tor->tracker );
|
||||
tor->tracker = NULL;
|
||||
|
||||
tr_bitfieldFree( tor->checkedPieces );
|
||||
|
||||
tr_free( tor->destination );
|
||||
|
||||
if( tor == h->torrentList )
|
||||
|
@ -913,9 +908,7 @@ tr_torrentStart( tr_torrent * tor )
|
|||
|
||||
if( !tor->isRunning )
|
||||
{
|
||||
if( !tor->uncheckedPieces )
|
||||
tor->uncheckedPieces = tr_bitfieldNew( tor->info.pieceCount );
|
||||
tr_fastResumeLoad( tor, TR_FR_PROGRESS, tor->uncheckedPieces, NULL );
|
||||
tr_fastResumeLoad( tor, TR_FR_PROGRESS, NULL );
|
||||
tor->isRunning = 1;
|
||||
tr_ioRecheckAdd( tor, checkAndStartCB );
|
||||
}
|
||||
|
@ -938,10 +931,7 @@ tr_torrentRecheck( tr_torrent * tor )
|
|||
{
|
||||
tr_globalLock( tor->handle );
|
||||
|
||||
if( !tor->uncheckedPieces )
|
||||
tor->uncheckedPieces = tr_bitfieldNew( tor->info.pieceCount );
|
||||
tr_bitfieldAddRange( tor->uncheckedPieces, 0, tor->info.pieceCount );
|
||||
|
||||
tr_torrentUncheck( tor );
|
||||
tr_ioRecheckAdd( tor, torrentRecheckDoneCB );
|
||||
|
||||
tr_globalUnlock( tor->handle );
|
||||
|
@ -1267,3 +1257,47 @@ tr_pieceOffset( const tr_torrent * tor, int index, int begin, int length )
|
|||
ret += length;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
int
|
||||
tr_torrentIsPieceChecked( const tr_torrent * tor, int piece )
|
||||
{
|
||||
return tr_bitfieldHas( tor->checkedPieces, piece );
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentSetPieceChecked( tr_torrent * tor, int piece, int isChecked )
|
||||
{
|
||||
if( isChecked )
|
||||
tr_bitfieldAdd( tor->checkedPieces, piece );
|
||||
else
|
||||
tr_bitfieldRem( tor->checkedPieces, piece );
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentSetFileChecked( tr_torrent * tor, int fileIndex, int isChecked )
|
||||
{
|
||||
const tr_file * file = &tor->info.files[fileIndex];
|
||||
const size_t begin = file->firstPiece;
|
||||
const size_t end = file->lastPiece + 1;
|
||||
|
||||
if( isChecked )
|
||||
tr_bitfieldAddRange ( tor->checkedPieces, begin, end );
|
||||
else
|
||||
tr_bitfieldRemRange ( tor->checkedPieces, begin, end );
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentUncheck( tr_torrent * tor )
|
||||
{
|
||||
tr_bitfieldRemRange ( tor->checkedPieces, 0, tor->info.pieceCount );
|
||||
}
|
||||
|
||||
int
|
||||
tr_torrentCountUncheckedPieces( const tr_torrent * tor )
|
||||
{
|
||||
return tr_bitfieldCountTrueBits( tor->checkedPieces );
|
||||
}
|
||||
|
|
|
@ -82,6 +82,12 @@ void tr_torrentInitFilePriority( tr_torrent * tor,
|
|||
tr_priority_t priority );
|
||||
|
||||
|
||||
int tr_torrentCountUncheckedPieces( const tr_torrent * );
|
||||
int tr_torrentIsPieceChecked ( const tr_torrent *, int piece );
|
||||
void tr_torrentSetPieceChecked ( tr_torrent *, int piece, int isChecked );
|
||||
void tr_torrentSetFileChecked ( tr_torrent *, int file, int isChecked );
|
||||
void tr_torrentUncheck ( tr_torrent * );
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_RECHECK_NONE,
|
||||
|
@ -123,7 +129,7 @@ struct tr_torrent
|
|||
|
||||
struct tr_completion * completion;
|
||||
|
||||
struct tr_bitfield * uncheckedPieces;
|
||||
struct tr_bitfield * checkedPieces;
|
||||
cp_status_t cpStatus;
|
||||
|
||||
struct tr_tracker * tracker;
|
||||
|
|
Loading…
Reference in New Issue