status: Add migration_speed ( bytes per second ) and migration_duration( seconds ) to the migration output

This commit is contained in:
nick
2013-07-26 11:50:01 +01:00
parent bc9ce93648
commit f590f8ed3c
5 changed files with 86 additions and 9 deletions

View File

@@ -106,6 +106,12 @@ void mirror_reset( struct mirror * mirror )
NULLCHECK( mirror->dirty_map );
mirror_set_state( mirror, MS_INIT );
bitset_set(mirror->dirty_map);
mirror->all_dirty = 0;
mirror->all_clean = 0;
mirror->pass = 0;
mirror->this_pass_dirty = 0;
mirror->this_pass_clean = 0;
mirror->migration_started = 0;
}
@@ -216,9 +222,11 @@ int mirror_pass(struct server * serve, int is_last_pass, uint64_t *written)
if (!is_last_pass) { server_unlock_io( serve ); }
m->this_pass_dirty += run;
m->all_dirty += run;
*written += run;
} else {
m->this_pass_clean += run;
m->all_clean += run;
}
current += run;
@@ -365,6 +373,8 @@ void mirror_run( struct server *serve )
uint64_t written;
info("Starting mirror" );
m->migration_started = monotonic_time_ms();
for (m->pass=0; m->pass < mirror_maximum_passes-1; m->pass++) {
m->this_pass_clean = 0;
m->this_pass_dirty = 0;

View File

@@ -67,7 +67,11 @@ struct mirror {
union mysockaddr * connect_from;
int client;
const char * filename;
/* Not used yet. Will be a limiter, used to restrict migration speed.
* only dirty bytes (those going over the network) will be considered */
off64_t max_bytes_per_second;
enum mirror_finish_action action_at_finish;
char *mapped;
@@ -83,6 +87,14 @@ struct mirror {
/* The current mirror pass. We put this here so status can query it */
int pass;
/* Number of dirty and clean bytes for the entire migration */
uint64_t all_dirty;
uint64_t all_clean;
/* The time (from monotonic_time_ms()) the migration was started. Can be
* used to calculate bps, etc. */
uint64_t migration_started;
/* The number of dirty (had to send to dest) and clean (could skip) bytes
* for this pass. Add them together and subtract from size to get remaining
* bytes. */

View File

@@ -19,8 +19,23 @@ struct status * status_create( struct server * serve )
status->migration_pass = serve->mirror->pass;
status->pass_dirty_bytes = serve->mirror->this_pass_dirty;
status->pass_clean_bytes = serve->mirror->this_pass_clean;
status->migration_duration = monotonic_time_ms();
if ( ( serve->mirror->migration_started ) < status->migration_duration ) {
status->migration_duration -= serve->mirror->migration_started;
} else {
status->migration_duration = 0;
}
status->migration_duration /= 1000;
status->migration_speed = serve->mirror->all_dirty / ( status->migration_duration + 1 );
}
server_unlock_start_mirror( serve );
return status;
@@ -46,6 +61,8 @@ int status_write( struct status * status, int fd )
PRINT_INT( migration_pass );
PRINT_UINT64( pass_dirty_bytes );
PRINT_UINT64( pass_clean_bytes );
PRINT_UINT64( migration_speed );
PRINT_UINT64( migration_duration );
}
dprintf(fd, "\n");

View File

@@ -41,6 +41,13 @@
* If is_migrating is true, then a number of other attributes may appear,
* relating to the progress of the migration.
*
* migration_duration:
* How long the migration has been running for, in ms.
*
* migration_speed:
* Network transfer speed, in bytes/second. This only takes dirty bytes
* into account.
*
* migration_pass:
* When migrating, we perform a number of passes over the file. This indicates
* the current pass.
@@ -53,6 +60,7 @@
* For the current pass, how many clean bytes? These are bytes we don't need
* to send to the destination. Once all the bytes are clean, the migration is
* done.
*
*/
@@ -70,6 +78,8 @@ struct status {
uint64_t pass_dirty_bytes;
uint64_t pass_clean_bytes;
uint64_t migration_duration;
uint64_t migration_speed;
};
/** Create a status object for the given server. */

View File

@@ -119,17 +119,34 @@ START_TEST( test_gets_size )
}
END_TEST
START_TEST( test_gets_pass_statistics )
START_TEST( test_gets_migration_statistics )
{
struct server * server = mock_mirroring_server();
server->mirror->this_pass_clean = 2048;
server->mirror->this_pass_dirty = 4096;
server->mirror->all_dirty = 16384;
/* we have a bit of a time dependency here */
server->mirror->migration_started = monotonic_time_ms();
struct status * status = status_create( server );
fail_unless( 2048 == status->pass_clean_bytes, "pass_clean_bytes wasn't gathered" );
fail_unless( 4096 == status->pass_dirty_bytes, "pass_dirty_bytes wasn't gathered" );
fail_unless (
0 == status->migration_duration ||
1 == status->migration_duration ||
2 == status->migration_duration,
"migration_duration is unreasonable!"
);
fail_unless(
16384 / ( status->migration_duration + 1 ) == status->migration_speed,
"migration_speed not calculated correctly"
);
status_destroy( status );
destroy_mock_server( server );
}
@@ -255,7 +272,7 @@ START_TEST( test_renders_migration_pass )
}
END_TEST
START_TEST( test_renders_pass_statistics )
START_TEST( test_renders_migration_statistics )
{
struct status status;
int fds[2];
@@ -266,15 +283,23 @@ START_TEST( test_renders_pass_statistics )
status.is_mirroring = 0;
status.pass_dirty_bytes = 2048;
status.pass_clean_bytes = 4096;
status.migration_duration = 8;
status.migration_speed = 40000000;
status_write( &status, fds[1] );
fail_unless( read_until_newline( fds[0], buf, 1024 ) > 0,
"Couldn't read the result" );
found = strstr( buf, "pass_dirty_bytes" );
fail_if( NULL != found, "migration pass output when not migrating" );
fail_if( NULL != found, "pass_dirty_bytes output when not migrating" );
found = strstr( buf, "pass_clean_bytes" );
fail_if( NULL != found, "migration pass output when not migrating" );
fail_if( NULL != found, "pass_clean_bytes output when not migrating" );
found = strstr( buf, "migration_duration" );
fail_if( NULL != found, "migration_duration output when not migrating" );
found = strstr( buf, "migration_speed" );
fail_if( NULL != found, "migration_speed output when not migrating" );
status.is_mirroring = 1;
status_write( &status, fds[1] );
@@ -282,10 +307,13 @@ START_TEST( test_renders_pass_statistics )
fail_unless( read_until_newline( fds[0], buf, 1024 ) > 0,
"Couldn't read the result" );
found = strstr( buf, "pass_dirty_bytes=2048" );
fail_if( NULL == found, "migration pass not output when not migrating" );
fail_if( NULL == found, "pass_dirty_bytes not output when migrating" );
found = strstr( buf, "pass_clean_bytes=4096" );
fail_if( NULL == found, "migration pass not output when not migrating" );
fail_if( NULL == found, "pass_clean_bytes not output when migrating" );
found = strstr( buf, "migration_duration=8" );
fail_if( NULL == found, "migration_duration not output when migrating" );
found = strstr( buf, "migration_speed=40000000" );
fail_if( NULL == found, "migration_speed not output when migrating" );
}
END_TEST
@@ -302,7 +330,7 @@ Suite *status_suite(void)
tcase_add_test(tc_create, test_gets_pid);
tcase_add_test(tc_create, test_gets_size);
tcase_add_test(tc_create, test_gets_migration_pass);
tcase_add_test(tc_create, test_gets_pass_statistics);
tcase_add_test(tc_create, test_gets_migration_statistics);
tcase_add_test(tc_render, test_renders_has_control);
@@ -310,7 +338,7 @@ Suite *status_suite(void)
tcase_add_test(tc_render, test_renders_pid);
tcase_add_test(tc_render, test_renders_size);
tcase_add_test(tc_render, test_renders_migration_pass);
tcase_add_test(tc_render, test_renders_pass_statistics);
tcase_add_test(tc_render, test_renders_migration_statistics);
suite_add_tcase(s, tc_create);
suite_add_tcase(s, tc_render);