diff --git a/src/mirror.c b/src/mirror.c index 728a883..bea55db 100644 --- a/src/mirror.c +++ b/src/mirror.c @@ -336,6 +336,19 @@ int mirror_should_quit( struct mirror * mirror ) } } +/* Bandwidth limiting - we hang around if bps is too high, unless we need to + * empty out the bitset stream a bit */ +int mirror_should_wait( struct mirror_ctrl *ctrl ) +{ + int bps_over = server_mirror_bps( ctrl->serve ) > + ctrl->serve->mirror->max_bytes_per_second; + + int stream_full = bitset_stream_size( ctrl->serve->allocation_map ) > + ( BITSET_STREAM_SIZE / 2 ); + + return bps_over && !stream_full; +} + /* * If there's an event in the bitset stream of the serve allocation map, we * use it to construct the next transfer request, covering precisely the area @@ -414,24 +427,6 @@ int mirror_setup_next_xfer( struct mirror_ctrl *ctrl ) return 1; } -uint64_t mirror_current_bps( struct mirror * mirror ) -{ - uint64_t duration_ms = monotonic_time_ms() - mirror->migration_started; - return mirror->all_dirty / ( ( duration_ms / 1000 ) + 1 ); -} - -int mirror_exceeds_max_bps( struct mirror * mirror ) -{ - uint64_t mig_speed = mirror_current_bps( mirror ); - debug( "current_bps: %"PRIu64"; max_bps: %"PRIu64, mig_speed, mirror->max_bytes_per_second ); - - if ( mig_speed > mirror->max_bytes_per_second ) { - return 1; - } - - return 0; -} - // ONLY CALL THIS AFTER CLOSING CLIENTS void mirror_complete( struct server *serve ) { @@ -626,7 +621,7 @@ static void mirror_read_cb( struct ev_loop *loop, ev_io *w, int revents ) /* FIXME: Should we ignore the bwlimit after server_close_clients has been called? */ - if ( mirror_exceeds_max_bps( m ) && bitset_stream_size( ctrl->serve->allocation_map ) < ( BITSET_STREAM_SIZE / 2 ) ) { + if ( mirror_should_wait( ctrl ) ) { /* We're over the bandwidth limit, so don't move onto the next transfer * yet. Our limit_watcher will move us on once we're OK. timeout_watcher * was disabled further up, so don't need to stop it here too */ @@ -681,7 +676,7 @@ void mirror_limit_cb( struct ev_loop *loop, ev_timer *w, int revents ) return; } - if ( mirror_exceeds_max_bps( ctrl->mirror ) && bitset_stream_size( ctrl->serve->allocation_map ) < ( BITSET_STREAM_SIZE / 2 ) ) { + if ( mirror_should_wait( ctrl ) ) { debug( "max_bps exceeded, waiting", ctrl->mirror->max_bytes_per_second ); ev_timer_again( loop, w ); } else { diff --git a/src/mirror.h b/src/mirror.h index 21682a6..91c8be1 100644 --- a/src/mirror.h +++ b/src/mirror.h @@ -134,7 +134,5 @@ struct mirror_super * mirror_super_create( ); void * mirror_super_runner( void * serve_uncast ); -uint64_t mirror_current_bps( struct mirror * mirror ); - #endif diff --git a/src/serve.c b/src/serve.c index 80605bc..cef1b67 100644 --- a/src/serve.c +++ b/src/serve.c @@ -879,7 +879,19 @@ uint64_t server_mirror_eta( struct server * serve ) { if ( server_is_mirroring( serve ) ) { uint64_t bytes_to_xfer = server_mirror_bytes_remaining( serve ); - return bytes_to_xfer / ( mirror_current_bps( serve->mirror ) + 1 ); + return bytes_to_xfer / ( server_mirror_bps( serve ) + 1 ); + } + + return 0; +} + +uint64_t server_mirror_bps( struct server * serve ) +{ + if ( server_is_mirroring( serve ) ) { + uint64_t duration_ms = + monotonic_time_ms() - serve->mirror->migration_started; + + return serve->mirror->all_dirty / ( ( duration_ms / 1000 ) + 1 ); } return 0; diff --git a/src/serve.h b/src/serve.h index bb9513c..0102733 100644 --- a/src/serve.h +++ b/src/serve.h @@ -128,6 +128,7 @@ int server_is_mirroring( struct server * serve ); uint64_t server_mirror_bytes_remaining( struct server * serve ); uint64_t server_mirror_eta( struct server * serve ); +uint64_t server_mirror_bps( struct server * serve ); void server_abandon_mirror( struct server * serve ); void server_prevent_mirror_start( struct server *serve ); diff --git a/src/status.c b/src/status.c index aa9f8c2..dc8d19f 100644 --- a/src/status.c +++ b/src/status.c @@ -27,7 +27,7 @@ struct status * status_create( struct server * serve ) status->migration_duration = 0; } status->migration_duration /= 1000; - status->migration_speed = serve->mirror->all_dirty / ( status->migration_duration + 1 ); + status->migration_speed = server_mirror_bps( serve ); status->migration_speed_limit = serve->mirror->max_bytes_per_second; status->migration_seconds_left = server_mirror_eta( serve );