From dd6610e98be0ed989fea8e37d45969b7602bac5f Mon Sep 17 00:00:00 2001 From: Andy Beverley Date: Sat, 7 Sep 2013 12:40:21 +0100 Subject: [PATCH] Enable SIGUSR1 stats to work without gui --- man/nwipe.1 | 3 ++ src/context.h | 9 ++-- src/gui.c | 122 +++++++++++++++++++++++++++++--------------------- src/gui.h | 1 + src/nwipe.c | 5 ++- src/options.c | 2 +- 6 files changed, 85 insertions(+), 57 deletions(-) diff --git a/man/nwipe.1 b/man/nwipe.1 index 817f8db..4ccc60c 100644 --- a/man/nwipe.1 +++ b/man/nwipe.1 @@ -18,6 +18,8 @@ same as dwipe, with a few changes: - The parted library is used to detect drives .TP - The code is designed to be compiled with gcc +.TP +- SIGUSR1 can be used to log the stats of the current wipe .SH OPTIONS .TP @@ -41,6 +43,7 @@ Do not wait for a key before exiting (default is to wait). \fB\-\-nogui\fR Do not show the GUI interface. Can only be used with the autonuke option. Nowait option is automatically invoked with the nogui option. +SIGUSR1 can be used to retrieve the current wiping statistics. .TP \fB\-\-verify\fR=\fITYPE\fR Whether to perform verification of erasure (default: last) diff --git a/src/context.h b/src/context.h index 0249e1e..ca13d0c 100644 --- a/src/context.h +++ b/src/context.h @@ -123,9 +123,12 @@ typedef struct nwipe_context_t_ /* Values cannot form part of the second array below, hence the need for this. */ typedef struct { - int nwipe_enumerated; /* The number of devices available. */ - int nwipe_selected; /* The number of devices being wiped. */ - pthread_t *gui_thread; /* The ID of GUI thread. */ + int nwipe_enumerated; /* The number of devices available. */ + int nwipe_selected; /* The number of devices being wiped. */ + time_t maxeta; /* The estimated runtime of the slowest device. */ + u64 throughput; /* Total throughput */ + u64 errors; /* The combined number of errors of all processes. */ + pthread_t *gui_thread; /* The ID of GUI thread. */ } nwipe_misc_thread_data_t; /* The second points to the first structure, as well as the structure of all the devices */ diff --git a/src/gui.c b/src/gui.c index daebbe2..6c2a40f 100644 --- a/src/gui.c +++ b/src/gui.c @@ -1659,13 +1659,13 @@ void *nwipe_gui_status( void *ptr ) int keystroke; /* The combined througput of all processes. */ - u64 nwipe_throughput = 0; + nwipe_misc_thread_data->throughput = 0; /* The estimated runtime of the slowest device. */ - time_t nwipe_maxeta = 0; + nwipe_misc_thread_data->maxeta = 0; /* The combined number of errors of all processes. */ - u64 nwipe_errors = 0; + nwipe_misc_thread_data->errors = 0; /* Time values. */ int nwipe_hh; @@ -1801,53 +1801,7 @@ void *nwipe_gui_status( void *ptr ) if ( nwipe_gui_blank == 0 ) { - nwipe_active = 0; // Number of active wipe threads - /* Enumerate all contexts to compute statistics. */ - for( i = 0 ; i < count ; i++ ) - { - /* Check whether the child process is still running the wipe. */ - if( c[i]->thread > 0 ) - { - /* Increment the child counter. */ - nwipe_active += 1; - - /* Maintain a rolling average of throughput. */ - nwipe_update_speedring( &c[i]->speedring, c[i]->round_done, nwipe_time_now ); - - if( c[i]->speedring.timestotal > 0 ) - { - /* Update the current average throughput in bytes-per-second. */ - c[i]->throughput = c[i]->speedring.bytestotal / c[i]->speedring.timestotal; - - /* Update the estimated remaining runtime. */ - /* Check that throughput is not zero (sometimes caused during a sync) */ - if (c[i]->throughput == 0) - { - c[i]->throughput = 1; - } - - c[i]->eta = ( c[i]->round_size - c[i]->round_done ) / c[i]->throughput; - - if( c[i]->eta > nwipe_maxeta ) - { - nwipe_maxeta = c[i]->eta; - } - } - - /* Update the percentage value. */ - c[i]->round_percent = (double) c[i]->round_done / (double) c[i]->round_size * 100; - - /* Accumulate combined throughput. */ - nwipe_throughput += c[i]->throughput; - - } /* child running */ - - /* Accumulate the error count. */ - nwipe_errors += c[i]->pass_errors; - nwipe_errors += c[i]->verify_errors; - - } /* for statistics */ - + nwipe_active = compute_stats(ptr); // Returns number of active wipe threads /* Print information for the user. */ for( i = offset ; i < offset + slots && i < count ; i++ ) @@ -1949,6 +1903,7 @@ void *nwipe_gui_status( void *ptr ) nwipe_gui_load(); + u64 nwipe_throughput = nwipe_misc_thread_data->throughput; if( nwipe_throughput >= INT64_C( 1000000000000000 ) ) { nwipe_throughput /= INT64_C( 1000000000000 ); nwipe_format = nwipe_tera; } else if( nwipe_throughput >= INT64_C( 1000000000000 ) ) @@ -1984,6 +1939,7 @@ void *nwipe_gui_status( void *ptr ) mvwprintw( stats_window, NWIPE_GUI_STATS_ETA_Y, 1, "Remaining:" ); + time_t nwipe_maxeta = nwipe_misc_thread_data->maxeta; if( nwipe_maxeta > 0 ) { /* Do it again for the estimated runtime remaining. */ @@ -1999,7 +1955,7 @@ void *nwipe_gui_status( void *ptr ) /* Print the error count. */ mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_ERRORS_X, "Errors:" ); - mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_TAB, "%llu", nwipe_errors ); + mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_TAB, "%llu", nwipe_misc_thread_data->errors ); /* Add a border. */ box( stats_window, 0, 0 ); @@ -2059,6 +2015,70 @@ void *nwipe_gui_status( void *ptr ) } /* nwipe_gui_status */ +int compute_stats(void *ptr) +{ + nwipe_thread_data_ptr_t *nwipe_thread_data_ptr; + nwipe_thread_data_ptr = (nwipe_thread_data_ptr_t *) ptr; + + nwipe_context_t **c; + nwipe_misc_thread_data_t *nwipe_misc_thread_data; + + c = nwipe_thread_data_ptr->c; + nwipe_misc_thread_data = nwipe_thread_data_ptr->nwipe_misc_thread_data; + int count = nwipe_misc_thread_data->nwipe_selected; + + int nwipe_active = 0; + int i; + + time_t nwipe_time_now = time( NULL ); + + /* Enumerate all contexts to compute statistics. */ + for( i = 0 ; i < count ; i++ ) + { + /* Check whether the child process is still running the wipe. */ + if( c[i]->thread > 0 ) + { + /* Increment the child counter. */ + nwipe_active += 1; + + /* Maintain a rolling average of throughput. */ + nwipe_update_speedring( &c[i]->speedring, c[i]->round_done, nwipe_time_now ); + + if( c[i]->speedring.timestotal > 0 ) + { + /* Update the current average throughput in bytes-per-second. */ + c[i]->throughput = c[i]->speedring.bytestotal / c[i]->speedring.timestotal; + + /* Update the estimated remaining runtime. */ + /* Check that throughput is not zero (sometimes caused during a sync) */ + if (c[i]->throughput == 0) + { + c[i]->throughput = 1; + } + + c[i]->eta = ( c[i]->round_size - c[i]->round_done ) / c[i]->throughput; + + if( c[i]->eta > nwipe_misc_thread_data->maxeta ) + { + nwipe_misc_thread_data->maxeta = c[i]->eta; + } + } + + /* Update the percentage value. */ + c[i]->round_percent = (double) c[i]->round_done / (double) c[i]->round_size * 100; + + /* Accumulate combined throughput. */ + nwipe_misc_thread_data->throughput += c[i]->throughput; + } /* child running */ + + /* Accumulate the error count. */ + nwipe_misc_thread_data->errors += c[i]->pass_errors; + nwipe_misc_thread_data->errors += c[i]->verify_errors; + + } /* for statistics */ + + return nwipe_active; +} void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_bytes, time_t speedring_now ) { diff --git a/src/gui.h b/src/gui.h index 1727a3c..60a3d21 100644 --- a/src/gui.h +++ b/src/gui.h @@ -35,6 +35,7 @@ void nwipe_gui_rounds( void ); /* Change the rounds op void nwipe_gui_verify( void ); /* Change the verify option. */ void nwipe_gui_noblank( void ); /* Change the noblank option. */ +int compute_stats(void *ptr); void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_done, time_t speedring_now ); diff --git a/src/nwipe.c b/src/nwipe.c index 253323e..3aea2c6 100644 --- a/src/nwipe.c +++ b/src/nwipe.c @@ -520,6 +520,8 @@ void *signal_hand(void *ptr) // Log current status. All values are automatically updated by the GUI case SIGUSR1 : { + compute_stats(ptr); + for( i = 0; i < nwipe_misc_thread_data->nwipe_selected; i++ ) { @@ -568,7 +570,7 @@ void *signal_hand(void *ptr) case SIGTERM : { - for( i = 0; i < nwipe_misc_thread_data->nwipe_enumerated; i++ ) + for( i = 0; i < nwipe_misc_thread_data->nwipe_selected; i++ ) { if ( c[i]->thread ) @@ -596,7 +598,6 @@ void *signal_hand(void *ptr) printf("%s\n", log_lines[i]); } - printf("Program interrupted (caught signal %d)\n", sig); // Cleanup diff --git a/src/options.c b/src/options.c index 96b9a31..5ab9796 100644 --- a/src/options.c +++ b/src/options.c @@ -395,7 +395,7 @@ display_help() puts(" --noblank Do not blank disk after wipe (default is to complete a final blank pass)" ); puts(" --nowait Do not wait for a key before exiting (default is to wait)" ); puts(" --nogui Do not show the GUI interface. Automatically invokes the nowait option" ); - puts(" Must be used with --autonuke option"); + puts(" Must be used with --autonuke option. Send SIGUSR1 to log current stats"); puts(""); exit( EXIT_SUCCESS ); }