diff --git a/src/mirror.c b/src/mirror.c index 2b35a31..ef355d4 100644 --- a/src/mirror.c +++ b/src/mirror.c @@ -166,8 +166,10 @@ int mirror_pass(struct server * serve, int is_last_pass, uint64_t *written) uint64_t current = 0; int success = 1; struct bitset_mapping *map = serve->mirror->dirty_map; + struct mirror * m = serve->mirror; *written = 0; + while (current < serve->size) { int run = bitset_run_count(map, current, mirror_longest_write); @@ -205,7 +207,10 @@ 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; *written += run; + } else { + m->this_pass_clean += run; } current += run; @@ -353,6 +358,8 @@ void mirror_run( struct server *serve ) info("Starting mirror" ); for (m->pass=0; m->pass < mirror_maximum_passes-1; m->pass++) { + m->this_pass_clean = 0; + m->this_pass_dirty = 0; debug("mirror start pass=%d", m->pass); if ( !mirror_pass( serve, 0, &written ) ){ @@ -366,6 +373,9 @@ void mirror_run( struct server *serve ) server_lock_io( serve ); { + m->this_pass_clean = 0; + m->this_pass_dirty = 0; + if ( mirror_pass( serve, 1, &written ) && mirror_should_quit( serve->mirror ) ) { debug("exit!"); diff --git a/src/mirror.h b/src/mirror.h index 741151a..3300a4b 100644 --- a/src/mirror.h +++ b/src/mirror.h @@ -82,6 +82,12 @@ struct mirror { /* The current mirror pass. We put this here so status can query it */ int pass; + + /* 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. */ + uint64_t this_pass_dirty; + uint64_t this_pass_clean; }; diff --git a/src/status.c b/src/status.c index 88ebb12..4ce697c 100644 --- a/src/status.c +++ b/src/status.c @@ -17,6 +17,8 @@ struct status * status_create( struct server * serve ) status->is_mirroring = NULL != serve->mirror; if ( status->is_mirroring ) { status->migration_pass = serve->mirror->pass; + status->pass_dirty_bytes = serve->mirror->this_pass_dirty; + status->pass_clean_bytes = serve->mirror->this_pass_clean; } server_unlock_start_mirror( serve ); diff --git a/src/status.h b/src/status.h index 9d6b6c8..d2cc67e 100644 --- a/src/status.h +++ b/src/status.h @@ -45,7 +45,14 @@ * When migrating, we perform a number of passes over the file. This indicates * the current pass. * + * pass_dirty_bytes: + * For the current pass, how many dirty bytes have we found so far? These are + * classed as bytes that we are required to send to the destination. * + * pass_clean_bytes: + * 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. */ @@ -60,6 +67,9 @@ struct status { int has_control; int is_mirroring; int migration_pass; + uint64_t pass_dirty_bytes; + uint64_t pass_clean_bytes; + }; /** Create a status object for the given server. */ diff --git a/tests/unit/check_status.c b/tests/unit/check_status.c index 66faea1..8697337 100644 --- a/tests/unit/check_status.c +++ b/tests/unit/check_status.c @@ -119,6 +119,22 @@ START_TEST( test_gets_size ) } END_TEST +START_TEST( test_gets_pass_statistics ) +{ + struct server * server = mock_mirroring_server(); + server->mirror->this_pass_clean = 2048; + server->mirror->this_pass_dirty = 4096; + + 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" ); + + status_destroy( status ); + destroy_mock_server( server ); +} +END_TEST + START_TEST( test_renders_has_control ) {