(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:
parent
a91c5e44e3
commit
d9369718b3
|
@ -23,6 +23,7 @@ SUBDIRS = \
|
|||
$(CLI_DIR) \
|
||||
$(GTK_DIR) \
|
||||
$(MAC_DIR) \
|
||||
utils \
|
||||
web
|
||||
|
||||
EXTRA_DIST = \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" );
|
||||
|
||||
|
|
243
gtk/details.c
243
gtk/details.c
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++];
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue