(trunk) experimental support for tr_torrentSetPriority()
This commit is contained in:
parent
b5487b3454
commit
03fa0b3e7d
|
@ -88,6 +88,7 @@
|
|||
|
||||
string | value type & description
|
||||
----------------------------------+-------------------------------------------------
|
||||
"bandwidthPriority" | number this torrent's bandwidth tr_priority_t
|
||||
"downloadLimit" | number maximum download speed (in K/s)
|
||||
"downloadLimited" | boolean true if "downloadLimit" is honored
|
||||
"files-wanted" | array indices of file(s) to download
|
||||
|
@ -132,6 +133,7 @@
|
|||
addedDate | number | tr_stat
|
||||
announceResponse | string | tr_stat
|
||||
announceURL | string | tr_stat
|
||||
bandwidthPriority | number | tr_priority_t
|
||||
comment | string | tr_info
|
||||
corruptEver | number | tr_stat
|
||||
creator | string | tr_info
|
||||
|
@ -469,6 +471,8 @@
|
|||
5 | 1.60 | yes | torrent-get | new arg "pieces"
|
||||
| | yes | torrent-get | new arg "fileStats"
|
||||
| | yes | torrent-set | new arg "ratio"
|
||||
| | yes | torrent-get | new arg "bandwidthPriority"
|
||||
| | yes | torrent-set | new arg "bandwidthPriority"
|
||||
| | yes | torrent-set | new arg "downloadLimited"
|
||||
| | yes | torrent-set | new arg "uploadLimited"
|
||||
| | yes | torrent-set | new arg "honorsSessionLimits"
|
||||
|
|
|
@ -148,10 +148,13 @@ tr_bandwidthSetParent( tr_bandwidth * b,
|
|||
|
||||
static void
|
||||
allocateBandwidth( tr_bandwidth * b,
|
||||
tr_priority_t parent_priority,
|
||||
tr_direction dir,
|
||||
int period_msec,
|
||||
tr_ptrArray * peer_pool )
|
||||
{
|
||||
tr_priority_t priority;
|
||||
|
||||
assert( tr_isBandwidth( b ) );
|
||||
assert( tr_isDirection( dir ) );
|
||||
|
||||
|
@ -170,9 +173,13 @@ allocateBandwidth( tr_bandwidth * b,
|
|||
#endif
|
||||
}
|
||||
|
||||
priority = MAX( parent_priority, b->priority );
|
||||
|
||||
/* add this bandwidth's peer, if any, to the peer pool */
|
||||
if( b->peer != NULL )
|
||||
if( b->peer != NULL ) {
|
||||
b->peer->priority = priority;
|
||||
tr_ptrArrayAppend( peer_pool, b->peer );
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DIRECTION
|
||||
if( ( dir == DEBUG_DIRECTION ) && ( n > 1 ) )
|
||||
|
@ -185,28 +192,16 @@ fprintf( stderr, "bandwidth %p has %d peers\n", b, n );
|
|||
struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayBase( &b->children );
|
||||
const int n = tr_ptrArraySize( &b->children );
|
||||
for( i=0; i<n; ++i )
|
||||
allocateBandwidth( children[i], dir, period_msec, peer_pool );
|
||||
allocateBandwidth( children[i], priority, dir, period_msec, peer_pool );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_bandwidthAllocate( tr_bandwidth * b,
|
||||
tr_direction dir,
|
||||
int period_msec )
|
||||
static void
|
||||
phaseOne( tr_ptrArray * peerArray, tr_direction dir )
|
||||
{
|
||||
int i, n, peerCount;
|
||||
tr_ptrArray tmp = TR_PTR_ARRAY_INIT;
|
||||
struct tr_peerIo ** peers;
|
||||
|
||||
/* allocateBandwidth() is a helper function with two purposes:
|
||||
* 1. allocate bandwidth to b and its subtree
|
||||
* 2. accumulate an array of all the peerIos from b and its subtree. */
|
||||
allocateBandwidth( b, dir, period_msec, &tmp );
|
||||
peers = (struct tr_peerIo**) tr_ptrArrayBase( &tmp );
|
||||
peerCount = tr_ptrArraySize( &tmp );
|
||||
|
||||
for( i=0; i<peerCount; ++i )
|
||||
tr_peerIoRef( peers[i] );
|
||||
int i, n;
|
||||
int peerCount = tr_ptrArraySize( peerArray );
|
||||
struct tr_peerIo ** peers = (struct tr_peerIo**) tr_ptrArrayBase( peerArray );
|
||||
|
||||
/* First phase of IO. Tries to distribute bandwidth fairly to keep faster
|
||||
* peers from starving the others. Loop through the peers, giving each a
|
||||
|
@ -235,6 +230,43 @@ tr_bandwidthAllocate( tr_bandwidth * b,
|
|||
if( i == n )
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_bandwidthAllocate( tr_bandwidth * b,
|
||||
tr_direction dir,
|
||||
int period_msec )
|
||||
{
|
||||
int i, peerCount;
|
||||
tr_ptrArray tmp = TR_PTR_ARRAY_INIT;
|
||||
tr_ptrArray low = TR_PTR_ARRAY_INIT;
|
||||
tr_ptrArray high = TR_PTR_ARRAY_INIT;
|
||||
tr_ptrArray normal = TR_PTR_ARRAY_INIT;
|
||||
struct tr_peerIo ** peers;
|
||||
|
||||
/* allocateBandwidth() is a helper function with two purposes:
|
||||
* 1. allocate bandwidth to b and its subtree
|
||||
* 2. accumulate an array of all the peerIos from b and its subtree. */
|
||||
allocateBandwidth( b, TR_PRI_LOW, dir, period_msec, &tmp );
|
||||
peers = (struct tr_peerIo**) tr_ptrArrayBase( &tmp );
|
||||
peerCount = tr_ptrArraySize( &tmp );
|
||||
|
||||
for( i=0; i<peerCount; ++i ) {
|
||||
tr_peerIoRef( peers[i] );
|
||||
switch( peers[i]->priority ) {
|
||||
case TR_PRI_HIGH: tr_ptrArrayAppend( &high, peers[i] ); break;
|
||||
case TR_PRI_LOW: tr_ptrArrayAppend( &low, peers[i] ); break;
|
||||
default: tr_ptrArrayAppend( &normal, peers[i] ); break;
|
||||
}
|
||||
}
|
||||
|
||||
/* First phase of IO. Tries to distribute bandwidth fairly to keep faster
|
||||
* peers from starving the others. Loop through the peers, giving each a
|
||||
* small chunk of bandwidth. Keep looping until we run out of bandwidth
|
||||
* and/or peers that can use it */
|
||||
phaseOne( &high, dir );
|
||||
phaseOne( &normal, dir );
|
||||
phaseOne( &low, dir );
|
||||
|
||||
/* Second phase of IO. To help us scale in high bandwidth situations,
|
||||
* enable on-demand IO for peers with bandwidth left to burn.
|
||||
|
@ -247,6 +279,9 @@ tr_bandwidthAllocate( tr_bandwidth * b,
|
|||
tr_peerIoUnref( peers[i] );
|
||||
|
||||
/* cleanup */
|
||||
tr_ptrArrayDestruct( &normal, NULL );
|
||||
tr_ptrArrayDestruct( &high, NULL );
|
||||
tr_ptrArrayDestruct( &low, NULL );
|
||||
tr_ptrArrayDestruct( &tmp, NULL );
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ typedef struct tr_bandwidth
|
|||
|
||||
struct tr_band band[2];
|
||||
struct tr_bandwidth * parent;
|
||||
tr_priority_t priority;
|
||||
int magicNumber;
|
||||
tr_session * session;
|
||||
tr_ptrArray children; /* struct tr_bandwidth */
|
||||
|
|
|
@ -181,7 +181,7 @@ internalIdToPublicBitfield( uint8_t id )
|
|||
ret = TR_FR_PROGRESS; break;
|
||||
|
||||
case FR_ID_PRIORITY:
|
||||
ret = TR_FR_PRIORITY; break;
|
||||
ret = TR_FR_FILE_PRIORITIES; break;
|
||||
|
||||
case FR_ID_SPEED:
|
||||
ret = TR_FR_SPEEDLIMIT; break;
|
||||
|
@ -366,7 +366,7 @@ parsePriorities( tr_torrent * tor,
|
|||
tr_free( dnd );
|
||||
tr_free( dl );
|
||||
|
||||
ret = TR_FR_PRIORITY;
|
||||
ret = TR_FR_FILE_PRIORITIES;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -69,6 +69,8 @@ typedef struct tr_peerIo
|
|||
* for reading or writing */
|
||||
tr_bool hasFinishedConnecting;
|
||||
|
||||
tr_priority_t priority;
|
||||
|
||||
int pendingEvents;
|
||||
|
||||
int magicNumber;
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
#define KEY_PAUSED "paused"
|
||||
#define KEY_PEERS "peers"
|
||||
#define KEY_PEERS6 "peers6"
|
||||
#define KEY_PRIORITY "priority"
|
||||
#define KEY_FILE_PRIORITIES "priority"
|
||||
#define KEY_BANDWIDTH_PRIORITY "bandwidth-priority"
|
||||
#define KEY_PROGRESS "progress"
|
||||
#define KEY_SPEEDLIMIT_OLD "speed-limit"
|
||||
#define KEY_SPEEDLIMIT_UP "speed-limit-up"
|
||||
|
@ -189,7 +190,7 @@ loadDND( tr_benc * dict,
|
|||
|
||||
tr_free( dnd );
|
||||
tr_free( dl );
|
||||
ret = TR_FR_PRIORITY;
|
||||
ret = TR_FR_DND;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -207,29 +208,27 @@ loadDND( tr_benc * dict,
|
|||
***/
|
||||
|
||||
static void
|
||||
savePriorities( tr_benc * dict,
|
||||
const tr_torrent * tor )
|
||||
saveFilePriorities( tr_benc * dict, const tr_torrent * tor )
|
||||
{
|
||||
const tr_info * inf = tr_torrentInfo( tor );
|
||||
const tr_file_index_t n = inf->fileCount;
|
||||
tr_file_index_t i;
|
||||
tr_benc * list;
|
||||
|
||||
list = tr_bencDictAddList( dict, KEY_PRIORITY, n );
|
||||
list = tr_bencDictAddList( dict, KEY_FILE_PRIORITIES, n );
|
||||
for( i = 0; i < n; ++i )
|
||||
tr_bencListAddInt( list, inf->files[i].priority );
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
loadPriorities( tr_benc * dict,
|
||||
tr_torrent * tor )
|
||||
loadFilePriorities( tr_benc * dict, tr_torrent * tor )
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
tr_info * inf = &tor->info;
|
||||
const tr_file_index_t n = inf->fileCount;
|
||||
tr_benc * list;
|
||||
|
||||
if( tr_bencDictFindList( dict, KEY_PRIORITY, &list )
|
||||
if( tr_bencDictFindList( dict, KEY_FILE_PRIORITIES, &list )
|
||||
&& ( tr_bencListSize( list ) == n ) )
|
||||
{
|
||||
int64_t priority;
|
||||
|
@ -237,7 +236,7 @@ loadPriorities( tr_benc * dict,
|
|||
for( i = 0; i < n; ++i )
|
||||
if( tr_bencGetInt( tr_bencListChild( list, i ), &priority ) )
|
||||
tr_torrentInitFilePriority( tor, i, priority );
|
||||
ret = TR_FR_PRIORITY;
|
||||
ret = TR_FR_FILE_PRIORITIES;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -502,9 +501,11 @@ tr_torrentSaveResume( const tr_torrent * tor )
|
|||
tor->uploadedPrev + tor->uploadedCur );
|
||||
tr_bencDictAddInt( &top, KEY_MAX_PEERS,
|
||||
tor->maxConnectedPeers );
|
||||
tr_bencDictAddInt( &top, KEY_BANDWIDTH_PRIORITY,
|
||||
tr_torrentGetPriority( tor ) );
|
||||
tr_bencDictAddBool( &top, KEY_PAUSED, !tor->isRunning );
|
||||
savePeers( &top, tor );
|
||||
savePriorities( &top, tor );
|
||||
saveFilePriorities( &top, tor );
|
||||
saveDND( &top, tor );
|
||||
saveProgress( &top, tor );
|
||||
saveSpeedLimits( &top, tor );
|
||||
|
@ -614,11 +615,19 @@ loadFromFile( tr_torrent * tor,
|
|||
fieldsLoaded |= TR_FR_ACTIVITY_DATE;
|
||||
}
|
||||
|
||||
if( ( fieldsToLoad & TR_FR_BANDWIDTH_PRIORITY )
|
||||
&& tr_bencDictFindInt( &top, KEY_BANDWIDTH_PRIORITY, &i )
|
||||
&& tr_isPriority( i ) )
|
||||
{
|
||||
tr_torrentSetPriority( tor, i );
|
||||
fieldsLoaded |= TR_FR_BANDWIDTH_PRIORITY;
|
||||
}
|
||||
|
||||
if( fieldsToLoad & TR_FR_PEERS )
|
||||
fieldsLoaded |= loadPeers( &top, tor );
|
||||
|
||||
if( fieldsToLoad & TR_FR_PRIORITY )
|
||||
fieldsLoaded |= loadPriorities( &top, tor );
|
||||
if( fieldsToLoad & TR_FR_FILE_PRIORITIES )
|
||||
fieldsLoaded |= loadFilePriorities( &top, tor );
|
||||
|
||||
if( fieldsToLoad & TR_FR_PROGRESS )
|
||||
fieldsLoaded |= loadProgress( &top, tor );
|
||||
|
|
|
@ -25,15 +25,16 @@ enum
|
|||
TR_FR_PEERS = ( 1 << 3 ),
|
||||
TR_FR_PROGRESS = ( 1 << 4 ),
|
||||
TR_FR_DND = ( 1 << 5 ),
|
||||
TR_FR_PRIORITY = ( 1 << 6 ),
|
||||
TR_FR_SPEEDLIMIT = ( 1 << 7 ),
|
||||
TR_FR_RUN = ( 1 << 8 ),
|
||||
TR_FR_DOWNLOAD_DIR = ( 1 << 9 ),
|
||||
TR_FR_MAX_PEERS = ( 1 << 10 ),
|
||||
TR_FR_ADDED_DATE = ( 1 << 11 ),
|
||||
TR_FR_DONE_DATE = ( 1 << 12 ),
|
||||
TR_FR_ACTIVITY_DATE = ( 1 << 13 ),
|
||||
TR_FR_RATIOLIMIT = ( 1 << 14 )
|
||||
TR_FR_FILE_PRIORITIES = ( 1 << 6 ),
|
||||
TR_FR_BANDWIDTH_PRIORITY = ( 1 << 7 ),
|
||||
TR_FR_SPEEDLIMIT = ( 1 << 8 ),
|
||||
TR_FR_RUN = ( 1 << 9 ),
|
||||
TR_FR_DOWNLOAD_DIR = ( 1 << 10 ),
|
||||
TR_FR_MAX_PEERS = ( 1 << 11 ),
|
||||
TR_FR_ADDED_DATE = ( 1 << 12 ),
|
||||
TR_FR_DONE_DATE = ( 1 << 13 ),
|
||||
TR_FR_ACTIVITY_DATE = ( 1 << 14 ),
|
||||
TR_FR_RATIOLIMIT = ( 1 << 15 )
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -409,6 +409,8 @@ addField( const tr_torrent * tor,
|
|||
tr_bencDictAddStr( d, key, st->announceResponse );
|
||||
else if( !strcmp( key, "announceURL" ) )
|
||||
tr_bencDictAddStr( d, key, st->announceURL );
|
||||
else if( !strcmp( key, "bandwidthPriority" ) )
|
||||
tr_bencDictAddInt( d, key, tr_torrentGetPriority( tor ) );
|
||||
else if( !strcmp( key, "comment" ) )
|
||||
tr_bencDictAddStr( d, key, inf->comment ? inf->comment : "" );
|
||||
else if( !strcmp( key, "corruptEver" ) )
|
||||
|
@ -721,6 +723,9 @@ torrentSet( tr_session * session,
|
|||
tr_bool boolVal;
|
||||
tr_torrent * tor = torrents[i];
|
||||
|
||||
if( tr_bencDictFindInt( args_in, "bandwidthPriority", &tmp ) )
|
||||
if( tr_isPriority( tmp ) )
|
||||
tr_torrentSetPriority( tor, tmp );
|
||||
if( tr_bencDictFindList( args_in, "files-unwanted", &files ) )
|
||||
setFileDLs( tor, FALSE, files );
|
||||
if( tr_bencDictFindList( args_in, "files-wanted", &files ) )
|
||||
|
|
|
@ -1521,7 +1521,7 @@ tr_torrentInitFilePriority( tr_torrent * tor,
|
|||
|
||||
assert( tr_isTorrent( tor ) );
|
||||
assert( fileIndex < tor->info.fileCount );
|
||||
assert( priority == TR_PRI_LOW || priority == TR_PRI_NORMAL || priority == TR_PRI_HIGH );
|
||||
assert( tr_isPriority( priority ) );
|
||||
|
||||
file = &tor->info.files[fileIndex];
|
||||
file->priority = priority;
|
||||
|
@ -1696,6 +1696,27 @@ tr_torrentSetFileDLs( tr_torrent * tor,
|
|||
****
|
||||
***/
|
||||
|
||||
tr_priority_t
|
||||
tr_torrentGetPriority( const tr_torrent * tor )
|
||||
{
|
||||
assert( tr_isTorrent( tor ) );
|
||||
|
||||
return tor->bandwidth->priority;
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentSetPriority( tr_torrent * tor, tr_priority_t priority )
|
||||
{
|
||||
assert( tr_isTorrent( tor ) );
|
||||
assert( tr_isPriority( priority ) );
|
||||
|
||||
tor->bandwidth->priority = priority;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
void
|
||||
tr_torrentSetPeerLimit( tr_torrent * tor,
|
||||
uint16_t maxConnectedPeers )
|
||||
|
|
|
@ -72,6 +72,13 @@ enum
|
|||
|
||||
typedef int8_t tr_priority_t;
|
||||
|
||||
static TR_INLINE tr_bool tr_isPriority( tr_priority_t p )
|
||||
{
|
||||
return ( p == TR_PRI_LOW )
|
||||
|| ( p == TR_PRI_NORMAL )
|
||||
|| ( p == TR_PRI_HIGH );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns Transmission's default configuration file directory.
|
||||
*
|
||||
|
@ -650,6 +657,9 @@ uint16_t tr_sessionGetPeerLimit( const tr_session * );
|
|||
void tr_sessionSetPeerLimitPerTorrent( tr_session *, uint16_t maxGlobalPeers );
|
||||
uint16_t tr_sessionGetPeerLimitPerTorrent( const tr_session * );
|
||||
|
||||
tr_priority_t tr_torrentGetPriority( const tr_torrent * );
|
||||
void tr_torrentSetPriority( tr_torrent *, tr_priority_t );
|
||||
|
||||
|
||||
/**
|
||||
* Load all the torrents in tr_getTorrentDir().
|
||||
|
|
Loading…
Reference in New Issue