Make retry more aggressive even absent new data (fixes #23 github issue)

This commit is contained in:
Keith Winstein
2012-02-25 12:12:16 -05:00
parent 58b584a2b3
commit a2b293c027
4 changed files with 52 additions and 27 deletions
+2 -2
View File
@@ -301,8 +301,8 @@ int OverlayManager::wait_time( void )
next_expiry = 1000; next_expiry = 1000;
} }
if ( predictions.active() && ( next_expiry > 10 ) ) { if ( predictions.active() && ( next_expiry > 20 ) ) {
next_expiry = 10; next_expiry = 20;
} }
return next_expiry; return next_expiry;
+1
View File
@@ -128,6 +128,7 @@ void Transport<MyState, RemoteState>::recv( void )
received_states.push_back( new_state ); received_states.push_back( new_state );
sender.set_ack_num( received_states.back().num ); sender.set_ack_num( received_states.back().num );
sender.remote_heard( new_state.timestamp );
if ( !inst.diff().empty() ) { if ( !inst.diff().empty() ) {
sender.set_data_ack(); sender.set_data_ack();
} }
+41 -25
View File
@@ -45,7 +45,8 @@ TransportSender<MyState>::TransportSender( Connection *s_connection, MyState &in
pending_data_ack( false ), pending_data_ack( false ),
ack_timestamp( 0 ), ack_timestamp( 0 ),
ack_history(), ack_history(),
SEND_MINDELAY( 15 ) SEND_MINDELAY( 15 ),
last_heard( 0 )
{ {
} }
@@ -63,41 +64,57 @@ unsigned int TransportSender<MyState>::send_interval( void ) const
return SEND_INTERVAL; return SEND_INTERVAL;
} }
/* How many ms can the caller wait before we will have an event (empty ack or next frame)? */ /* Housekeeping routine to calculate next send and ack times */
template <class MyState> template <class MyState>
int TransportSender<MyState>::wait_time( void ) void TransportSender<MyState>::calculate_timers( void )
{ {
if ( pending_data_ack && (next_ack_time > timestamp() + ACK_DELAY) ) { uint64_t now = timestamp();
next_ack_time = timestamp() + ACK_DELAY;
/* Update assumed receiver state */
update_assumed_receiver_state();
/* Cut out common prefix of all states */
rationalize_states();
if ( pending_data_ack && (next_ack_time > now + ACK_DELAY) ) {
next_ack_time = now + ACK_DELAY;
} }
if ( !(current_state == sent_states.back().state) ) { /* pending data to send */ if ( ( !(current_state == assumed_receiver_state->state)
if ( next_send_time > timestamp() + SEND_MINDELAY ) { && (last_heard + ACTIVE_RETRY_TIMEOUT > now) )
next_send_time = timestamp() + SEND_MINDELAY; || !(current_state == sent_states.back().state) ) { /* pending data to send */
if ( next_send_time > now + SEND_MINDELAY ) {
next_send_time = now + SEND_MINDELAY;
} }
if ( next_send_time < sent_states.back().timestamp + send_interval() ) { if ( next_send_time < sent_states.back().timestamp + send_interval() ) {
next_send_time = sent_states.back().timestamp + send_interval(); next_send_time = sent_states.back().timestamp + send_interval();
} }
} else {
next_send_time = uint64_t(-1);
} }
/* speed up shutdown sequence */ /* speed up shutdown sequence */
if ( shutdown_in_progress || (ack_num == uint64_t(-1)) ) { if ( shutdown_in_progress || (ack_num == uint64_t(-1)) ) {
next_ack_time = sent_states.back().timestamp + send_interval(); next_ack_time = sent_states.back().timestamp + send_interval();
} }
}
uint64_t next_wakeup = next_ack_time; /* How many ms to wait until next event */
template <class MyState>
int TransportSender<MyState>::wait_time( void )
{
calculate_timers();
if ( next_send_time < next_wakeup ) { uint64_t next_wakeup = min( next_ack_time, next_send_time );
next_wakeup = next_send_time; uint64_t now = timestamp();
}
if ( !connection->get_attached() ) { if ( !connection->get_attached() ) {
return -1; return -1;
} }
if ( next_wakeup > timestamp() ) { if ( next_wakeup > now ) {
return next_wakeup - timestamp(); return next_wakeup - now;
} else { } else {
return 0; return 0;
} }
@@ -107,35 +124,33 @@ int TransportSender<MyState>::wait_time( void )
template <class MyState> template <class MyState>
void TransportSender<MyState>::tick( void ) void TransportSender<MyState>::tick( void )
{ {
wait_time(); calculate_timers(); /* updates assumed receiver state and rationalizes */
if ( !connection->get_attached() ) { if ( !connection->get_attached() ) {
return; return;
} }
if ( (timestamp() < next_ack_time) uint64_t now = timestamp();
&& (timestamp() < next_send_time) ) {
if ( (now < next_ack_time)
&& (now < next_send_time) ) {
return; return;
} }
/* Determine if a new diff or empty ack needs to be sent */ /* Determine if a new diff or empty ack needs to be sent */
/* Update assumed receiver state */
update_assumed_receiver_state();
/* Cut out common prefix of all states */
rationalize_states();
string diff = current_state.diff_from( assumed_receiver_state->state ); string diff = current_state.diff_from( assumed_receiver_state->state );
if ( diff.empty() && (timestamp() >= next_ack_time) ) { if ( diff.empty() && (now >= next_ack_time) ) {
send_empty_ack(); send_empty_ack();
return; return;
} }
if ( !diff.empty() && ( (timestamp() >= next_send_time) if ( !diff.empty() && ( (now >= next_send_time)
|| (timestamp() >= next_ack_time) ) ) { || (now >= next_ack_time) ) ) {
/* Send diffs or ack */ /* Send diffs or ack */
send_to_receiver( diff ); send_to_receiver( diff );
return;
} }
} }
@@ -156,6 +171,7 @@ void TransportSender<MyState>::send_empty_ack( void )
send_in_fragments( "", new_num ); send_in_fragments( "", new_num );
next_ack_time = timestamp() + ACK_INTERVAL; next_ack_time = timestamp() + ACK_INTERVAL;
next_send_time = uint64_t(-1);
} }
template <class MyState> template <class MyState>
+8
View File
@@ -44,6 +44,7 @@ namespace Network {
static const int ACK_DELAY = 100; /* ms before delayed ack */ static const int ACK_DELAY = 100; /* ms before delayed ack */
static const int SHUTDOWN_RETRIES = 3; /* number of shutdown packets to send before giving up */ static const int SHUTDOWN_RETRIES = 3; /* number of shutdown packets to send before giving up */
static const int ECHO_TIMEOUT = 50; /* for late ack */ static const int ECHO_TIMEOUT = 50; /* for late ack */
static const int ACTIVE_RETRY_TIMEOUT = 10000; /* attempt to resend at frame rate */
/* helper methods for tick() */ /* helper methods for tick() */
void update_assumed_receiver_state( void ); void update_assumed_receiver_state( void );
@@ -72,6 +73,8 @@ namespace Network {
uint64_t next_ack_time; uint64_t next_ack_time;
uint64_t next_send_time; uint64_t next_send_time;
void calculate_timers( void );
bool verbose; bool verbose;
bool shutdown_in_progress; bool shutdown_in_progress;
int shutdown_tries; int shutdown_tries;
@@ -86,6 +89,8 @@ namespace Network {
unsigned int SEND_MINDELAY; /* ms to collect all input */ unsigned int SEND_MINDELAY; /* ms to collect all input */
uint64_t last_heard; /* last time received new state */
public: public:
/* constructor */ /* constructor */
TransportSender( Connection *s_connection, MyState &initial_state ); TransportSender( Connection *s_connection, MyState &initial_state );
@@ -105,6 +110,9 @@ namespace Network {
/* Accelerate reply ack */ /* Accelerate reply ack */
void set_data_ack( void ) { pending_data_ack = true; } void set_data_ack( void ) { pending_data_ack = true; }
/* Received something */
void remote_heard( uint64_t ts ) { last_heard = ts; }
/* Starts shutdown sequence */ /* Starts shutdown sequence */
void start_shutdown( void ) { shutdown_in_progress = true; } void start_shutdown( void ) { shutdown_in_progress = true; }