From 5aff42b0aadff5ff5ba3a9c3ab2264eae4982d57 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Fri, 30 Sep 2011 13:51:36 -0400 Subject: [PATCH] Further improvements to smooth shutdown (and fix bug re: shutdown acceleration) --- stm-server.cpp | 2 +- transportsender.cpp | 22 +++++++++------------- transportsender.hpp | 5 +++-- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/stm-server.cpp b/stm-server.cpp index 6053857..81f3c27 100644 --- a/stm-server.cpp +++ b/stm-server.cpp @@ -256,7 +256,7 @@ void serve( int host_fd ) if ( (pollfds[ 1 ].revents) & (POLLERR | POLLHUP | POLLNVAL) ) { /* host problem */ - if ( network.attached() && (!network.shutdown_in_progress()) ) { + if ( network.attached() ) { network.start_shutdown(); } else { break; diff --git a/transportsender.cpp b/transportsender.cpp index cc19f5a..1d52e5d 100644 --- a/transportsender.cpp +++ b/transportsender.cpp @@ -14,7 +14,7 @@ TransportSender::TransportSender( Connection *s_connection, MyState &in next_send_time( timestamp() ), verbose( false ), shutdown_in_progress( false ), - shutdown_timestamp( -1 ), + shutdown_tries( 0 ), ack_num( 0 ), pending_data_ack( false ) { @@ -42,8 +42,6 @@ int TransportSender::wait_time( void ) 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 ( next_send_time > timestamp() + SEND_MINDELAY ) { next_send_time = timestamp() + SEND_MINDELAY; @@ -59,6 +57,8 @@ int TransportSender::wait_time( void ) next_ack_time = sent_states.back().timestamp + send_interval(); } + uint64_t next_wakeup = next_ack_time; + if ( next_send_time < next_wakeup ) { next_wakeup = next_send_time; } @@ -244,6 +244,10 @@ void TransportSender::send_in_fragments( string diff, uint64_t new_num for ( auto i = fragments.begin(); i != fragments.end(); i++ ) { connection->send( i->tostring() ); + if ( new_num == uint64_t(-1) ) { + shutdown_tries++; + } + if ( verbose ) { 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, @@ -280,17 +284,9 @@ void TransportSender::process_acknowledgment_through( uint64_t ack_num assert( !sent_states.empty() ); } -/* give up on getting acknowledgement for shutdown after 5 RTTs */ +/* give up on getting acknowledgement for shutdown */ template bool TransportSender::shutdown_ack_timed_out( void ) { - if ( !shutdown_in_progress ) { - return false; - } - - if ( timestamp() - shutdown_timestamp > 5 * connection->get_SRTT() ) { - return true; - } - - return false; + return shutdown_tries >= SHUTDOWN_RETRIES; } diff --git a/transportsender.hpp b/transportsender.hpp index 940bd9d..6850a55 100644 --- a/transportsender.hpp +++ b/transportsender.hpp @@ -24,6 +24,7 @@ namespace Network { static const int ACK_INTERVAL = 1000; /* ms between empty acks */ static const int ACK_DELAY = 10; /* ms before delayed ack */ 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() */ unsigned int send_interval( void ); @@ -55,7 +56,7 @@ namespace Network { bool verbose; bool shutdown_in_progress; - uint64_t shutdown_timestamp; + int shutdown_tries; /* information about receiver state */ uint64_t ack_num; @@ -81,7 +82,7 @@ namespace Network { void set_data_ack( void ) { pending_data_ack = true; } /* 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 */ /* Cannot modify current_state while shutdown in progress */