Further improvements to smooth shutdown (and fix bug re: shutdown acceleration)
This commit is contained in:
+1
-1
@@ -256,7 +256,7 @@ void serve( int host_fd )
|
|||||||
if ( (pollfds[ 1 ].revents)
|
if ( (pollfds[ 1 ].revents)
|
||||||
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
||||||
/* host problem */
|
/* host problem */
|
||||||
if ( network.attached() && (!network.shutdown_in_progress()) ) {
|
if ( network.attached() ) {
|
||||||
network.start_shutdown();
|
network.start_shutdown();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|||||||
+9
-13
@@ -14,7 +14,7 @@ TransportSender<MyState>::TransportSender( Connection *s_connection, MyState &in
|
|||||||
next_send_time( timestamp() ),
|
next_send_time( timestamp() ),
|
||||||
verbose( false ),
|
verbose( false ),
|
||||||
shutdown_in_progress( false ),
|
shutdown_in_progress( false ),
|
||||||
shutdown_timestamp( -1 ),
|
shutdown_tries( 0 ),
|
||||||
ack_num( 0 ),
|
ack_num( 0 ),
|
||||||
pending_data_ack( false )
|
pending_data_ack( false )
|
||||||
{
|
{
|
||||||
@@ -42,8 +42,6 @@ int TransportSender<MyState>::wait_time( void )
|
|||||||
next_ack_time = timestamp() + ACK_DELAY;
|
next_ack_time = timestamp() + ACK_DELAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t next_wakeup = next_ack_time;
|
|
||||||
|
|
||||||
if ( !(current_state == sent_states.back().state) ) { /* pending data to send */
|
if ( !(current_state == sent_states.back().state) ) { /* pending data to send */
|
||||||
if ( next_send_time > timestamp() + SEND_MINDELAY ) {
|
if ( next_send_time > timestamp() + SEND_MINDELAY ) {
|
||||||
next_send_time = timestamp() + SEND_MINDELAY;
|
next_send_time = timestamp() + SEND_MINDELAY;
|
||||||
@@ -59,6 +57,8 @@ int TransportSender<MyState>::wait_time( void )
|
|||||||
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;
|
||||||
|
|
||||||
if ( next_send_time < next_wakeup ) {
|
if ( next_send_time < next_wakeup ) {
|
||||||
next_wakeup = next_send_time;
|
next_wakeup = next_send_time;
|
||||||
}
|
}
|
||||||
@@ -244,6 +244,10 @@ void TransportSender<MyState>::send_in_fragments( string diff, uint64_t new_num
|
|||||||
for ( auto i = fragments.begin(); i != fragments.end(); i++ ) {
|
for ( auto i = fragments.begin(); i != fragments.end(); i++ ) {
|
||||||
connection->send( i->tostring() );
|
connection->send( i->tostring() );
|
||||||
|
|
||||||
|
if ( new_num == uint64_t(-1) ) {
|
||||||
|
shutdown_tries++;
|
||||||
|
}
|
||||||
|
|
||||||
if ( verbose ) {
|
if ( verbose ) {
|
||||||
fprintf( stderr, "[%d] Sent [%d=>%d] id %d, frag %d ack=%d, throwaway=%d, len=%d, frame rate=%.2f, timeout=%d\n",
|
fprintf( stderr, "[%d] Sent [%d=>%d] id %d, frag %d ack=%d, throwaway=%d, len=%d, frame rate=%.2f, timeout=%d\n",
|
||||||
(int)(timestamp() % 100000), (int)inst.old_num(), (int)inst.new_num(), (int)i->id, (int)i->fragment_num,
|
(int)(timestamp() % 100000), (int)inst.old_num(), (int)inst.new_num(), (int)i->id, (int)i->fragment_num,
|
||||||
@@ -280,17 +284,9 @@ void TransportSender<MyState>::process_acknowledgment_through( uint64_t ack_num
|
|||||||
assert( !sent_states.empty() );
|
assert( !sent_states.empty() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* give up on getting acknowledgement for shutdown after 5 RTTs */
|
/* give up on getting acknowledgement for shutdown */
|
||||||
template <class MyState>
|
template <class MyState>
|
||||||
bool TransportSender<MyState>::shutdown_ack_timed_out( void )
|
bool TransportSender<MyState>::shutdown_ack_timed_out( void )
|
||||||
{
|
{
|
||||||
if ( !shutdown_in_progress ) {
|
return shutdown_tries >= SHUTDOWN_RETRIES;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( timestamp() - shutdown_timestamp > 5 * connection->get_SRTT() ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -24,6 +24,7 @@ namespace Network {
|
|||||||
static const int ACK_INTERVAL = 1000; /* ms between empty acks */
|
static const int ACK_INTERVAL = 1000; /* ms between empty acks */
|
||||||
static const int ACK_DELAY = 10; /* ms before delayed ack */
|
static const int ACK_DELAY = 10; /* ms before delayed ack */
|
||||||
static const int SEND_MINDELAY = 20; /* ms to collect all input */
|
static const int SEND_MINDELAY = 20; /* ms to collect all input */
|
||||||
|
static const int SHUTDOWN_RETRIES = 3; /* number of shutdown packets to send before giving up */
|
||||||
|
|
||||||
/* helper methods for tick() */
|
/* helper methods for tick() */
|
||||||
unsigned int send_interval( void );
|
unsigned int send_interval( void );
|
||||||
@@ -55,7 +56,7 @@ namespace Network {
|
|||||||
|
|
||||||
bool verbose;
|
bool verbose;
|
||||||
bool shutdown_in_progress;
|
bool shutdown_in_progress;
|
||||||
uint64_t shutdown_timestamp;
|
int shutdown_tries;
|
||||||
|
|
||||||
/* information about receiver state */
|
/* information about receiver state */
|
||||||
uint64_t ack_num;
|
uint64_t ack_num;
|
||||||
@@ -81,7 +82,7 @@ namespace Network {
|
|||||||
void set_data_ack( void ) { pending_data_ack = true; }
|
void set_data_ack( void ) { pending_data_ack = true; }
|
||||||
|
|
||||||
/* Starts shutdown sequence */
|
/* Starts shutdown sequence */
|
||||||
void start_shutdown( void ) { shutdown_in_progress = true; shutdown_timestamp = timestamp(); }
|
void start_shutdown( void ) { shutdown_in_progress = true; }
|
||||||
|
|
||||||
/* Misc. getters and setters */
|
/* Misc. getters and setters */
|
||||||
/* Cannot modify current_state while shutdown in progress */
|
/* Cannot modify current_state while shutdown in progress */
|
||||||
|
|||||||
Reference in New Issue
Block a user