test code for #575 (m1b's bug)

This commit is contained in:
Charles Kerr 2008-01-02 18:05:05 +00:00
parent e504a26c66
commit 0e56fa0baf
5 changed files with 77 additions and 53 deletions

View File

@ -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 );

View File

@ -47,7 +47,6 @@ enum
*/
uint64_t tr_fastResumeLoad( tr_torrent * tor,
uint64_t fieldsToLoad,
struct tr_bitfield * uncheckedPieces,
const tr_ctor * ctor );
#endif

View File

@ -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 );

View File

@ -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 );
}

View File

@ -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;