(trunk) #2548 "T's request queue can send out too many duplicate requests" -- (1) fix r9465 implementation bug that caused some peers to get starved of requests if they rejected a request or choked, then unchoked us. (2) increase a block request's TTL by 15 seconds to reduce cancel/req cycles between two or more blocks (3) add a debug mode to the GTK+ client's peer tab to watch the pending requests counts both up & down

This commit is contained in:
Charles Kerr 2009-12-16 18:20:01 +00:00
parent a91c5e44e3
commit d9369718b3
10 changed files with 254 additions and 159 deletions

View File

@ -23,6 +23,7 @@ SUBDIRS = \
$(CLI_DIR) \
$(GTK_DIR) \
$(MAC_DIR) \
utils \
web
EXTRA_DIST = \

View File

@ -446,6 +446,7 @@ AC_CONFIG_FILES([Makefile
macosx/Makefile
gtk/Makefile
gtk/icons/Makefile
utils/Makefile
web/Makefile
web/images/Makefile
web/images/buttons/Makefile

View File

@ -177,6 +177,7 @@ tr_prefs_init_defaults( tr_benc * d )
tr_bencDictAddBool( d, PREF_KEY_PLAY_DOWNLOAD_COMPLETE_SOUND, TRUE );
tr_bencDictAddBool( d, PREF_KEY_SHOW_DESKTOP_NOTIFICATION, TRUE );
tr_bencDictAddBool( d, PREF_KEY_SHOW_MORE_TRACKER_INFO, FALSE );
tr_bencDictAddBool( d, PREF_KEY_SHOW_MORE_PEER_INFO, FALSE );
tr_bencDictAddBool( d, PREF_KEY_SHOW_BACKUP_TRACKERS, FALSE );
tr_bencDictAddStr( d, PREF_KEY_STATUSBAR_STATS, "total-ratio" );

View File

@ -86,6 +86,8 @@ struct DetailsImpl
GtkListStore * peer_store;
GtkListStore * webseed_store;
GtkWidget * webseed_view;
GtkWidget * peer_view;
GtkWidget * more_peer_details_check;
GtkListStore * trackers;
GtkTreeModel * trackers_filtered;
@ -1086,6 +1088,10 @@ enum
PEER_COL_UPLOAD_RATE_STRING,
PEER_COL_CLIENT,
PEER_COL_PROGRESS,
PEER_COL_UPLOAD_REQUEST_COUNT_INT,
PEER_COL_UPLOAD_REQUEST_COUNT_STRING,
PEER_COL_DOWNLOAD_REQUEST_COUNT_INT,
PEER_COL_DOWNLOAD_REQUEST_COUNT_STRING,
PEER_COL_ENCRYPTION_STOCK_ID,
PEER_COL_STATUS,
N_PEER_COLS
@ -1103,6 +1109,10 @@ getPeerColumnName( int column )
case PEER_COL_UPLOAD_RATE_DOUBLE: return _( "Up" );
case PEER_COL_CLIENT: return _( "Client" );
case PEER_COL_PROGRESS: return _( "%" );
case PEER_COL_UPLOAD_REQUEST_COUNT_INT:
case PEER_COL_UPLOAD_REQUEST_COUNT_STRING: return _( "Up Reqs" );
case PEER_COL_DOWNLOAD_REQUEST_COUNT_INT:
case PEER_COL_DOWNLOAD_REQUEST_COUNT_STRING: return _( "Dn Reqs" );
case PEER_COL_STATUS: return _( "Status" );
default: return "";
}
@ -1122,6 +1132,10 @@ peer_store_new( void )
G_TYPE_STRING, /* upload speed string */
G_TYPE_STRING, /* client */
G_TYPE_INT, /* progress [0..100] */
G_TYPE_INT, /* upload request count int */
G_TYPE_STRING, /* upload request count string */
G_TYPE_INT, /* download request count int */
G_TYPE_STRING, /* download request count string */
G_TYPE_STRING, /* encryption stock id */
G_TYPE_STRING); /* flagString */
}
@ -1165,6 +1179,8 @@ refreshPeerRow( GtkListStore * store,
{
char up_speed[128];
char down_speed[128];
char up_count[128];
char down_count[128];
if( peer->rateToPeer > 0.01 )
tr_strlspeed( up_speed, peer->rateToPeer, sizeof( up_speed ) );
@ -1176,8 +1192,22 @@ refreshPeerRow( GtkListStore * store,
else
*down_speed = '\0';
if( peer->pendingReqsToPeer > 0 )
g_snprintf( down_count, sizeof( down_count ), "%d", peer->pendingReqsToPeer );
else
*down_count = '\0';
if( peer->pendingReqsToClient > 0 )
g_snprintf( up_count, sizeof( down_count ), "%d", peer->pendingReqsToClient );
else
*up_count = '\0';
gtk_list_store_set( store, iter,
PEER_COL_PROGRESS, (int)( 100.0 * peer->progress ),
PEER_COL_UPLOAD_REQUEST_COUNT_INT, peer->pendingReqsToClient,
PEER_COL_UPLOAD_REQUEST_COUNT_STRING, up_count,
PEER_COL_DOWNLOAD_REQUEST_COUNT_INT, peer->pendingReqsToPeer,
PEER_COL_DOWNLOAD_REQUEST_COUNT_STRING, down_count,
PEER_COL_DOWNLOAD_RATE_DOUBLE, peer->rateToClient,
PEER_COL_DOWNLOAD_RATE_STRING, down_speed,
PEER_COL_UPLOAD_RATE_DOUBLE, peer->rateToPeer,
@ -1429,10 +1459,132 @@ onPeerViewQueryTooltip( GtkWidget * widget,
}
#endif
static void
setPeerViewColumns( GtkTreeView * peer_view )
{
int i;
int n = 0;
const tr_bool more = pref_flag_get( PREF_KEY_SHOW_MORE_PEER_INFO );
int view_columns[32];
GtkTreeViewColumn * c;
GtkCellRenderer * r;
view_columns[n++] = PEER_COL_ENCRYPTION_STOCK_ID;
view_columns[n++] = PEER_COL_UPLOAD_RATE_STRING;
if( more ) view_columns[n++] = PEER_COL_UPLOAD_REQUEST_COUNT_STRING;
view_columns[n++] = PEER_COL_DOWNLOAD_RATE_STRING;
if( more ) view_columns[n++] = PEER_COL_DOWNLOAD_REQUEST_COUNT_STRING;
view_columns[n++] = PEER_COL_PROGRESS;
view_columns[n++] = PEER_COL_STATUS;
view_columns[n++] = PEER_COL_ADDRESS;
view_columns[n++] = PEER_COL_CLIENT;
/* remove any existing columns */
{
GList * l;
GList * columns = gtk_tree_view_get_columns( peer_view );
for( l=columns; l!=NULL; l=l->next )
gtk_tree_view_remove_column( peer_view, l->data );
g_list_free( columns );
}
for( i=0; i<n; ++i )
{
const int col = view_columns[i];
const char * t = getPeerColumnName( col );
int sort_col = col;
switch( col )
{
case PEER_COL_ADDRESS:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
sort_col = PEER_COL_ADDRESS_COLLATED;
break;
case PEER_COL_CLIENT:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
break;
case PEER_COL_PROGRESS:
r = gtk_cell_renderer_progress_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "value", PEER_COL_PROGRESS, NULL );
break;
case PEER_COL_ENCRYPTION_STOCK_ID:
r = gtk_cell_renderer_pixbuf_new( );
g_object_set( r, "xalign", (gfloat)0.0,
"yalign", (gfloat)0.5,
NULL );
c = gtk_tree_view_column_new_with_attributes( t, r, "stock-id", PEER_COL_ENCRYPTION_STOCK_ID, NULL );
gtk_tree_view_column_set_sizing( c, GTK_TREE_VIEW_COLUMN_FIXED );
gtk_tree_view_column_set_fixed_width( c, 20 );
break;
case PEER_COL_UPLOAD_REQUEST_COUNT_STRING:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
sort_col = PEER_COL_UPLOAD_REQUEST_COUNT_INT;
break;
case PEER_COL_DOWNLOAD_REQUEST_COUNT_STRING:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
sort_col = PEER_COL_DOWNLOAD_REQUEST_COUNT_INT;
break;
case PEER_COL_DOWNLOAD_RATE_STRING:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
sort_col = PEER_COL_DOWNLOAD_RATE_DOUBLE;
break;
case PEER_COL_UPLOAD_RATE_STRING:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
sort_col = PEER_COL_UPLOAD_RATE_DOUBLE;
break;
case PEER_COL_STATUS:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
break;
default:
abort( );
}
gtk_tree_view_column_set_resizable( c, FALSE );
gtk_tree_view_column_set_sort_column_id( c, sort_col );
gtk_tree_view_append_column( GTK_TREE_VIEW( peer_view ), c );
}
/* the 'expander' column has a 10-pixel margin on the left
that doesn't look quite correct in any of these columns...
so create a non-visible column and assign it as the
'expander column. */
{
GtkTreeViewColumn *c = gtk_tree_view_column_new( );
gtk_tree_view_column_set_visible( c, FALSE );
gtk_tree_view_append_column( GTK_TREE_VIEW( peer_view ), c );
gtk_tree_view_set_expander_column( GTK_TREE_VIEW( peer_view ), c );
}
}
static void
onMorePeerInfoToggled( GtkToggleButton * button, struct DetailsImpl * di )
{
const char * key = PREF_KEY_SHOW_MORE_PEER_INFO;
const gboolean value = gtk_toggle_button_get_active( button );
tr_core_set_pref_bool( di->core, key, value );
setPeerViewColumns( GTK_TREE_VIEW( di->peer_view ) );
}
static GtkWidget*
peer_page_new( struct DetailsImpl * di )
{
guint i;
gboolean b;
const char * str;
GtkListStore *store;
GtkWidget *v, *w, *ret, *sw, *vbox;
@ -1440,14 +1592,6 @@ peer_page_new( struct DetailsImpl * di )
GtkTreeModel * m;
GtkTreeViewColumn * c;
GtkCellRenderer * r;
int view_columns[] = { PEER_COL_ENCRYPTION_STOCK_ID,
PEER_COL_UPLOAD_RATE_STRING,
PEER_COL_DOWNLOAD_RATE_STRING,
PEER_COL_PROGRESS,
PEER_COL_STATUS,
PEER_COL_ADDRESS,
PEER_COL_CLIENT };
/* webseeds */
@ -1501,6 +1645,7 @@ peer_page_new( struct DetailsImpl * di )
"rules-hint", TRUE,
NULL ) );
#endif
di->peer_view = v;
#if GTK_CHECK_VERSION( 2,12,0 )
g_signal_connect( v, "query-tooltip",
@ -1510,76 +1655,7 @@ peer_page_new( struct DetailsImpl * di )
g_signal_connect( v, "button-release-event",
G_CALLBACK( on_tree_view_button_released ), NULL );
for( i=0; i<G_N_ELEMENTS( view_columns ); ++i )
{
const int col = view_columns[i];
const char * t = getPeerColumnName( col );
int sort_col = col;
switch( col )
{
case PEER_COL_ADDRESS:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
sort_col = PEER_COL_ADDRESS_COLLATED;
break;
case PEER_COL_CLIENT:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
break;
case PEER_COL_PROGRESS:
r = gtk_cell_renderer_progress_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "value", PEER_COL_PROGRESS, NULL );
break;
case PEER_COL_ENCRYPTION_STOCK_ID:
r = gtk_cell_renderer_pixbuf_new( );
g_object_set( r, "xalign", (gfloat)0.0,
"yalign", (gfloat)0.5,
NULL );
c = gtk_tree_view_column_new_with_attributes( t, r, "stock-id", PEER_COL_ENCRYPTION_STOCK_ID, NULL );
gtk_tree_view_column_set_sizing( c, GTK_TREE_VIEW_COLUMN_FIXED );
gtk_tree_view_column_set_fixed_width( c, 20 );
break;
case PEER_COL_DOWNLOAD_RATE_STRING:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
sort_col = PEER_COL_DOWNLOAD_RATE_DOUBLE;
break;
case PEER_COL_UPLOAD_RATE_STRING:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
sort_col = PEER_COL_UPLOAD_RATE_DOUBLE;
break;
case PEER_COL_STATUS:
r = gtk_cell_renderer_text_new( );
c = gtk_tree_view_column_new_with_attributes( t, r, "text", col, NULL );
break;
default:
abort( );
}
gtk_tree_view_column_set_resizable( c, FALSE );
gtk_tree_view_column_set_sort_column_id( c, sort_col );
gtk_tree_view_append_column( GTK_TREE_VIEW( v ), c );
}
/* the 'expander' column has a 10-pixel margin on the left
that doesn't look quite correct in any of these columns...
so create a non-visible column and assign it as the
'expander column. */
{
GtkTreeViewColumn *c = gtk_tree_view_column_new( );
gtk_tree_view_column_set_visible( c, FALSE );
gtk_tree_view_append_column( GTK_TREE_VIEW( v ), c );
gtk_tree_view_set_expander_column( GTK_TREE_VIEW( v ), c );
}
setPeerViewColumns( GTK_TREE_VIEW( v ) );
w = sw = gtk_scrolled_window_new( NULL, NULL );
gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( w ),
@ -1589,7 +1665,6 @@ peer_page_new( struct DetailsImpl * di )
GTK_SHADOW_IN );
gtk_container_add( GTK_CONTAINER( w ), v );
vbox = gtk_vbox_new( FALSE, GUI_PAD );
gtk_container_set_border_width( GTK_CONTAINER( vbox ), GUI_PAD_BIG );
@ -1598,6 +1673,14 @@ peer_page_new( struct DetailsImpl * di )
gtk_paned_pack2( GTK_PANED( v ), sw, TRUE, TRUE );
gtk_box_pack_start( GTK_BOX( vbox ), v, TRUE, TRUE, 0 );
w = gtk_check_button_new_with_mnemonic( _( "Show _more details" ) );
di->more_peer_details_check = w;
b = pref_flag_get( PREF_KEY_SHOW_MORE_PEER_INFO );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), b );
g_signal_connect( w, "toggled", G_CALLBACK( onMorePeerInfoToggled ), di );
gtk_box_pack_start( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
/* ip-to-GtkTreeRowReference */
di->peer_hash = g_hash_table_new_full( g_str_hash,
g_str_equal,

View File

@ -31,6 +31,7 @@ GtkWidget * tr_prefs_dialog_new( GObject * core,
#define PREF_KEY_SHOW_DESKTOP_NOTIFICATION "show-desktop-notification"
#define PREF_KEY_PLAY_DOWNLOAD_COMPLETE_SOUND "play-download-complete-sound"
#define PREF_KEY_SHOW_MORE_TRACKER_INFO "show-tracker-scrapes"
#define PREF_KEY_SHOW_MORE_PEER_INFO "show-extra-peer-details"
#define PREF_KEY_SHOW_BACKUP_TRACKERS "show-backup-trackers"
#define PREF_KEY_START "start-added-torrents"
#define PREF_KEY_TRASH_ORIGINAL "trash-original-torrent-files"

View File

@ -33,11 +33,7 @@ enum
/** when we're making requests from another peer,
batch them together to send enough requests to
meet our bandwidth goals for the next N seconds */
REQUEST_BUF_SECS = 10,
/** how long we'll let requests we've made stay pending
before we cancel them */
REQUEST_TTL_SECS = 30
REQUEST_BUF_SECS = 10
};
typedef enum

View File

@ -85,7 +85,10 @@ enum
MYFLAG_UNREACHABLE = 2,
/* the minimum we'll wait before attempting to reconnect to a peer */
MINIMUM_RECONNECT_INTERVAL_SECS = 5
MINIMUM_RECONNECT_INTERVAL_SECS = 5,
/** how long we'll let requests we've made linger before we cancel them */
REQUEST_TTL_SECS = 45
};
@ -618,7 +621,7 @@ requestListSort( Torrent * t, int mode )
}
static void
requestListAdd( Torrent * t, const time_t now, tr_block_index_t block, tr_peer * peer )
requestListAdd( Torrent * t, tr_block_index_t block, tr_peer * peer )
{
struct block_request key;
@ -634,7 +637,7 @@ requestListAdd( Torrent * t, const time_t now, tr_block_index_t block, tr_peer *
/* populate the record we're inserting */
key.block = block;
key.peer = peer;
key.sentAt = now;
key.sentAt = tr_time( );
/* insert the request to our array... */
switch( t->requestsSort )
@ -657,9 +660,16 @@ requestListAdd( Torrent * t, const time_t now, tr_block_index_t block, tr_peer *
break;
}
}
/*fprintf( stderr, "added request of block %lu from peer %p... "
if( peer != NULL )
{
++peer->pendingReqsToPeer;
assert( peer->pendingReqsToPeer >= 0 );
}
/*fprintf( stderr, "added request of block %lu from peer %s... "
"there are now %d block\n",
(unsigned long)block, peer, t->requestCount );*/
(unsigned long)block, tr_atomAddrStr( peer->atom ), t->requestCount );*/
}
static struct block_request *
@ -712,12 +722,19 @@ requestListRemove( Torrent * t, tr_block_index_t block, const tr_peer * peer )
{
const int pos = b - t->requests;
assert( pos < t->requestCount );
if( b->peer != NULL )
{
--b->peer->pendingReqsToPeer;
assert( b->peer->pendingReqsToPeer >= 0 );
}
memmove( t->requests + pos,
t->requests + pos + 1,
sizeof( struct block_request ) * ( --t->requestCount - pos ) );
/*fprintf( stderr, "removing request of block %lu from peer %p... "
/*fprintf( stderr, "removing request of block %lu from peer %s... "
"there are now %d block requests left\n",
(unsigned long)block, peer, t->requestCount );*/
(unsigned long)block, tr_atomAddrStr( peer->atom ), t->requestCount );*/
}
}
@ -951,7 +968,6 @@ tr_peerMgrGetNextRequests( tr_torrent * tor,
Torrent * t;
struct weighted_piece * pieces;
const tr_bitset * have = &peer->have;
const time_t now = tr_time( );
/* sanity clause */
assert( tr_isTorrent( tor ) );
@ -1000,7 +1016,7 @@ tr_peerMgrGetNextRequests( tr_torrent * tor,
setme[got++] = b;
/* update our own tables */
requestListAdd( t, now, b, peer );
requestListAdd( t, b, peer );
++p->requestCount;
}
}
@ -2194,20 +2210,22 @@ tr_peerMgrPeerStats( const tr_torrent * tor,
tr_ntop( &atom->addr, stat->addr, sizeof( stat->addr ) );
tr_strlcpy( stat->client, ( peer->client ? peer->client : "" ),
sizeof( stat->client ) );
stat->port = ntohs( peer->atom->port );
stat->from = atom->from;
stat->progress = peer->progress;
stat->isEncrypted = tr_peerIoIsEncrypted( peer->io ) ? 1 : 0;
stat->rateToPeer = tr_peerGetPieceSpeed( peer, now, TR_CLIENT_TO_PEER );
stat->rateToClient = tr_peerGetPieceSpeed( peer, now, TR_PEER_TO_CLIENT );
stat->peerIsChoked = peer->peerIsChoked;
stat->peerIsInterested = peer->peerIsInterested;
stat->clientIsChoked = peer->clientIsChoked;
stat->clientIsInterested = peer->clientIsInterested;
stat->isIncoming = tr_peerIoIsIncoming( peer->io );
stat->isDownloadingFrom = clientIsDownloadingFrom( tor, peer );
stat->isUploadingTo = clientIsUploadingTo( peer );
stat->isSeed = ( atom->uploadOnly == UPLOAD_ONLY_YES ) || ( peer->progress >= 1.0 );
stat->port = ntohs( peer->atom->port );
stat->from = atom->from;
stat->progress = peer->progress;
stat->isEncrypted = tr_peerIoIsEncrypted( peer->io ) ? 1 : 0;
stat->rateToPeer = tr_peerGetPieceSpeed( peer, now, TR_CLIENT_TO_PEER );
stat->rateToClient = tr_peerGetPieceSpeed( peer, now, TR_PEER_TO_CLIENT );
stat->peerIsChoked = peer->peerIsChoked;
stat->peerIsInterested = peer->peerIsInterested;
stat->clientIsChoked = peer->clientIsChoked;
stat->clientIsInterested = peer->clientIsInterested;
stat->isIncoming = tr_peerIoIsIncoming( peer->io );
stat->isDownloadingFrom = clientIsDownloadingFrom( tor, peer );
stat->isUploadingTo = clientIsUploadingTo( peer );
stat->isSeed = ( atom->uploadOnly == UPLOAD_ONLY_YES ) || ( peer->progress >= 1.0 );
stat->pendingReqsToPeer = peer->pendingReqsToPeer;
stat->pendingReqsToClient = peer->pendingReqsToClient;
pch = stat->flagStr;
if( t->optimistic == peer ) *pch++ = 'O';
@ -3085,8 +3103,6 @@ compareAtomPtrsByAddress( const void * va, const void *vb )
return tr_compareAddresses( &a->addr, &b->addr );
}
static time_t tr_now = 0;
/* best come first, worst go last */
static int
compareAtomPtrsByShelfDate( const void * va, const void *vb )
@ -3096,6 +3112,7 @@ compareAtomPtrsByShelfDate( const void * va, const void *vb )
const struct peer_atom * a = * (const struct peer_atom**) va;
const struct peer_atom * b = * (const struct peer_atom**) vb;
const int data_time_cutoff_secs = 60 * 60;
const time_t tr_now = tr_time( );
assert( tr_isAtom( a ) );
assert( tr_isAtom( b ) );
@ -3159,7 +3176,6 @@ atomPulse( int foo UNUSED, short bar UNUSED, void * vmgr )
/* if there's room, keep the best of what's left */
i = 0;
if( keepCount < maxAtomCount ) {
tr_now = tr_time( );
qsort( test, testCount, sizeof( struct peer_atom * ), compareAtomPtrsByShelfDate );
while( i<testCount && keepCount<maxAtomCount )
keep[keepCount++] = test[i++];

View File

@ -90,6 +90,13 @@ typedef struct tr_peer
uint8_t encryption_preference;
tr_port dht_port;
/* how many requests the peer has made that we haven't responded to yet */
int pendingReqsToClient;
/* how many requests we've made and are currently awaiting a response for */
int pendingReqsToPeer;
struct tr_peerIo * io;
struct peer_atom * atom;

View File

@ -179,7 +179,6 @@ struct tr_peermsgs
/*tr_bool haveFastSet;*/
int activeRequestCount;
int desiredRequestCount;
int prefetchCount;
@ -209,7 +208,6 @@ struct tr_peermsgs
struct evbuffer * outMessages; /* all the non-piece messages */
struct peer_request peerAskedFor[REQQ];
int peerAskedForCount;
int peerAskedForMetadata[METADATA_REQQ];
int peerAskedForMetadataCount;
@ -756,13 +754,13 @@ popNextMetadataRequest( tr_peermsgs * msgs, int * piece )
static tr_bool
popNextRequest( tr_peermsgs * msgs, struct peer_request * setme )
{
if( msgs->peerAskedForCount == 0 )
if( msgs->peer->pendingReqsToClient == 0 )
return FALSE;
*setme = msgs->peerAskedFor[0];
tr_removeElementFromArray( msgs->peerAskedFor, 0, sizeof( struct peer_request ),
msgs->peerAskedForCount-- );
msgs->peer->pendingReqsToClient-- );
return TRUE;
}
@ -836,7 +834,6 @@ requestIsValid( const tr_peermsgs * msgs, const struct peer_request * req )
return reqIsValid( msgs, req->index, req->offset, req->length );
}
void
tr_peerMsgsCancel( tr_peermsgs * msgs, tr_block_index_t block )
{
@ -1257,13 +1254,13 @@ peerMadeRequest( tr_peermsgs * msgs,
dbgmsg( msgs, "rejecting request for a piece we don't have." );
else if( peerIsChoked )
dbgmsg( msgs, "rejecting request from choked peer" );
else if( msgs->peerAskedForCount + 1 >= REQQ )
else if( msgs->peer->pendingReqsToClient + 1 >= REQQ )
dbgmsg( msgs, "rejecting request ... reqq is full" );
else
allow = TRUE;
if( allow )
msgs->peerAskedFor[msgs->peerAskedForCount++] = *req;
msgs->peerAskedFor[msgs->peer->pendingReqsToClient++] = *req;
else if( fext )
protocolSendReject( msgs, req );
}
@ -1374,13 +1371,6 @@ readBtPiece( tr_peermsgs * msgs,
static void updateDesiredRequestCount( tr_peermsgs * msgs, uint64_t now );
static void
decrementActiveRequestCount( tr_peermsgs * msgs )
{
if( msgs->activeRequestCount > 0 )
msgs->activeRequestCount--;
}
static int
readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
{
@ -1471,15 +1461,15 @@ readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.length );
dbgmsg( msgs, "got a Cancel %u:%u->%u", r.index, r.offset, r.length );
for( i=0; i<msgs->peerAskedForCount; ++i ) {
for( i=0; i<msgs->peer->pendingReqsToClient; ++i ) {
const struct peer_request * req = msgs->peerAskedFor + i;
if( ( req->index == r.index ) && ( req->offset == r.offset ) && ( req->length == r.length ) )
break;
}
if( i < msgs->peerAskedForCount )
if( i < msgs->peer->pendingReqsToClient )
tr_removeElementFromArray( msgs->peerAskedFor, i, sizeof( struct peer_request ),
msgs->peerAskedForCount-- );
msgs->peer->pendingReqsToClient-- );
break;
}
@ -1547,10 +1537,9 @@ readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.index );
tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.offset );
tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.length );
if( fext ) {
decrementActiveRequestCount( msgs );
if( fext )
fireGotRej( msgs, &r );
} else {
else {
fireError( msgs, EMSGSIZE );
return READ_ERR;
}
@ -1632,7 +1621,6 @@ clientGotBlock( tr_peermsgs * msgs,
return err;
addPeerToBlamefield( msgs, req->index );
decrementActiveRequestCount( msgs );
fireGotBlock( msgs, req );
return 0;
}
@ -1714,7 +1702,7 @@ updateDesiredRequestCount( tr_peermsgs * msgs, uint64_t now )
int irate;
int estimatedBlocksInPeriod;
double rate;
const int floor = 4;
const int floor = 2;
const int seconds = REQUEST_BUF_SECS;
/* Get the rate limit we should use.
@ -1778,14 +1766,12 @@ updateMetadataRequests( tr_peermsgs * msgs, time_t now )
static void
updateBlockRequests( tr_peermsgs * msgs )
{
const int MIN_BATCH_SIZE = 4;
const int numwant = msgs->desiredRequestCount - msgs->activeRequestCount;
/* make sure we have enough block requests queued up */
if( numwant >= MIN_BATCH_SIZE )
if( ( msgs->desiredRequestCount > 0 ) &&
( msgs->peer->pendingReqsToPeer <= ( msgs->desiredRequestCount * 0.66 ) ) )
{
int i;
int n;
const int numwant = msgs->desiredRequestCount - msgs->peer->pendingReqsToPeer;
tr_block_index_t * blocks = tr_new( tr_block_index_t, numwant );
tr_peerMgrGetNextRequests( msgs->torrent, msgs->peer, numwant, blocks, &n );
@ -1797,8 +1783,6 @@ updateBlockRequests( tr_peermsgs * msgs )
protocolSendRequest( msgs, &req );
}
msgs->activeRequestCount += n;
tr_free( blocks );
}
}
@ -1809,7 +1793,7 @@ prefetchPieces( tr_peermsgs *msgs )
int i;
/* Maintain 12 prefetched blocks per unchoked peer */
for( i=msgs->prefetchCount; i<msgs->peerAskedForCount && i<12; ++i )
for( i=msgs->prefetchCount; i<msgs->peer->pendingReqsToClient && i<12; ++i )
{
const struct peer_request * req = msgs->peerAskedFor + i;
tr_ioPrefetch( msgs->torrent, req->index, req->offset, req->length );
@ -2368,7 +2352,6 @@ tr_peerMsgsNew( struct tr_torrent * torrent,
m->outMessagesBatchedAt = 0;
m->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;
m->incoming.block = evbuffer_new( );
m->peerAskedForCount = 0;
evtimer_set( &m->pexTimer, pexPulse, m );
tr_timerAdd( &m->pexTimer, PEX_INTERVAL_SECS, 0 );
peer->msgs = m;

View File

@ -1316,27 +1316,33 @@ tr_bool tr_torrentCanManualUpdate( const tr_torrent * torrent );
typedef struct tr_peer_stat
{
tr_bool isEncrypted;
tr_bool isDownloadingFrom;
tr_bool isUploadingTo;
tr_bool isSeed;
tr_bool isEncrypted;
tr_bool isDownloadingFrom;
tr_bool isUploadingTo;
tr_bool isSeed;
tr_bool peerIsChoked;
tr_bool peerIsInterested;
tr_bool clientIsChoked;
tr_bool clientIsInterested;
tr_bool isIncoming;
tr_bool peerIsChoked;
tr_bool peerIsInterested;
tr_bool clientIsChoked;
tr_bool clientIsInterested;
tr_bool isIncoming;
uint8_t from;
tr_port port;
uint8_t from;
tr_port port;
char addr[TR_INET6_ADDRSTRLEN];
char client[80];
char flagStr[32];
char addr[TR_INET6_ADDRSTRLEN];
char client[80];
char flagStr[32];
float progress;
float rateToPeer;
float rateToClient;
float progress;
float rateToPeer;
float rateToClient;
/* how many requests the peer has made that we haven't responded to yet */
int pendingReqsToClient;
/* how many requests we've made and are currently awaiting a response for */
int pendingReqsToPeer;
}
tr_peer_stat;