diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index 78d248a..6c379ee 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -490,7 +490,7 @@ typedef struct pvwatchfd_s *pvwatchfd_t; void pv_error(pvstate_t, char *, ...); int pv_main_loop(pvstate_t); -void pv_calculate_transfer_rate(pvstate_t, bool); +void pv_calculate_transfer_rate(pvtransfercalc_t, pvtransferstate_t, pvcontrol_t, pvdisplay_t, bool); long pv_bound_long(long, long, long); long pv_seconds_remaining(const off_t, const off_t, const long double); diff --git a/src/pv/calc.c b/src/pv/calc.c index 51515a7..4eca7f1 100644 --- a/src/pv/calc.c +++ b/src/pv/calc.c @@ -17,23 +17,24 @@ * rate, otherwise calulate the average rate from the difference between the * current position + elapsed time pair, and the oldest pair in the buffer. */ -static void pv__update_average_rate_history(pvstate_t state, long double rate) +static void pv__update_average_rate_history(pvtransfercalc_t calc, pvtransferstate_t transfer, + unsigned int history_interval, long double rate) { - size_t first = state->calc.history_first; - size_t last = state->calc.history_last; + size_t first = calc->history_first; + size_t last = calc->history_last; long double last_elapsed; - if (NULL == state->calc.history) + if (NULL == calc->history) return; - last_elapsed = state->calc.history[last].elapsed_sec; + last_elapsed = calc->history[last].elapsed_sec; /* * Do nothing if this is not the first call but not enough time has * elapsed since the previous call yet. */ if ((last_elapsed > 0.0) - && (state->transfer.elapsed_seconds < (last_elapsed + state->control.history_interval))) + && (transfer->elapsed_seconds < (last_elapsed + history_interval))) return; /* @@ -41,53 +42,59 @@ static void pv__update_average_rate_history(pvstate_t state, long double rate) * buffer. */ if (last_elapsed > 0.0) { - size_t len = state->calc.history_len; + size_t len = calc->history_len; last = (last + 1) % len; - state->calc.history_last = last; + calc->history_last = last; if (last == first) { first = (first + 1) % len; - state->calc.history_first = first; + calc->history_first = first; } } - state->calc.history[last].elapsed_sec = state->transfer.elapsed_seconds; - state->calc.history[last].transferred = state->transfer.transferred; + calc->history[last].elapsed_sec = transfer->elapsed_seconds; + calc->history[last].transferred = transfer->transferred; if (first == last) { - state->calc.current_avg_rate = rate; + calc->current_avg_rate = rate; } else { - off_t bytes = (state->calc.history[last].transferred - state->calc.history[first].transferred); - long double sec = (state->calc.history[last].elapsed_sec - state->calc.history[first].elapsed_sec); - state->calc.current_avg_rate = (long double) bytes / sec; + off_t bytes = (calc->history[last].transferred - calc->history[first].transferred); + long double sec = (calc->history[last].elapsed_sec - calc->history[first].elapsed_sec); + calc->current_avg_rate = (long double) bytes / sec; } } /* - * Update all calculated transfer state (state->calc). + * Update all calculated transfer state (usually state->calc). * - * If "final" is true, this is the final update, so - * state->calc.transfer_rate and state->calc.average_rate are given as an - * average over the whole transfer; otherwise they are the current transfer - * rate and current average rate. + * If "final" is true, this is the final update, so calc->transfer_rate and + * calc->average_rate are given as an average over the whole transfer; + * otherwise they are the current transfer rate and current average rate. * - * The value of state->calc.percentage will reflect the percentage - * completion if state->control.size is greater than zero, otherwise it will - * increase by 2 each call and wrap at 200. + * The value of calc->percentage will reflect the percentage completion if + * control->size is greater than zero, otherwise it will increase by 2 each + * call and wrap at 200. */ -void pv_calculate_transfer_rate(pvstate_t state, bool final) +void pv_calculate_transfer_rate(pvtransfercalc_t calc, pvtransferstate_t transfer, pvcontrol_t control, + pvdisplay_t display, bool final) { off_t bytes_since_last; long double time_since_last, transfer_rate, average_rate; - /* Quick safety check - state must exist. */ - if (NULL == state) + /* Quick safety checks for null pointers. */ + if (NULL == calc) + return; + if (NULL == transfer) + return; + if (NULL == control) + return; + if (NULL == display) return; bytes_since_last = 0; - if (state->transfer.transferred >= 0) { - bytes_since_last = state->transfer.transferred - state->calc.prev_transferred; - state->calc.prev_transferred = state->transfer.transferred; + if (transfer->transferred >= 0) { + bytes_since_last = transfer->transferred - calc->prev_transferred; + calc->prev_transferred = transfer->transferred; } /* @@ -96,37 +103,37 @@ void pv_calculate_transfer_rate(pvstate_t state, bool final) * adding to that until a reasonable amount of time has passed to * avoid rate spikes or division by zero. */ - time_since_last = state->transfer.elapsed_seconds - state->calc.prev_elapsed_sec; + time_since_last = transfer->elapsed_seconds - calc->prev_elapsed_sec; if (time_since_last <= 0.01) { - transfer_rate = state->calc.prev_rate; - state->calc.prev_trans += bytes_since_last; + transfer_rate = calc->prev_rate; + calc->prev_trans += bytes_since_last; } else { long double measured_rate; - transfer_rate = ((long double) bytes_since_last + state->calc.prev_trans) / time_since_last; + transfer_rate = ((long double) bytes_since_last + calc->prev_trans) / time_since_last; measured_rate = transfer_rate; - state->calc.prev_elapsed_sec = state->transfer.elapsed_seconds; - state->calc.prev_trans = 0; + calc->prev_elapsed_sec = transfer->elapsed_seconds; + calc->prev_trans = 0; - if (state->control.bits) + if (control->bits) measured_rate = 8.0 * measured_rate; - if ((state->calc.measurements_taken < 1) || (measured_rate < state->calc.rate_min)) { - state->calc.rate_min = measured_rate; + if ((calc->measurements_taken < 1) || (measured_rate < calc->rate_min)) { + calc->rate_min = measured_rate; } - if (measured_rate > state->calc.rate_max) { - state->calc.rate_max = measured_rate; + if (measured_rate > calc->rate_max) { + calc->rate_max = measured_rate; } - state->calc.rate_sum += measured_rate; - state->calc.ratesquared_sum += (measured_rate * measured_rate); - state->calc.measurements_taken++; + calc->rate_sum += measured_rate; + calc->ratesquared_sum += (measured_rate * measured_rate); + calc->measurements_taken++; } - state->calc.prev_rate = transfer_rate; + calc->prev_rate = transfer_rate; /* Update history and current average rate for ETA. */ - pv__update_average_rate_history(state, transfer_rate); - average_rate = state->calc.current_avg_rate; + pv__update_average_rate_history(calc, transfer, control->history_interval, transfer_rate); + average_rate = calc->current_avg_rate; /* * If this is the final update at the end of the transfer, we @@ -135,18 +142,18 @@ void pv_calculate_transfer_rate(pvstate_t state, bool final) */ if (final) { /* Safety check to avoid division by zero. */ - if (state->transfer.elapsed_seconds < 0.000001) - state->transfer.elapsed_seconds = 0.000001; + if (transfer->elapsed_seconds < 0.000001) + transfer->elapsed_seconds = 0.000001; average_rate = - (((long double) (state->transfer.transferred)) - - ((long double) state->display.initial_offset)) / (long double) (state->transfer.elapsed_seconds); + (((long double) (transfer->transferred)) - + ((long double) display->initial_offset)) / (long double) (transfer->elapsed_seconds); transfer_rate = average_rate; } - state->calc.transfer_rate = transfer_rate; - state->calc.average_rate = average_rate; + calc->transfer_rate = transfer_rate; + calc->average_rate = average_rate; - if (state->control.size <= 0) { + if (control->size <= 0) { /* * If we don't know the total size of the incoming data, * then for a percentage, we gradually increase the @@ -156,16 +163,16 @@ void pv_calculate_transfer_rate(pvstate_t state, bool final) * 0%-100%, 100%-0%, 0%-100%, and so on. */ if (transfer_rate > 0) - state->calc.percentage += 2; - if (state->calc.percentage > 199) - state->calc.percentage = 0; + calc->percentage += 2; + if (calc->percentage > 199) + calc->percentage = 0; } else { - state->calc.percentage = pv_percentage(state->transfer.transferred, state->control.size); + calc->percentage = pv_percentage(transfer->transferred, control->size); } /* Ensure the percentage is never negative or huge. */ - if (state->calc.percentage < 0.0) - state->calc.percentage = 0.0; - if (state->calc.percentage > 100000.0) - state->calc.percentage = 100000.0; + if (calc->percentage < 0.0) + calc->percentage = 0.0; + if (calc->percentage > 100000.0) + calc->percentage = 100000.0; } diff --git a/src/pv/display.c b/src/pv/display.c index 7726d1b..782fb12 100644 --- a/src/pv/display.c +++ b/src/pv/display.c @@ -1194,7 +1194,7 @@ void pv_display(pvstate_t state, bool final) pv_sig_checkbg(); - pv_calculate_transfer_rate(state, final); + pv_calculate_transfer_rate(&(state->calc), &(state->transfer), &(state->control), &(state->display), final); /* * Enable colour on the main display, and disable it on the extra diff --git a/src/pv/loop.c b/src/pv/loop.c index bfb39da..8c9887f 100644 --- a/src/pv/loop.c +++ b/src/pv/loop.c @@ -506,7 +506,8 @@ int pv_main_loop(pvstate_t state) if (state->control.no_display) { /* If there's no display, calculate rate for the statistics. */ - pv_calculate_transfer_rate(state, final_update); + pv_calculate_transfer_rate(&(state->calc), &(state->transfer), &(state->control), + &(state->display), final_update); } else { /* Produce the display. */ pv_display(state, final_update);