From 0e56fa0baf802ff5f7203bb5501d7de1932ff6cc Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 2 Jan 2008 18:05:05 +0000 Subject: [PATCH] test code for #575 (m1b's bug) --- libtransmission/fastresume.c | 30 ++++++--------- libtransmission/fastresume.h | 1 - libtransmission/inout.c | 19 +++------- libtransmission/torrent.c | 72 ++++++++++++++++++++++++++---------- libtransmission/torrent.h | 8 +++- 5 files changed, 77 insertions(+), 53 deletions(-) diff --git a/libtransmission/fastresume.c b/libtransmission/fastresume.c index 02c902c8e..a8ae0961d 100644 --- a/libtransmission/fastresume.c +++ b/libtransmission/fastresume.c @@ -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; iinfo.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; iinfo.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 ); diff --git a/libtransmission/fastresume.h b/libtransmission/fastresume.h index 8b77648df..e2860d14b 100644 --- a/libtransmission/fastresume.h +++ b/libtransmission/fastresume.h @@ -47,7 +47,6 @@ enum */ uint64_t tr_fastResumeLoad( tr_torrent * tor, uint64_t fieldsToLoad, - struct tr_bitfield * uncheckedPieces, const tr_ctor * ctor ); #endif diff --git a/libtransmission/inout.c b/libtransmission/inout.c index a05beab34..b64e0b43e 100644 --- a/libtransmission/inout.c +++ b/libtransmission/inout.c @@ -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; iinfo.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; iinfo.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 ); diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index fd5836009..2666d529f 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -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 ); +} diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index 57d5abcfa..f94ee305e 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -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;