set default torrent ul/dl speed limits from global ul/dl speed. as a side effect, totally decouples fastresume from inout.

This commit is contained in:
Charles Kerr 2007-07-23 03:00:20 +00:00
parent d5d68fb1f8
commit eaca893b4c
6 changed files with 130 additions and 120 deletions

View File

@ -146,7 +146,8 @@ static void fastResumeWriteData( uint8_t id, void * data, uint32_t size,
fwrite( data, size, count, file );
}
void fastResumeSave( const tr_torrent_t * tor )
void
tr_fastResumeSave( const tr_torrent_t * tor )
{
char path[MAX_PATH_LENGTH];
FILE * file;
@ -390,17 +391,20 @@ fastResumeLoadProgress( const tr_torrent_t * tor,
bitfield.len = FR_BLOCK_BITFIELD_LEN( tor );
bitfield.bits = walk;
tr_cpBlockBitfieldSet( tor->completion, &bitfield );
/* FIXME: remove the "unchecked pieces" */
}
free( buf );
return TR_OK;
}
static int
static uint64_t
fastResumeLoadOld( tr_torrent_t * tor,
tr_bitfield_t * uncheckedPieces,
FILE * file )
{
uint64_t ret = 0;
/* Check the size */
const int size = 4 + FR_PROGRESS_LEN( tor );
fseek( file, 0, SEEK_END );
@ -422,21 +426,22 @@ fastResumeLoadOld( tr_torrent_t * tor,
fclose( file );
ret |= TR_FR_PROGRESS;
tr_inf( "Fast resuming successful (version 0)" );
return 0;
return ret;
}
int
fastResumeLoad( tr_torrent_t * tor,
tr_bitfield_t * uncheckedPieces )
static uint64_t
fastResumeLoadImpl ( tr_torrent_t * tor,
tr_bitfield_t * uncheckedPieces )
{
char path[MAX_PATH_LENGTH];
FILE * file;
int version = 0;
uint8_t id;
uint32_t len;
int ret;
uint64_t ret = 0;
assert( tor != NULL );
assert( uncheckedPieces != NULL );
@ -444,22 +449,21 @@ fastResumeLoad( tr_torrent_t * tor,
/* Open resume file */
fastResumeFileName( path, sizeof path, tor, 1 );
file = fopen( path, "r" );
if( NULL == file )
if( !file )
{
if( ENOENT == errno )
{
fastResumeFileName( path, sizeof path, tor, 0 );
file = fopen( path, "r" );
if( NULL != file )
if( !file )
{
goto good;
fastResumeFileName( path, sizeof path, tor, 1 );
tr_inf( "Couldn't open '%s' for reading", path );
return ret;
}
fastResumeFileName( path, sizeof path, tor, 1 );
}
tr_inf( "Could not open '%s' for reading", path );
return 1;
}
good:
tr_dbg( "Resume file '%s' loaded", path );
/* Check format version */
@ -472,10 +476,9 @@ fastResumeLoad( tr_torrent_t * tor,
{
tr_inf( "Resume file has version %d, not supported", version );
fclose( file );
return 1;
return ret;
}
ret = 1;
/* read each block of data */
while( 1 == fread( &id, 1, 1, file ) && 1 == fread( &len, 4, 1, file ) )
{
@ -485,14 +488,15 @@ fastResumeLoad( tr_torrent_t * tor,
/* read progress data */
if( (uint32_t)FR_PROGRESS_LEN( tor ) == len )
{
ret = fastResumeLoadProgress( tor, uncheckedPieces, file );
const int rret = fastResumeLoadProgress( tor, uncheckedPieces, file );
if( ret && ( feof(file) || ferror(file) ) )
if( rret && ( feof(file) || ferror(file) ) )
{
fclose( file );
return 1;
return ret;
}
ret |= TR_FR_PROGRESS;
continue;
}
break;
@ -502,14 +506,15 @@ fastResumeLoad( tr_torrent_t * tor,
/* read priority data */
if( len == (uint32_t)(2 * tor->info.fileCount) )
{
ret = loadPriorities( tor, file );
const int rret = loadPriorities( tor, file );
if( ret && ( feof(file) || ferror(file) ) )
if( rret && ( feof(file) || ferror(file) ) )
{
fclose( file );
return 1;
return ret;
}
ret |= TR_FR_PRIORITY;
continue;
}
break;
@ -518,14 +523,15 @@ fastResumeLoad( tr_torrent_t * tor,
/* read speed data */
if( len == FR_SPEED_LEN )
{
ret = loadSpeeds( tor, file );
const int rret = loadSpeeds( tor, file );
if( ret && ( feof(file) || ferror(file) ) )
if( rret && ( feof(file) || ferror(file) ) )
{
fclose( file );
return 1;
return ret;
}
ret |= TR_FR_SPEEDLIMIT;
continue;
}
break;
@ -537,9 +543,10 @@ fastResumeLoad( tr_torrent_t * tor,
if( 1 != fread( &tor->downloadedPrev, 8, 1, file ) )
{
fclose( file );
return 1;
return ret;
}
tor->downloadedCur = 0;
ret |= TR_FR_DOWNLOADED;
continue;
}
break;
@ -551,8 +558,10 @@ fastResumeLoad( tr_torrent_t * tor,
if( 1 != fread( &tor->uploadedPrev, 8, 1, file ) )
{
fclose( file );
return 1;
return ret;
}
tor->uploadedCur = 0;
ret |= TR_FR_UPLOADED;
continue;
}
break;
@ -566,13 +575,14 @@ fastResumeLoad( tr_torrent_t * tor,
{
free( buf );
fclose( file );
return 1;
return ret;
}
used = tr_torrentAddCompact( tor, TR_PEER_FROM_CACHE,
buf, len / 6 );
tr_dbg( "found %i peers in resume file, used %i",
len / 6, used );
free( buf );
ret |= TR_FR_PEERS;
}
continue;
@ -586,11 +596,17 @@ fastResumeLoad( tr_torrent_t * tor,
}
fclose( file );
if( !ret )
{
tr_inf( "Fast resuming successful" );
}
return ret;
}
uint64_t
tr_fastResumeLoad( tr_torrent_t * tor,
tr_bitfield_t * uncheckedPieces )
{
const uint64_t ret = fastResumeLoadImpl( tor, uncheckedPieces );
if( ! ( ret & TR_FR_PROGRESS ) )
tr_bitfieldAddRange( uncheckedPieces, 0, tor->info.pieceCount );
return ret;
}

View File

@ -25,9 +25,22 @@
#ifndef TR_FAST_RESUME_H
#define TR_FAST_RESUME_H
void fastResumeSave( const tr_torrent_t * tor );
void tr_fastResumeSave( const tr_torrent_t * tor );
int fastResumeLoad( tr_torrent_t * tor,
tr_bitfield_t * uncheckedPieces );
enum
{
TR_FR_DOWNLOADED = (1<<0),
TR_FR_UPLOADED = (1<<1),
TR_FR_PEERS = (1<<2),
TR_FR_PROGRESS = (1<<3),
TR_FR_PRIORITY = (1<<4),
TR_FR_SPEEDLIMIT = (1<<5)
};
/**
* Returns a bitwise-or'ed set of the data loaded from fastresume
*/
uint64_t tr_fastResumeLoad( tr_torrent_t * tor,
tr_bitfield_t * uncheckedPieces );
#endif

View File

@ -12,7 +12,6 @@
#include <sys/stat.h>
#include <unistd.h>
#include "transmission.h"
#include "fastresume.h"
#include "fdlimit.h"
struct tr_io_s
@ -211,46 +210,28 @@ checkPiece ( tr_torrent_t * tor, int pieceIndex )
return ret;
}
int
tr_ioCheckFiles( tr_torrent_t * tor, int mode )
void
tr_ioCheckFiles( tr_torrent_t * tor )
{
int i;
tr_bitfield_t * uncheckedPieces = tr_bitfieldNew( tor->info.pieceCount );
tr_cpReset( tor->completion );
tr_bitfieldClear( uncheckedPieces );
if( (mode==TR_RECHECK_FORCE) || fastResumeLoad( tor, uncheckedPieces ) )
tr_bitfieldAddRange( uncheckedPieces, 0, tor->info.pieceCount );
if( tr_bitfieldIsEmpty( uncheckedPieces ) ) {
tr_bitfieldFree( uncheckedPieces );
return TR_OK;
}
if( mode == TR_RECHECK_FAST ) {
tr_bitfieldFree( uncheckedPieces );
return TR_ERROR_IO_OTHER;
}
tr_inf( "Verifying some pieces of \"%s\"", tor->info.name );
for( i=0; i<tor->info.pieceCount; ++i )
if( tor->uncheckedPieces != NULL )
{
if( !tr_bitfieldHas( uncheckedPieces, i ) )
continue;
int i;
tr_bitfield_t * p = tor->uncheckedPieces;
tor->uncheckedPieces = NULL;
tr_dbg ( "Checking piece %d because it's not in fast-resume", i );
tr_inf( "Verifying some pieces of \"%s\"", tor->info.name );
tr_torrentSetHasPiece( tor, i, !checkPiece( tor, i ) );
for( i=0; i<tor->info.pieceCount; ++i )
{
if( !tr_bitfieldHas( p, i ) )
continue;
tr_bitfieldRem( uncheckedPieces, i );
tr_torrentSetHasPiece( tor, i, !checkPiece( tor, i ) );
}
tr_bitfieldFree( p );
tor->fastResumeDirty = TRUE;
}
fastResumeSave( tor );
tr_bitfieldFree( uncheckedPieces );
return TR_OK;
}
/****
@ -258,17 +239,10 @@ tr_ioCheckFiles( tr_torrent_t * tor, int mode )
****/
tr_io_t*
tr_ioInitFast( tr_torrent_t * tor )
tr_ioNew ( tr_torrent_t * tor )
{
tr_io_t * io = tr_calloc( 1, sizeof( tr_io_t ) );
io->tor = tor;
if( tr_ioCheckFiles( tor, TR_RECHECK_FAST ) )
{
tr_free( io );
io = NULL;
}
return io;
}
@ -283,8 +257,6 @@ tr_ioSync( tr_io_t * io )
for( i=0; i<info->fileCount; ++i )
tr_fdFileClose( io->tor->destination, info->files[i].name );
fastResumeSave( io->tor );
}
}
@ -298,14 +270,6 @@ tr_ioClose( tr_io_t * io )
}
}
/* try to load the fast resume file */
int
tr_ioLoadResume( tr_torrent_t * tor )
{
return tr_ioCheckFiles ( tor, TR_RECHECK_FAST );
}
int
tr_ioHash( tr_io_t * io, int pieceIndex )
{

View File

@ -27,18 +27,9 @@
typedef struct tr_io_s tr_io_t;
int tr_ioLoadResume ( tr_torrent_t * );
void tr_ioCheckFiles ( tr_torrent_t * );
enum
{
TR_RECHECK_FAST, /* only try the fast resume, even if it's incomplete */
TR_RECHECK_FORCE /* ignore the fast resume data; recheck from disk */
};
int tr_ioCheckFiles ( tr_torrent_t *, int recheckMode );
tr_io_t * tr_ioInitFast ( tr_torrent_t * );
tr_io_t * tr_ioNew ( tr_torrent_t * );
/***********************************************************************
* tr_ioRead, tr_ioWrite

View File

@ -97,6 +97,7 @@ typedef enum { TR_NET_OK, TR_NET_ERROR, TR_NET_WAIT } tr_tristate_t;
#include "peer.h"
#include "inout.h"
#include "ratecontrol.h"
#include "utils.h"
#ifndef TRUE
#define TRUE 1
@ -189,7 +190,7 @@ struct tr_torrent_s
tr_completion_t * completion;
volatile char dieFlag;
volatile char recheckFlag;
tr_bitfield_t * uncheckedPieces;
run_status_t runStatus;
cp_status_t cpStatus;
tr_thread_t thread;

View File

@ -180,7 +180,9 @@ torrentRealInit( tr_handle_t * h,
int flags )
{
int i;
uint64_t loaded;
char name[512];
tr_bitfield_t * uncheckedPieces;
tor->info.flags |= flags;
@ -231,7 +233,25 @@ torrentRealInit( tr_handle_t * h,
tor->error = TR_OK;
tor->runStatus = flags & TR_FLAG_PAUSED ? TR_RUN_STOPPED : TR_RUN_RUNNING;
tor->recheckFlag = tr_ioCheckFiles( tor, TR_RECHECK_FAST );
uncheckedPieces = tr_bitfieldNew( tor->info.pieceCount );
loaded = tr_fastResumeLoad( tor, uncheckedPieces );
if( tr_bitfieldIsEmpty( uncheckedPieces ) )
tr_bitfieldFree( uncheckedPieces );
else {
tor->uncheckedPieces = uncheckedPieces;
fprintf( stderr, "torrent %s has %d unchecked pieces\n", tor->info.name, (int)tr_bitfieldCountTrueBits(tor->uncheckedPieces) );
}
if( !(loaded & TR_FR_SPEEDLIMIT ) ) {
int limit, enabled;
tr_getGlobalSpeedLimit( tor->handle, TR_UP, &enabled, &limit );
tr_torrentSetSpeedLimit( tor, TR_UP, limit );
tr_getGlobalSpeedLimit( tor->handle, TR_DOWN, &enabled, &limit );
tr_torrentSetSpeedLimit( tor, TR_DOWN, limit );
}
tor->cpStatus = tr_cpGetStatus( tor->completion );
tr_sharedLock( h->shared );
@ -444,16 +464,23 @@ int tr_torrentScrape( tr_torrent_t * tor, int * s, int * l, int * d )
}
#endif
void tr_torrentSetFolder( tr_torrent_t * tor, const char * path )
static void
fastResumeSave( tr_torrent_t * tor )
{
tr_fastResumeSave( tor );
tor->fastResumeDirty = FALSE;
}
void
tr_torrentSetFolder( tr_torrent_t * tor, const char * path )
{
tr_free( tor->destination );
tor->destination = tr_strdup( path );
if( !tor->ioLoaded )
tor->ioLoaded = tr_ioLoadResume( tor ) == TR_OK;
fastResumeSave( tor );
}
const char* tr_torrentGetFolder( const tr_torrent_t * tor )
const char*
tr_torrentGetFolder( const tr_torrent_t * tor )
{
return tor->destination;
}
@ -582,7 +609,7 @@ tr_torrentStat( tr_torrent_t * tor )
s->left = tr_cpLeftUntilDone ( tor->completion );
if( tor->recheckFlag )
if( tor->uncheckedPieces )
s->status = TR_STATUS_CHECK_WAIT;
else switch( tor->runStatus ) {
case TR_RUN_STOPPING: /* fallthrough */
@ -855,7 +882,9 @@ void tr_torrentRemoveSaved( tr_torrent_t * tor )
void tr_torrentRecheck( tr_torrent_t * tor )
{
tor->recheckFlag = TRUE;
if( !tor->uncheckedPieces )
tor->uncheckedPieces = tr_bitfieldNew( tor->info.pieceCount );
tr_bitfieldAddRange( tor->uncheckedPieces, 0, tor->info.pieceCount );
}
@ -997,6 +1026,7 @@ recheckCpState( tr_torrent_t * tor )
tr_trackerCompleted( tor->tracker ); /* tell the tracker */
}
tr_ioSync( tor->io );
fastResumeSave( tor );
}
tr_torrentWriterUnlock( tor );
}
@ -1022,7 +1052,6 @@ torrentThreadLoop ( void * _tor )
if( tor->fastResumeDirty )
{
tor->fastResumeDirty = FALSE;
fastResumeSave( tor );
recheckCpState( tor );
}
@ -1038,6 +1067,7 @@ torrentThreadLoop ( void * _tor )
/* close the IO */
tr_ioClose( tor->io );
tor->io = NULL;
fastResumeSave( tor );
/* close the peers */
for( i=0; i<tor->peerCount; ++i )
@ -1078,7 +1108,7 @@ torrentThreadLoop ( void * _tor )
}
/* do we need to check files? */
if( tor->recheckFlag )
if( tor->uncheckedPieces )
{
if( !tr_lockTryLock( &checkFilesLock ) )
{
@ -1086,11 +1116,10 @@ torrentThreadLoop ( void * _tor )
tr_torrentWriterLock( tor );
realStatus = tor->runStatus;
tor->recheckFlag = FALSE;
tor->runStatus = TR_RUN_CHECKING;
tr_torrentWriterUnlock( tor );
tr_ioCheckFiles( tor, TR_RECHECK_FORCE );
tr_ioCheckFiles( tor );
setRunState( tor, realStatus );
tr_torrentWriterLock( tor );
@ -1117,11 +1146,7 @@ torrentThreadLoop ( void * _tor )
if( tor->io == NULL ) {
*tor->errorString = '\0';
tr_torrentResetTransferStats( tor );
tor->io = tr_ioInitFast( tor );
if( tor->io == NULL ) {
tor->recheckFlag = TRUE;
continue;
}
tor->io = tr_ioNew( tor );
tr_peerIdNew ( tor->peer_id, sizeof(tor->peer_id) );
tor->tracker = tr_trackerInit( tor );
tor->startDate = tr_date();