Move calculated values out of state.display into a new structure, state.calc, to separate out the display portion from the calculation portion; and move history_interval into state.control, as it is a control parameter set at the start.
This commit is contained in:
+18
-10
@@ -116,6 +116,7 @@ struct pvstate_s {
|
||||
int watch_fd; /* fd to watch */
|
||||
int output_fd; /* fd to write output to */
|
||||
unsigned int average_rate_window; /* time window in seconds for average rate calculations */
|
||||
unsigned int history_interval; /* seconds between each average rate calc history entry */
|
||||
unsigned int width; /* screen width */
|
||||
unsigned int height; /* screen height */
|
||||
bool force; /* display even if not on terminal */
|
||||
@@ -193,16 +194,28 @@ struct pvstate_s {
|
||||
|
||||
char lastoutput_buffer[PV_SIZEOF_LASTOUTPUT_BUFFER];
|
||||
|
||||
long double prev_elapsed_sec; /* elapsed sec at which rate last calculated */
|
||||
long double prev_rate; /* last calculated instantaneous transfer rate */
|
||||
long double prev_trans; /* bytes transferred since last rate calculation */
|
||||
long double current_avg_rate; /* current average rate over last history intervals */
|
||||
/*@only@*/ /*@null@*/ char *display_buffer; /* buffer for display string */
|
||||
size_t display_buffer_size; /* size allocated to display buffer */
|
||||
size_t display_string_len; /* length of string in display buffer */
|
||||
off_t initial_offset; /* offset when first opened (when watching fds) */
|
||||
size_t lastoutput_length; /* number of last-output bytes to show */
|
||||
|
||||
size_t format_segment_count; /* number of format string segments */
|
||||
|
||||
unsigned int prev_screen_width; /* screen width last time we were called */
|
||||
bool display_visible; /* set once anything written to terminal */
|
||||
|
||||
} display;
|
||||
|
||||
/************************************
|
||||
* Calculated state of the transfer *
|
||||
************************************/
|
||||
struct {
|
||||
long double prev_elapsed_sec; /* elapsed sec at which rate last calculated */
|
||||
long double prev_rate; /* last calculated instantaneous transfer rate */
|
||||
long double prev_trans; /* bytes transferred since last rate calculation */
|
||||
long double current_avg_rate; /* current average rate over last history intervals */
|
||||
|
||||
/* Keep track of progress over last intervals to compute current average rate. */
|
||||
/*@null@*/ struct { /* state at previous intervals (circular buffer) */
|
||||
long double elapsed_sec; /* time since start of transfer */
|
||||
@@ -211,14 +224,9 @@ struct pvstate_s {
|
||||
size_t history_len; /* total size of history array */
|
||||
size_t history_first; /* index of oldest entry */
|
||||
size_t history_last; /* index of newest entry */
|
||||
size_t format_segment_count; /* number of format string segments */
|
||||
|
||||
int history_interval; /* seconds between each history entry */
|
||||
unsigned int prev_screen_width; /* screen width last time we were called */
|
||||
int percentage; /* transfer percentage completion */
|
||||
bool display_visible; /* set once anything written to terminal */
|
||||
|
||||
} display;
|
||||
} calc;
|
||||
|
||||
/********************
|
||||
* Cursor/IPC state *
|
||||
|
||||
+36
-37
@@ -608,21 +608,21 @@ static long bound_long(long x, long min, long max)
|
||||
static void pv__update_average_rate_history(pvstate_t state, off_t total_bytes, long double elapsed_sec,
|
||||
long double rate)
|
||||
{
|
||||
size_t first = state->display.history_first;
|
||||
size_t last = state->display.history_last;
|
||||
size_t first = state->calc.history_first;
|
||||
size_t last = state->calc.history_last;
|
||||
long double last_elapsed;
|
||||
|
||||
if (NULL == state->display.history)
|
||||
if (NULL == state->calc.history)
|
||||
return;
|
||||
|
||||
last_elapsed = state->display.history[last].elapsed_sec;
|
||||
last_elapsed = state->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)
|
||||
&& (elapsed_sec < (last_elapsed + state->display.history_interval)))
|
||||
&& (elapsed_sec < (last_elapsed + state->control.history_interval)))
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -630,25 +630,24 @@ static void pv__update_average_rate_history(pvstate_t state, off_t total_bytes,
|
||||
* buffer.
|
||||
*/
|
||||
if (last_elapsed > 0.0) {
|
||||
size_t len = state->display.history_len;
|
||||
size_t len = state->calc.history_len;
|
||||
last = (last + 1) % len;
|
||||
state->display.history_last = last;
|
||||
state->calc.history_last = last;
|
||||
if (last == first) {
|
||||
first = (first + 1) % len;
|
||||
state->display.history_first = first;
|
||||
state->calc.history_first = first;
|
||||
}
|
||||
}
|
||||
|
||||
state->display.history[last].elapsed_sec = elapsed_sec;
|
||||
state->display.history[last].total_bytes = total_bytes;
|
||||
state->calc.history[last].elapsed_sec = elapsed_sec;
|
||||
state->calc.history[last].total_bytes = total_bytes;
|
||||
|
||||
if (first == last) {
|
||||
state->display.current_avg_rate = rate;
|
||||
state->calc.current_avg_rate = rate;
|
||||
} else {
|
||||
off_t bytes = (state->display.history[last].total_bytes - state->display.history[first].total_bytes);
|
||||
long double sec =
|
||||
(state->display.history[last].elapsed_sec - state->display.history[first].elapsed_sec);
|
||||
state->display.current_avg_rate = (long double) bytes / sec;
|
||||
off_t bytes = (state->calc.history[last].total_bytes - state->calc.history[first].total_bytes);
|
||||
long double sec = (state->calc.history[last].elapsed_sec - state->calc.history[first].elapsed_sec);
|
||||
state->calc.current_avg_rate = (long double) bytes / sec;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,20 +708,20 @@ static bool pv__format(pvstate_t state, long double elapsed_sec, off_t bytes_sin
|
||||
* adding to that until a reasonable amount of time has passed to
|
||||
* avoid rate spikes or division by zero.
|
||||
*/
|
||||
time_since_last = elapsed_sec - state->display.prev_elapsed_sec;
|
||||
time_since_last = elapsed_sec - state->calc.prev_elapsed_sec;
|
||||
if (time_since_last <= 0.01) {
|
||||
rate = state->display.prev_rate;
|
||||
state->display.prev_trans += bytes_since_last;
|
||||
rate = state->calc.prev_rate;
|
||||
state->calc.prev_trans += bytes_since_last;
|
||||
} else {
|
||||
rate = ((long double) bytes_since_last + state->display.prev_trans) / time_since_last;
|
||||
state->display.prev_elapsed_sec = elapsed_sec;
|
||||
state->display.prev_trans = 0;
|
||||
rate = ((long double) bytes_since_last + state->calc.prev_trans) / time_since_last;
|
||||
state->calc.prev_elapsed_sec = elapsed_sec;
|
||||
state->calc.prev_trans = 0;
|
||||
}
|
||||
state->display.prev_rate = rate;
|
||||
state->calc.prev_rate = rate;
|
||||
|
||||
/* Update history and current average rate for ETA. */
|
||||
pv__update_average_rate_history(state, total_bytes, elapsed_sec, rate);
|
||||
average_rate = state->display.current_avg_rate;
|
||||
average_rate = state->calc.current_avg_rate;
|
||||
|
||||
/*
|
||||
* If this is the final update at the end of the transfer, we
|
||||
@@ -749,16 +748,16 @@ static bool pv__format(pvstate_t state, long double elapsed_sec, off_t bytes_sin
|
||||
* 0%-100%, 100%-0%, 0%-100%, and so on.
|
||||
*/
|
||||
if (rate > 0)
|
||||
state->display.percentage += 2;
|
||||
if (state->display.percentage > 199)
|
||||
state->display.percentage = 0;
|
||||
state->calc.percentage += 2;
|
||||
if (state->calc.percentage > 199)
|
||||
state->calc.percentage = 0;
|
||||
} else if (state->control.numeric || state->display.component[PV_COMPONENT_PROGRESS].required) {
|
||||
/*
|
||||
* If we do know the total size, and we're going to show
|
||||
* the percentage (numeric mode or a progress bar),
|
||||
* calculate the percentage completion.
|
||||
*/
|
||||
state->display.percentage = pv__calc_percentage(total_bytes, state->control.size);
|
||||
state->calc.percentage = pv__calc_percentage(total_bytes, state->control.size);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -825,7 +824,7 @@ static bool pv__format(pvstate_t state, long double elapsed_sec, off_t bytes_sin
|
||||
} else {
|
||||
(void) pv_snprintf(state->display.display_buffer,
|
||||
state->display.display_buffer_size, "%.99s%ld\n", numericprefix,
|
||||
(long) (state->display.percentage));
|
||||
(long) (state->calc.percentage));
|
||||
}
|
||||
|
||||
state->display.display_string_len = strlen(state->display.display_buffer); /* flawfinder: ignore */
|
||||
@@ -965,7 +964,7 @@ static bool pv__format(pvstate_t state, long double elapsed_sec, off_t bytes_sin
|
||||
eta =
|
||||
pv__seconds_remaining(((off_t) total_bytes - state->display.initial_offset),
|
||||
state->control.size - state->display.initial_offset,
|
||||
state->display.current_avg_rate);
|
||||
state->calc.current_avg_rate);
|
||||
|
||||
/*
|
||||
* Bounds check, so we don't overrun the suffix buffer. This
|
||||
@@ -1020,7 +1019,7 @@ static bool pv__format(pvstate_t state, long double elapsed_sec, off_t bytes_sin
|
||||
eta =
|
||||
pv__seconds_remaining((off_t) (total_bytes - state->display.initial_offset),
|
||||
state->control.size - state->display.initial_offset,
|
||||
state->display.current_avg_rate);
|
||||
state->calc.current_avg_rate);
|
||||
|
||||
/*
|
||||
* Bounds check, so we don't overrun the suffix buffer. This
|
||||
@@ -1152,11 +1151,11 @@ static bool pv__format(pvstate_t state, long double elapsed_sec, off_t bytes_sin
|
||||
/* Known size; show a bar and a percentage. */
|
||||
size_t pct_width;
|
||||
|
||||
if (state->display.percentage < 0)
|
||||
state->display.percentage = 0;
|
||||
if (state->display.percentage > 100000)
|
||||
state->display.percentage = 100000;
|
||||
(void) pv_snprintf(pct, sizeof(pct), "%3ld%%", state->display.percentage);
|
||||
if (state->calc.percentage < 0)
|
||||
state->calc.percentage = 0;
|
||||
if (state->calc.percentage > 100000)
|
||||
state->calc.percentage = 100000;
|
||||
(void) pv_snprintf(pct, sizeof(pct), "%3ld%%", state->calc.percentage);
|
||||
pct_width = strlen(pct); /* flawfinder: ignore */
|
||||
/* flawfinder: always \0-terminated by pv_snprintf() and the earlier memset(). */
|
||||
|
||||
@@ -1169,7 +1168,7 @@ static bool pv__format(pvstate_t state, long double elapsed_sec, off_t bytes_sin
|
||||
available_width = (int) (component_buf_size - 16);
|
||||
|
||||
/* The bar portion. */
|
||||
bar_length = (int) ((available_width * state->display.percentage) / 100 - 1);
|
||||
bar_length = (int) ((available_width * state->calc.percentage) / 100 - 1);
|
||||
for (pad_count = 0; pad_count < bar_length; pad_count++) {
|
||||
if (pad_count < available_width)
|
||||
(void) pv_strlcat(component_content, "=", component_buf_size);
|
||||
@@ -1193,7 +1192,7 @@ static bool pv__format(pvstate_t state, long double elapsed_sec, off_t bytes_sin
|
||||
} else {
|
||||
/* Unknown size; show a moving indicator. */
|
||||
|
||||
int indicator_position = state->display.percentage;
|
||||
int indicator_position = state->calc.percentage;
|
||||
|
||||
available_width = (int) (state->control.width) - static_portion_size - 5;
|
||||
|
||||
|
||||
+14
-14
@@ -24,12 +24,12 @@
|
||||
/* alloc / realloc history buffer */
|
||||
static void pv_alloc_history(pvstate_t state)
|
||||
{
|
||||
if (NULL != state->display.history)
|
||||
free(state->display.history);
|
||||
state->display.history = NULL;
|
||||
if (NULL != state->calc.history)
|
||||
free(state->calc.history);
|
||||
state->calc.history = NULL;
|
||||
|
||||
state->display.history = calloc((size_t) (state->display.history_len), sizeof(state->display.history[0]));
|
||||
if (NULL == state->display.history) {
|
||||
state->calc.history = calloc((size_t) (state->calc.history_len), sizeof(state->calc.history[0]));
|
||||
if (NULL == state->calc.history) {
|
||||
/*@-mustfreefresh@ */
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory
|
||||
@@ -42,8 +42,8 @@ static void pv_alloc_history(pvstate_t state)
|
||||
return;
|
||||
}
|
||||
|
||||
state->display.history_first = state->display.history_last = 0;
|
||||
state->display.history[0].elapsed_sec = 0.0; /* to be safe, memset() not recommended for doubles */
|
||||
state->calc.history_first = state->calc.history_last = 0;
|
||||
state->calc.history[0].elapsed_sec = 0.0; /* to be safe, memset() not recommended for doubles */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -156,9 +156,9 @@ void pv_state_free(pvstate_t state)
|
||||
/*@+keeptrans@ */
|
||||
/* splint - explicitly freeing this structure, so free() here is OK. */
|
||||
|
||||
if (NULL != state->display.history)
|
||||
free(state->display.history);
|
||||
state->display.history = NULL;
|
||||
if (NULL != state->calc.history)
|
||||
free(state->calc.history);
|
||||
state->calc.history = NULL;
|
||||
|
||||
if (NULL != state->files.filename) {
|
||||
unsigned int file_idx;
|
||||
@@ -406,11 +406,11 @@ void pv_state_average_rate_window_set(pvstate_t state, unsigned int val)
|
||||
val = 1;
|
||||
state->control.average_rate_window = val;
|
||||
if (val >= 20) {
|
||||
state->display.history_len = (size_t) (val / 5 + 1);
|
||||
state->display.history_interval = 5;
|
||||
state->calc.history_len = (size_t) (val / 5 + 1);
|
||||
state->control.history_interval = 5;
|
||||
} else {
|
||||
state->display.history_len = (size_t) (val + 1);
|
||||
state->display.history_interval = 1;
|
||||
state->calc.history_len = (size_t) (val + 1);
|
||||
state->control.history_interval = 1;
|
||||
}
|
||||
pv_alloc_history(state);
|
||||
}
|
||||
|
||||
+2
-2
@@ -498,8 +498,8 @@ int pv_watchpid_scanfds(pvstate_t state,
|
||||
/*@-mustfreeonly@ *//* splint - this is not a leak, this is a new entry. */
|
||||
info_array[use_idx].state->display.display_buffer = NULL;
|
||||
info_array[use_idx].state->display.display_buffer_size = 0;
|
||||
info_array[use_idx].state->display.history = NULL;
|
||||
info_array[use_idx].state->display.history_len = 0;
|
||||
info_array[use_idx].state->calc.history = NULL;
|
||||
info_array[use_idx].state->calc.history_len = 0;
|
||||
/*@+mustfreeonly@ */
|
||||
pv_state_average_rate_window_set(info_array[use_idx].state, state->control.average_rate_window);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user