Replace all gettimeofday() calls, and elapsed time arithmetic, with a new set of elapsed time functions based on clock_gettime(), to avoid faults due to time zone / DST changes and machine suspend/resume.
This commit is contained in:
@@ -19,6 +19,7 @@ src/main/remote.c \
|
||||
src/main/version.c \
|
||||
src/pv/cursor.c \
|
||||
src/pv/display.c \
|
||||
src/pv/elapsedtime.c \
|
||||
src/pv/file.c \
|
||||
src/pv/loop.c \
|
||||
src/pv/number.c \
|
||||
|
||||
@@ -84,6 +84,7 @@ is acknowledged and greatly appreciated:
|
||||
* [Nick Black](https://nick-black.com) - added "`--bits`" option
|
||||
* [Andrew Schulman](https://github.com/andrew-schulman) - provided reproducible example of terminal size detection issue in 1.7.17/1.7.18
|
||||
* [fuschia74](https://github.com/fuchsia74) - provided "`--enable-static`" patch for "`configure`"
|
||||
* [Wilhelm von Thiele](https://github.com/TurtleWilly) - assisted with OS X cleanups ([Issue#73](https://codeberg.org/a-j-wood/pv/issues/73), [Issue#74](https://codeberg.org/a-j-wood/pv/issues/74))
|
||||
* [Wilhelm von Thiele](https://github.com/TurtleWilly) - assisted with OS X cleanups ([#73](https://codeberg.org/a-j-wood/pv/issues/73), [#74](https://codeberg.org/a-j-wood/pv/issues/74))
|
||||
* Matějů Miroslav, Ing. - suggested fix for ETA and elapsed time faults when suspending and resuming a machine ([#13](https://codeberg.org/a-j-wood/pv/issues/13))
|
||||
|
||||
---
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* security: keep self-contained copies of name and format string in PV internal state for memory safety
|
||||
* fix: only report errors about missing files when starting to transfer from them, not while calculating size, and behave more like `cat`(1) by skipping them and moving on
|
||||
* fix: auto-calculate total line count with "`--line-mode`" when all inputs are regular files
|
||||
* fix: use `clock_gettime()` in ETA calculation to cope with machine suspend/resume ([#13](https://codeberg.org/a-j-wood/pv/issues/13))
|
||||
* fix: if "`--width`" or "`--height`" were provided, do not change them when the window size changes ([#36](https://codeberg.org/a-j-wood/pv/issues/36))
|
||||
* cleanup: switched the build system to GNU Automake
|
||||
* cleanup: added a test for terminal width detection to "`make check`"
|
||||
|
||||
@@ -4,7 +4,6 @@ Bugs
|
||||
----
|
||||
|
||||
* ([#5](https://codeberg.org/a-j-wood/pv/issues/5)) Transfer IPC leadership on exit of leader
|
||||
* ([#13](https://codeberg.org/a-j-wood/pv/issues/13)) Use `clock_gettime()` in ETA calculation to cope with machine suspend/resume (Mateju Miroslav)
|
||||
* ([#20](https://codeberg.org/a-j-wood/pv/issues/20)) Terminal state is not restored correctly in all cases (VA)
|
||||
* ([#24](https://codeberg.org/a-j-wood/pv/issues/24)) Debian #890901 - Race condition with multiple "`pv -c`" leaves terminal state inconsistent (Lars Ellenberg, Viktor Ashirov)
|
||||
* ([#34](https://codeberg.org/a-j-wood/pv/issues/34)) Continue timer even if input or output is blocking (Martin Probst - Jun 2017)
|
||||
|
||||
+13
-12
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -30,15 +31,15 @@ extern "C" {
|
||||
#define PV_DISPLAY_OUTPUTBUF 256
|
||||
#define PV_DISPLAY_FINETA 512
|
||||
|
||||
#define RATE_GRANULARITY 100000 /* usec between -L rate chunks */
|
||||
#define RATE_BURST_WINDOW 5 /* rate burst window (multiples of rate) */
|
||||
#define REMOTE_INTERVAL 100000 /* usec between checks for -R */
|
||||
#define BUFFER_SIZE 409600 /* default transfer buffer size */
|
||||
#define BUFFER_SIZE_MAX 524288 /* max auto transfer buffer size */
|
||||
#define MAX_READ_AT_ONCE 524288 /* max to read() in one go */
|
||||
#define MAX_WRITE_AT_ONCE 524288 /* max to write() in one go */
|
||||
#define TRANSFER_READ_TIMEOUT 90000 /* usec to time reads out at */
|
||||
#define TRANSFER_WRITE_TIMEOUT 900000 /* usec to time writes out at */
|
||||
#define RATE_GRANULARITY 100000000.0L /* nsec between -L rate chunks */
|
||||
#define RATE_BURST_WINDOW 5 /* rate burst window (multiples of rate) */
|
||||
#define REMOTE_INTERVAL 100000000 /* nsec between checks for -R */
|
||||
#define BUFFER_SIZE 409600 /* default transfer buffer size */
|
||||
#define BUFFER_SIZE_MAX 524288 /* max auto transfer buffer size */
|
||||
#define MAX_READ_AT_ONCE 524288 /* max to read() in one go */
|
||||
#define MAX_WRITE_AT_ONCE 524288 /* max to write() in one go */
|
||||
#define TRANSFER_READ_TIMEOUT 0.09L /* seconds to time reads out at */
|
||||
#define TRANSFER_WRITE_TIMEOUT 0.9L /* seconds to time writes out at */
|
||||
|
||||
#define MAXIMISE_BUFFER_FILL 1
|
||||
|
||||
@@ -125,8 +126,8 @@ struct pvstate_s {
|
||||
* Signal handling *
|
||||
*******************/
|
||||
int pv_sig_old_stderr; /* see pv_sig_ttou() */
|
||||
struct timeval pv_sig_tstp_time; /* see pv_sig_tstp() / __cont() */
|
||||
struct timeval pv_sig_toffset; /* total time spent stopped */
|
||||
struct timespec pv_sig_tstp_time; /* see pv_sig_tstp() / __cont() */
|
||||
struct timespec pv_sig_toffset; /* total time spent stopped */
|
||||
volatile sig_atomic_t pv_sig_newsize; /* whether we need to get term size again */
|
||||
volatile sig_atomic_t pv_sig_abort; /* whether we need to abort right now */
|
||||
volatile sig_atomic_t reparse_display; /* whether to re-check format string */
|
||||
@@ -265,7 +266,7 @@ struct pvwatchfd_s {
|
||||
struct stat sb_fd_link; /* lstat of fd symlink */
|
||||
unsigned long long size; /* size of whole file, 0 if unknown */
|
||||
long long position; /* position last seen at */
|
||||
struct timeval start_time; /* time we started watching the fd */
|
||||
struct timespec start_time; /* time we started watching the fd */
|
||||
};
|
||||
typedef struct pvwatchfd_s *pvwatchfd_t;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -76,6 +77,43 @@ extern int pv_snprintf(char *, size_t, const char *, ...);
|
||||
* termination with '\0'.
|
||||
*/
|
||||
extern size_t pv_strlcat(char *, const char *, size_t);
|
||||
|
||||
/*
|
||||
* Functions relating to elapsed time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read the current elapsed time, relative to an unspecified point in the
|
||||
* past, and store it in the given timespec buffer. The time is guaranteed
|
||||
* to not go backwards and does not count time when the system was
|
||||
* suspended. See clock_gettime(2) with CLOCK_MONOTONIC.
|
||||
*/
|
||||
void pv_elapsedtime_read(struct timespec *);
|
||||
|
||||
/* Set the time in the given timespec to zero. */
|
||||
void pv_elapsedtime_zero(struct timespec *);
|
||||
|
||||
/* Copy the second timespec into the first. Analogous to strcpy(3). */
|
||||
void pv_elapsedtime_copy(struct timespec *, const struct timespec *);
|
||||
|
||||
/*
|
||||
* Return -1, 0, or 1 depending on whether the first time is earlier than,
|
||||
* equal to, or later than the second time. Analogous to strcmp(3).
|
||||
*/
|
||||
int pv_elapsedtime_compare(const struct timespec *, const struct timespec *);
|
||||
|
||||
/* Add the latter two timespecs and store them in the first timespec. */
|
||||
void pv_elapsedtime_add(struct timespec *, const struct timespec *, const struct timespec *);
|
||||
|
||||
/* Add a number of nanoseconds to the given timespec. */
|
||||
void pv_elapsedtime_add_nsec(struct timespec *, long long);
|
||||
|
||||
/* Set the first timespec to the second minus the third. */
|
||||
void pv_elapsedtime_subtract(struct timespec *, const struct timespec *, const struct timespec *);
|
||||
|
||||
/* Convert a timespec to seconds. */
|
||||
long double pv_elapsedtime_seconds(const struct timespec *);
|
||||
|
||||
|
||||
/*
|
||||
* Main PV functions.
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Functions relating to elapsed time.
|
||||
*
|
||||
* Copyright 2023 Andrew Wood
|
||||
*
|
||||
* Distributed under the Artistic License v2.0; see `doc/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/*
|
||||
* Read the current elapsed time, relative to an unspecified point in the
|
||||
* past, and store it in the given timespec buffer. The time is guaranteed
|
||||
* to not go backwards and does not count time when the system was
|
||||
* suspended. See clock_gettime(2) with CLOCK_MONOTONIC.
|
||||
*
|
||||
* The read should not fail; if it does, the program is aborted with exit
|
||||
* status 16.
|
||||
*/
|
||||
void pv_elapsedtime_read(struct timespec *return_time)
|
||||
{
|
||||
if (0 != clock_gettime(CLOCK_MONOTONIC, return_time)) {
|
||||
fprintf(stderr, "%s: %s: %s\n", PACKAGE_NAME, "clock_gettime", strerror(errno));
|
||||
exit(16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the time in the given timespec to zero.
|
||||
*/
|
||||
void pv_elapsedtime_zero(struct timespec *zero_time)
|
||||
{
|
||||
if (NULL == zero_time)
|
||||
return;
|
||||
zero_time->tv_sec = 0;
|
||||
zero_time->tv_nsec = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copy source_time into dest_time. Analogous to strcpy(3).
|
||||
*/
|
||||
void pv_elapsedtime_copy(struct timespec *dest_time, const struct timespec *source_time)
|
||||
{
|
||||
if (NULL == dest_time)
|
||||
return;
|
||||
if (NULL == source_time)
|
||||
return;
|
||||
dest_time->tv_sec = source_time->tv_sec;
|
||||
dest_time->tv_nsec = source_time->tv_nsec;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return -1, 0, or 1 depending on whether the first time is earlier than,
|
||||
* equal to, or later than the second time. Analogous to strcmp(3).
|
||||
*/
|
||||
int pv_elapsedtime_compare(const struct timespec *first_time, const struct timespec *second_time)
|
||||
{
|
||||
/* Treat NULL as a zero time. */
|
||||
if ((NULL == first_time) && (NULL == second_time))
|
||||
return 0;
|
||||
if ((NULL == first_time) && (NULL != second_time))
|
||||
return -1;
|
||||
if ((NULL != first_time) && (NULL == second_time))
|
||||
return 1;
|
||||
|
||||
/* Check the seconds part, first */
|
||||
if (first_time->tv_sec < second_time->tv_sec)
|
||||
return -1;
|
||||
if (first_time->tv_sec > second_time->tv_sec)
|
||||
return 1;
|
||||
|
||||
/* Seconds are equal - compare nanoseconds. */
|
||||
if (first_time->tv_nsec < second_time->tv_nsec)
|
||||
return -1;
|
||||
if (first_time->tv_nsec > second_time->tv_nsec)
|
||||
return 1;
|
||||
|
||||
/* Nanoseconds are also equal - times are equal. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add first_time and second_time, writing the result to return_time.
|
||||
*/
|
||||
void pv_elapsedtime_add(struct timespec *return_time, const struct timespec *first_time,
|
||||
const struct timespec *second_time)
|
||||
{
|
||||
long long seconds, nanoseconds;
|
||||
|
||||
if (NULL == return_time)
|
||||
return;
|
||||
|
||||
seconds = 0;
|
||||
nanoseconds = 0;
|
||||
|
||||
if (NULL != first_time) {
|
||||
seconds += first_time->tv_sec;
|
||||
nanoseconds += first_time->tv_nsec;
|
||||
}
|
||||
|
||||
if (NULL != second_time) {
|
||||
seconds += second_time->tv_sec;
|
||||
nanoseconds += second_time->tv_nsec;
|
||||
}
|
||||
|
||||
seconds += nanoseconds / 1000000000;
|
||||
nanoseconds = nanoseconds % 1000000000;
|
||||
|
||||
return_time->tv_sec = seconds;
|
||||
return_time->tv_nsec = nanoseconds;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add a number of nanoseconds to the given timespec.
|
||||
*/
|
||||
void pv_elapsedtime_add_nsec(struct timespec *return_time, long long add_nanoseconds)
|
||||
{
|
||||
long long seconds, nanoseconds;
|
||||
|
||||
if (NULL == return_time)
|
||||
return;
|
||||
|
||||
seconds = return_time->tv_sec;
|
||||
nanoseconds = return_time->tv_nsec + add_nanoseconds;
|
||||
|
||||
seconds += nanoseconds / 1000000000;
|
||||
nanoseconds = nanoseconds % 1000000000;
|
||||
|
||||
return_time->tv_sec = seconds;
|
||||
return_time->tv_nsec = nanoseconds;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the return timespec to the first time minus the second time.
|
||||
*/
|
||||
void pv_elapsedtime_subtract(struct timespec *return_time, const struct timespec *first_time,
|
||||
const struct timespec *second_time)
|
||||
{
|
||||
long long seconds, nanoseconds;
|
||||
|
||||
if (NULL == return_time)
|
||||
return;
|
||||
|
||||
seconds = 0;
|
||||
nanoseconds = 0;
|
||||
|
||||
if (NULL != first_time) {
|
||||
seconds += first_time->tv_sec;
|
||||
nanoseconds += first_time->tv_nsec;
|
||||
}
|
||||
|
||||
if (NULL != second_time) {
|
||||
seconds -= second_time->tv_sec;
|
||||
nanoseconds -= second_time->tv_nsec;
|
||||
}
|
||||
|
||||
seconds += nanoseconds / 1000000000;
|
||||
nanoseconds = nanoseconds % 1000000000;
|
||||
|
||||
if (nanoseconds < 0) {
|
||||
seconds--;
|
||||
nanoseconds = 1000000000 + nanoseconds;
|
||||
}
|
||||
|
||||
return_time->tv_sec = seconds;
|
||||
return_time->tv_nsec = nanoseconds;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a timespec to seconds.
|
||||
*/
|
||||
long double pv_elapsedtime_seconds(const struct timespec *elapsed_time)
|
||||
{
|
||||
long double seconds;
|
||||
|
||||
if (NULL == elapsed_time)
|
||||
return 0.0;
|
||||
|
||||
seconds = (long double) elapsed_time->tv_sec;
|
||||
seconds += (long double) (elapsed_time->tv_nsec) / 1000000000.0L;
|
||||
|
||||
return seconds;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
+140
-163
@@ -26,24 +26,6 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
/*
|
||||
* Add the given number of microseconds (which may be negative) to the given
|
||||
* timeval.
|
||||
*/
|
||||
static void pv_timeval_add_usec(struct timeval *val, long usec)
|
||||
{
|
||||
val->tv_usec += usec;
|
||||
while (val->tv_usec < 0) {
|
||||
val->tv_sec--;
|
||||
val->tv_usec += 1000000;
|
||||
}
|
||||
while (val->tv_usec >= 1000000) {
|
||||
val->tv_sec++;
|
||||
val->tv_usec -= 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Pipe data from a list of files to standard output, giving information
|
||||
* about the transfer on standard error according to the given options.
|
||||
@@ -53,12 +35,12 @@ static void pv_timeval_add_usec(struct timeval *val, long usec)
|
||||
int pv_main_loop(pvstate_t state)
|
||||
{
|
||||
long written, lineswritten;
|
||||
long long total_written, since_last, cansend;
|
||||
long long total_written, transferred_since_last, cansend;
|
||||
long double target;
|
||||
int eof_in, eof_out, final_update;
|
||||
struct timeval start_time, next_update, next_ratecheck, cur_time;
|
||||
struct timeval init_time, next_remotecheck;
|
||||
long double elapsed;
|
||||
struct timespec start_time, next_update, next_ratecheck, cur_time;
|
||||
struct timespec init_time, next_remotecheck, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
struct stat sb;
|
||||
int fd, file_idx;
|
||||
|
||||
@@ -71,8 +53,9 @@ int pv_main_loop(pvstate_t state)
|
||||
* "total_written" is the total bytes written since the start,
|
||||
* or in line mode, the total lines written since the start.
|
||||
*
|
||||
* "since_last" is the bytes written since the last display,
|
||||
* or in line mode, the lines written since the last display.
|
||||
* "transferred_since_last" is the bytes written since the last
|
||||
* display, or in line mode, the lines written since the last
|
||||
* display.
|
||||
*
|
||||
* The remaining variables are all unchanged by linemode.
|
||||
*/
|
||||
@@ -84,26 +67,22 @@ int pv_main_loop(pvstate_t state)
|
||||
eof_in = 0;
|
||||
eof_out = 0;
|
||||
total_written = 0;
|
||||
since_last = 0;
|
||||
transferred_since_last = 0;
|
||||
state->initial_offset = 0;
|
||||
|
||||
gettimeofday(&start_time, NULL);
|
||||
gettimeofday(&cur_time, NULL);
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_copy(&start_time, &cur_time);
|
||||
|
||||
next_update.tv_sec = start_time.tv_sec;
|
||||
next_update.tv_usec = start_time.tv_usec;
|
||||
pv_elapsedtime_copy(&next_ratecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_remotecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
if ((state->delay_start > 0)
|
||||
&& (state->delay_start > state->interval)) {
|
||||
pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->delay_start));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->delay_start));
|
||||
} else {
|
||||
pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
}
|
||||
|
||||
next_ratecheck.tv_sec = start_time.tv_sec;
|
||||
next_ratecheck.tv_usec = start_time.tv_usec;
|
||||
next_remotecheck.tv_sec = start_time.tv_sec;
|
||||
next_remotecheck.tv_usec = start_time.tv_usec;
|
||||
|
||||
target = 0;
|
||||
final_update = 0;
|
||||
file_idx = 0;
|
||||
@@ -159,29 +138,26 @@ int pv_main_loop(pvstate_t state)
|
||||
cansend = 0;
|
||||
|
||||
/*
|
||||
* Check for remote messages from -R every short while
|
||||
* Check for remote messages from -R every short while.
|
||||
*/
|
||||
if ((cur_time.tv_sec > next_remotecheck.tv_sec)
|
||||
|| (cur_time.tv_sec == next_remotecheck.tv_sec && cur_time.tv_usec >= next_remotecheck.tv_usec)) {
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_remotecheck) > 0) {
|
||||
pv_remote_check(state);
|
||||
pv_timeval_add_usec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
}
|
||||
|
||||
if (state->pv_sig_abort)
|
||||
break;
|
||||
|
||||
if (state->rate_limit > 0) {
|
||||
gettimeofday(&cur_time, NULL);
|
||||
if ((cur_time.tv_sec > next_ratecheck.tv_sec)
|
||||
|| (cur_time.tv_sec == next_ratecheck.tv_sec && cur_time.tv_usec >= next_ratecheck.tv_usec)) {
|
||||
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_ratecheck) > 0) {
|
||||
target +=
|
||||
((long double) (state->rate_limit)) / (long double) (1000000 / RATE_GRANULARITY);
|
||||
long double burstMax = ((long double) (state->rate_limit * RATE_BURST_WINDOW));
|
||||
if (target > burstMax) {
|
||||
target = burstMax;
|
||||
((long double) (state->rate_limit)) / (long double) (1000000000.0 / RATE_GRANULARITY);
|
||||
long double burst_max = ((long double) (state->rate_limit * RATE_BURST_WINDOW));
|
||||
if (target > burst_max) {
|
||||
target = burst_max;
|
||||
}
|
||||
pv_timeval_add_usec(&next_ratecheck, RATE_GRANULARITY);
|
||||
pv_elapsedtime_add_nsec(&next_ratecheck, RATE_GRANULARITY);
|
||||
}
|
||||
cansend = target;
|
||||
}
|
||||
@@ -216,12 +192,12 @@ int pv_main_loop(pvstate_t state)
|
||||
}
|
||||
|
||||
if (state->linemode) {
|
||||
since_last += lineswritten;
|
||||
transferred_since_last += lineswritten;
|
||||
total_written += lineswritten;
|
||||
if (state->rate_limit > 0)
|
||||
target -= lineswritten;
|
||||
} else {
|
||||
since_last += written;
|
||||
transferred_since_last += written;
|
||||
total_written += written;
|
||||
if (state->rate_limit > 0)
|
||||
target -= written;
|
||||
@@ -239,15 +215,19 @@ int pv_main_loop(pvstate_t state)
|
||||
}
|
||||
}
|
||||
|
||||
gettimeofday(&cur_time, NULL);
|
||||
/* Now check the current time. */
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
/* If full EOF, final update, and force a display updaate. */
|
||||
if (eof_in && eof_out) {
|
||||
final_update = 1;
|
||||
if ((state->display_visible)
|
||||
|| (0 == state->delay_start))
|
||||
next_update.tv_sec = cur_time.tv_sec - 1;
|
||||
|| (0 == state->delay_start)) {
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
}
|
||||
}
|
||||
|
||||
/* Just go round the loop again if there's no display. */
|
||||
if (state->no_display)
|
||||
continue;
|
||||
|
||||
@@ -258,6 +238,7 @@ int pv_main_loop(pvstate_t state)
|
||||
* was received.
|
||||
*/
|
||||
if (state->wait) {
|
||||
/* Restart the loop if nothing written yet. */
|
||||
if (state->linemode) {
|
||||
if (lineswritten < 1)
|
||||
continue;
|
||||
@@ -279,47 +260,47 @@ int pv_main_loop(pvstate_t state)
|
||||
* SIGTSTOP so things don't mess up.
|
||||
*/
|
||||
pv_sig_nopause();
|
||||
gettimeofday(&start_time, NULL);
|
||||
state->pv_sig_toffset.tv_sec = 0;
|
||||
state->pv_sig_toffset.tv_usec = 0;
|
||||
pv_elapsedtime_read(&start_time);
|
||||
pv_elapsedtime_zero(&(state->pv_sig_toffset));
|
||||
pv_sig_allowpause();
|
||||
|
||||
next_update.tv_sec = start_time.tv_sec;
|
||||
next_update.tv_usec = start_time.tv_usec;
|
||||
pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval));
|
||||
/*
|
||||
* Start the display, but only at the next interval,
|
||||
* not immediately.
|
||||
*/
|
||||
pv_elapsedtime_copy(&next_update, &start_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
}
|
||||
|
||||
if ((cur_time.tv_sec < next_update.tv_sec)
|
||||
|| (cur_time.tv_sec == next_update.tv_sec && cur_time.tv_usec < next_update.tv_usec)) {
|
||||
/* Restart the loop if it's not time to update the display. */
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
if (next_update.tv_sec < cur_time.tv_sec) {
|
||||
next_update.tv_sec = cur_time.tv_sec;
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
} else if (next_update.tv_sec == cur_time.tv_sec && next_update.tv_usec < cur_time.tv_usec) {
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
}
|
||||
/* Set the "next update" time to now, if it's in the past. */
|
||||
if (pv_elapsedtime_compare(&next_update, &cur_time) < 0)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
init_time.tv_sec = start_time.tv_sec + state->pv_sig_toffset.tv_sec;
|
||||
init_time.tv_usec = start_time.tv_usec + state->pv_sig_toffset.tv_usec;
|
||||
if (init_time.tv_usec >= 1000000) {
|
||||
init_time.tv_sec++;
|
||||
init_time.tv_usec -= 1000000;
|
||||
}
|
||||
if (init_time.tv_usec < 0) {
|
||||
init_time.tv_sec--;
|
||||
init_time.tv_usec += 1000000;
|
||||
}
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
pv_elapsedtime_add(&init_time, &start_time, &(state->pv_sig_toffset));
|
||||
|
||||
elapsed = cur_time.tv_sec - init_time.tv_sec;
|
||||
elapsed += (cur_time.tv_usec - init_time.tv_usec) / 1000000.0;
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
* time minus effective start time.
|
||||
*/
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &init_time);
|
||||
|
||||
elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
if (final_update)
|
||||
since_last = -1;
|
||||
transferred_since_last = -1;
|
||||
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
if (state->pv_sig_newsize) {
|
||||
unsigned int new_width, new_height;
|
||||
|
||||
@@ -335,9 +316,9 @@ int pv_main_loop(pvstate_t state)
|
||||
state->height = new_height;
|
||||
}
|
||||
|
||||
pv_display(state, elapsed, since_last, total_written);
|
||||
pv_display(state, elapsed_seconds, transferred_since_last, total_written);
|
||||
|
||||
since_last = 0;
|
||||
transferred_since_last = 0;
|
||||
}
|
||||
|
||||
if (state->cursor) {
|
||||
@@ -368,10 +349,10 @@ int pv_main_loop(pvstate_t state)
|
||||
int pv_watchfd_loop(pvstate_t state)
|
||||
{
|
||||
struct pvwatchfd_s info;
|
||||
long long position_now, total_written, since_last;
|
||||
struct timeval next_update, cur_time;
|
||||
struct timeval init_time, next_remotecheck;
|
||||
long double elapsed;
|
||||
long long position_now, total_written, transferred_since_last;
|
||||
struct timespec next_update, cur_time;
|
||||
struct timespec init_time, next_remotecheck, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
int ended;
|
||||
int first_check;
|
||||
int rc;
|
||||
@@ -401,29 +382,24 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
}
|
||||
}
|
||||
|
||||
gettimeofday(&(info.start_time), NULL);
|
||||
gettimeofday(&cur_time, NULL);
|
||||
|
||||
next_update.tv_sec = info.start_time.tv_sec;
|
||||
next_update.tv_usec = info.start_time.tv_usec;
|
||||
pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval));
|
||||
|
||||
next_remotecheck.tv_sec = info.start_time.tv_sec;
|
||||
next_remotecheck.tv_usec = info.start_time.tv_usec;
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_copy(&(info.start_time), &cur_time);
|
||||
pv_elapsedtime_copy(&next_remotecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
ended = 0;
|
||||
total_written = 0;
|
||||
since_last = 0;
|
||||
transferred_since_last = 0;
|
||||
first_check = 1;
|
||||
|
||||
while (!ended) {
|
||||
/*
|
||||
* Check for remote messages from -R every short while
|
||||
* Check for remote messages from -R every short while.
|
||||
*/
|
||||
if ((cur_time.tv_sec > next_remotecheck.tv_sec)
|
||||
|| (cur_time.tv_sec == next_remotecheck.tv_sec && cur_time.tv_usec >= next_remotecheck.tv_usec)) {
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_remotecheck) > 0) {
|
||||
pv_remote_check(state);
|
||||
pv_timeval_add_usec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
}
|
||||
|
||||
if (state->pv_sig_abort)
|
||||
@@ -434,7 +410,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
if (position_now < 0) {
|
||||
ended = 1;
|
||||
} else {
|
||||
since_last += position_now - total_written;
|
||||
transferred_since_last += position_now - total_written;
|
||||
total_written = position_now;
|
||||
if (first_check) {
|
||||
state->initial_offset = position_now;
|
||||
@@ -442,15 +418,19 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
}
|
||||
}
|
||||
|
||||
gettimeofday(&cur_time, NULL);
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
/* Ended - force a display update. */
|
||||
if (ended) {
|
||||
ended = 1;
|
||||
next_update.tv_sec = cur_time.tv_sec - 1;
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
}
|
||||
|
||||
if ((cur_time.tv_sec < next_update.tv_sec)
|
||||
|| (cur_time.tv_sec == next_update.tv_sec && cur_time.tv_usec < next_update.tv_usec)) {
|
||||
/*
|
||||
* Restart the loop after a brief delay, if it's not time to
|
||||
* update the display.
|
||||
*/
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 50000;
|
||||
@@ -458,32 +438,30 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
if (next_update.tv_sec < cur_time.tv_sec) {
|
||||
next_update.tv_sec = cur_time.tv_sec;
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
} else if (next_update.tv_sec == cur_time.tv_sec && next_update.tv_usec < cur_time.tv_usec) {
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
}
|
||||
/* Set the "next update" time to now, if it's in the past. */
|
||||
if (pv_elapsedtime_compare(&next_update, &cur_time) < 0)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
init_time.tv_sec = info.start_time.tv_sec + state->pv_sig_toffset.tv_sec;
|
||||
init_time.tv_usec = info.start_time.tv_usec + state->pv_sig_toffset.tv_usec;
|
||||
if (init_time.tv_usec >= 1000000) {
|
||||
init_time.tv_sec++;
|
||||
init_time.tv_usec -= 1000000;
|
||||
}
|
||||
if (init_time.tv_usec < 0) {
|
||||
init_time.tv_sec--;
|
||||
init_time.tv_usec += 1000000;
|
||||
}
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
pv_elapsedtime_add(&init_time, &(info.start_time), &(state->pv_sig_toffset));
|
||||
|
||||
elapsed = cur_time.tv_sec - init_time.tv_sec;
|
||||
elapsed += (cur_time.tv_usec - init_time.tv_usec) / 1000000.0;
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
* time minus effective start time.
|
||||
*/
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &init_time);
|
||||
|
||||
elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
if (ended)
|
||||
since_last = -1;
|
||||
transferred_since_last = -1;
|
||||
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
if (state->pv_sig_newsize) {
|
||||
unsigned int new_width, new_height;
|
||||
|
||||
@@ -499,9 +477,9 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
state->height = new_height;
|
||||
}
|
||||
|
||||
pv_display(state, elapsed, since_last, total_written);
|
||||
pv_display(state, elapsed_seconds, transferred_since_last, total_written);
|
||||
|
||||
since_last = 0;
|
||||
transferred_since_last = 0;
|
||||
}
|
||||
|
||||
if (!state->numeric)
|
||||
@@ -530,7 +508,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
struct pvstate_s *state_array = NULL;
|
||||
int array_length = 0;
|
||||
int fd_to_idx[FD_SETSIZE] = { 0, };
|
||||
struct timeval next_update, cur_time;
|
||||
struct timespec next_update, cur_time;
|
||||
int idx;
|
||||
int prev_displayed_lines, blank_lines;
|
||||
int first_pass = 1;
|
||||
@@ -570,11 +548,9 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
* Get things ready for the main loop.
|
||||
*/
|
||||
|
||||
gettimeofday(&cur_time, NULL);
|
||||
|
||||
next_update.tv_sec = cur_time.tv_sec;
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
for (idx = 0; idx < FD_SETSIZE; idx++) {
|
||||
fd_to_idx[idx] = -1;
|
||||
@@ -588,7 +564,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
if (state->pv_sig_abort)
|
||||
break;
|
||||
|
||||
gettimeofday(&cur_time, NULL);
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
if (kill(state->watch_pid, 0) != 0) {
|
||||
if (first_pass) {
|
||||
@@ -603,8 +579,11 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((cur_time.tv_sec < next_update.tv_sec)
|
||||
|| (cur_time.tv_sec == next_update.tv_sec && cur_time.tv_usec < next_update.tv_usec)) {
|
||||
/*
|
||||
* Restart the loop after a brief delay, if it's not time to
|
||||
* update the display.
|
||||
*/
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 50000;
|
||||
@@ -612,15 +591,13 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
if (next_update.tv_sec < cur_time.tv_sec) {
|
||||
next_update.tv_sec = cur_time.tv_sec;
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
} else if (next_update.tv_sec == cur_time.tv_sec && next_update.tv_usec < cur_time.tv_usec) {
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
}
|
||||
/* Set the "next update" time to now, if it's in the past. */
|
||||
if (pv_elapsedtime_compare(&next_update, &cur_time) < 0)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
if (state->pv_sig_newsize) {
|
||||
state->pv_sig_newsize = 0;
|
||||
pv_screensize(&(state->width), &(state->height));
|
||||
@@ -651,9 +628,9 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
displayed_lines = 0;
|
||||
|
||||
for (fd = 0; fd < FD_SETSIZE; fd++) {
|
||||
long long position_now, since_last;
|
||||
struct timeval init_time;
|
||||
long double elapsed;
|
||||
long long position_now, transferred_since_last;
|
||||
struct timespec init_time, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
|
||||
if (displayed_lines >= (int) (state->height))
|
||||
break;
|
||||
@@ -689,31 +666,31 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
since_last = position_now - info_array[idx].position;
|
||||
transferred_since_last = position_now - info_array[idx].position;
|
||||
info_array[idx].position = position_now;
|
||||
|
||||
init_time.tv_sec = info_array[idx].start_time.tv_sec + state->pv_sig_toffset.tv_sec;
|
||||
init_time.tv_usec = info_array[idx].start_time.tv_usec + state->pv_sig_toffset.tv_usec;
|
||||
if (init_time.tv_usec >= 1000000) {
|
||||
init_time.tv_sec++;
|
||||
init_time.tv_usec -= 1000000;
|
||||
}
|
||||
if (init_time.tv_usec < 0) {
|
||||
init_time.tv_sec--;
|
||||
init_time.tv_usec += 1000000;
|
||||
}
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
pv_elapsedtime_add(&init_time, &(info_array[idx].start_time), &(state->pv_sig_toffset));
|
||||
|
||||
elapsed = cur_time.tv_sec - init_time.tv_sec;
|
||||
elapsed += (cur_time.tv_usec - init_time.tv_usec) / 1000000.0;
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
* time minus effective start time.
|
||||
*/
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &init_time);
|
||||
|
||||
elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
if (displayed_lines > 0) {
|
||||
debug("%s", "adding newline");
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
|
||||
debug("%s %d [%d]: %Lf / %Ld / %Ld", "fd", fd, idx, elapsed, since_last, position_now);
|
||||
debug("%s %d [%d]: %Lf / %Ld / %Ld", "fd", fd, idx, elapsed_seconds, transferred_since_last, position_now);
|
||||
|
||||
pv_display(&(state_array[idx]), elapsed, since_last, position_now);
|
||||
pv_display(&(state_array[idx]), elapsed_seconds, transferred_since_last, position_now);
|
||||
displayed_lines++;
|
||||
}
|
||||
|
||||
|
||||
+14
-20
@@ -12,7 +12,6 @@
|
||||
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -55,7 +54,7 @@ static void pv_sig_ttou( __attribute__((unused))
|
||||
static void pv_sig_tstp( __attribute__((unused))
|
||||
int s)
|
||||
{
|
||||
gettimeofday(&(pv_sig_state->pv_sig_tstp_time), NULL);
|
||||
pv_elapsedtime_read(&(pv_sig_state->pv_sig_tstp_time));
|
||||
raise(SIGSTOP);
|
||||
}
|
||||
|
||||
@@ -68,11 +67,13 @@ static void pv_sig_tstp( __attribute__((unused))
|
||||
static void pv_sig_cont( __attribute__((unused))
|
||||
int s)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timespec current_time;
|
||||
struct timespec time_spent_stopped;
|
||||
struct termios t;
|
||||
|
||||
pv_sig_state->pv_sig_newsize = 1;
|
||||
|
||||
/* if this SIGCONT didn't follow a SIGTSTP so we have no stop time */
|
||||
if (0 == pv_sig_state->pv_sig_tstp_time.tv_sec) {
|
||||
tcgetattr(STDERR_FILENO, &t);
|
||||
t.c_lflag |= TOSTOP;
|
||||
@@ -83,21 +84,16 @@ static void pv_sig_cont( __attribute__((unused))
|
||||
return;
|
||||
}
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
pv_elapsedtime_read(¤t_time);
|
||||
|
||||
pv_sig_state->pv_sig_toffset.tv_sec += (tv.tv_sec - pv_sig_state->pv_sig_tstp_time.tv_sec);
|
||||
pv_sig_state->pv_sig_toffset.tv_usec += (tv.tv_usec - pv_sig_state->pv_sig_tstp_time.tv_usec);
|
||||
if (pv_sig_state->pv_sig_toffset.tv_usec >= 1000000) {
|
||||
pv_sig_state->pv_sig_toffset.tv_sec++;
|
||||
pv_sig_state->pv_sig_toffset.tv_usec -= 1000000;
|
||||
}
|
||||
if (pv_sig_state->pv_sig_toffset.tv_usec < 0) {
|
||||
pv_sig_state->pv_sig_toffset.tv_sec--;
|
||||
pv_sig_state->pv_sig_toffset.tv_usec += 1000000;
|
||||
}
|
||||
/* time spent stopped = current time - time SIGTSTP received */
|
||||
pv_elapsedtime_subtract(&time_spent_stopped, ¤t_time, &(pv_sig_state->pv_sig_tstp_time));
|
||||
|
||||
pv_sig_state->pv_sig_tstp_time.tv_sec = 0;
|
||||
pv_sig_state->pv_sig_tstp_time.tv_usec = 0;
|
||||
/* add time spent stopped the total stopped-time count */
|
||||
pv_elapsedtime_add(&(pv_sig_state->pv_sig_toffset), &(pv_sig_state->pv_sig_toffset), &time_spent_stopped);
|
||||
|
||||
/* reset the SIGTSTP receipt time */
|
||||
pv_elapsedtime_zero(&(pv_sig_state->pv_sig_tstp_time));
|
||||
|
||||
if (pv_sig_state->pv_sig_old_stderr != -1) {
|
||||
dup2(pv_sig_state->pv_sig_old_stderr, STDERR_FILENO);
|
||||
@@ -145,10 +141,8 @@ void pv_sig_init(pvstate_t state)
|
||||
pv_sig_state = state;
|
||||
|
||||
pv_sig_state->pv_sig_old_stderr = -1;
|
||||
pv_sig_state->pv_sig_tstp_time.tv_sec = 0;
|
||||
pv_sig_state->pv_sig_tstp_time.tv_usec = 0;
|
||||
pv_sig_state->pv_sig_toffset.tv_sec = 0;
|
||||
pv_sig_state->pv_sig_toffset.tv_usec = 0;
|
||||
pv_elapsedtime_zero(&(pv_sig_state->pv_sig_tstp_time));
|
||||
pv_elapsedtime_zero(&(pv_sig_state->pv_sig_toffset));
|
||||
|
||||
/*
|
||||
* Ignore SIGPIPE, so we don't die if stdout is a pipe and the other
|
||||
|
||||
+25
-21
@@ -32,21 +32,21 @@
|
||||
* buffer as full as we can.
|
||||
*
|
||||
* We stop retrying if the time elapsed since this function was entered
|
||||
* reaches TRANSFER_READ_TIMEOUT microseconds.
|
||||
* reaches TRANSFER_READ_TIMEOUT seconds.
|
||||
*/
|
||||
static ssize_t pv__transfer_read_repeated(int fd, void *buf, size_t count)
|
||||
{
|
||||
struct timeval start_time;
|
||||
struct timespec start_time;
|
||||
ssize_t total_read;
|
||||
|
||||
gettimeofday(&start_time, NULL);
|
||||
pv_elapsedtime_read(&start_time);
|
||||
|
||||
total_read = 0;
|
||||
|
||||
while (count > 0) {
|
||||
ssize_t nread;
|
||||
struct timeval now;
|
||||
long elapsed_usec;
|
||||
struct timespec cur_time, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
|
||||
nread = read(fd, buf, count > MAX_READ_AT_ONCE ? MAX_READ_AT_ONCE : count);
|
||||
if (nread < 0)
|
||||
@@ -59,11 +59,13 @@ static ssize_t pv__transfer_read_repeated(int fd, void *buf, size_t count)
|
||||
if (0 == nread)
|
||||
return total_read;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
elapsed_usec = 1000000 * (now.tv_sec - start_time.tv_sec) + (now.tv_usec - start_time.tv_usec);
|
||||
if (elapsed_usec > TRANSFER_READ_TIMEOUT) {
|
||||
debug("%s %d: %s (%ld %s)", "fd", fd,
|
||||
"stopping read - timer expired", elapsed_usec, "usec elapsed");
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &start_time);
|
||||
elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
if (elapsed_seconds > TRANSFER_READ_TIMEOUT) {
|
||||
debug("%s %d: %s (%lf %s)", "fd", fd,
|
||||
"stopping read - timer expired", elapsed_seconds, "sec elapsed");
|
||||
return total_read;
|
||||
}
|
||||
|
||||
@@ -100,21 +102,21 @@ static ssize_t pv__transfer_read_repeated(int fd, void *buf, size_t count)
|
||||
* fsync() if _POSIX_SYNCHRONIZED_IO is not > 0).
|
||||
*
|
||||
* We stop retrying if the time elapsed since this function was entered
|
||||
* reaches TRANSFER_WRITE_TIMEOUT microseconds.
|
||||
* reaches TRANSFER_WRITE_TIMEOUT seconds.
|
||||
*/
|
||||
static ssize_t pv__transfer_write_repeated(int fd, void *buf, size_t count, bool sync_after_write)
|
||||
{
|
||||
struct timeval start_time;
|
||||
struct timespec start_time;
|
||||
ssize_t total_written;
|
||||
|
||||
gettimeofday(&start_time, NULL);
|
||||
pv_elapsedtime_read(&start_time);
|
||||
|
||||
total_written = 0;
|
||||
|
||||
while (count > 0) {
|
||||
ssize_t nwritten;
|
||||
struct timeval now;
|
||||
long elapsed_usec;
|
||||
struct timespec cur_time, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
size_t asked_to_write;
|
||||
|
||||
asked_to_write = count > MAX_WRITE_AT_ONCE ? MAX_WRITE_AT_ONCE : count;
|
||||
@@ -163,11 +165,13 @@ static ssize_t pv__transfer_write_repeated(int fd, void *buf, size_t count, bool
|
||||
if (0 == nwritten)
|
||||
return total_written;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
elapsed_usec = 1000000 * (now.tv_sec - start_time.tv_sec) + (now.tv_usec - start_time.tv_usec);
|
||||
if (elapsed_usec > TRANSFER_WRITE_TIMEOUT) {
|
||||
debug("%s %d: %s (%ld %s)", "fd", fd,
|
||||
"stopping write - timer expired", elapsed_usec, "usec elapsed");
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &start_time);
|
||||
elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
if (elapsed_seconds > TRANSFER_WRITE_TIMEOUT) {
|
||||
debug("%s %d: %s (%lf %s)", "fd", fd,
|
||||
"stopping write - timer expired", elapsed_seconds, "sec elapsed");
|
||||
return total_written;
|
||||
}
|
||||
|
||||
@@ -175,7 +179,7 @@ static ssize_t pv__transfer_write_repeated(int fd, void *buf, size_t count, bool
|
||||
* Running the select() here seems to make PV eat a lot of
|
||||
* CPU in some cases, so instead we just go round the loop
|
||||
* again and rely on our alarm() to interrupt us if we run
|
||||
* out of time - also on our gettimeofday() check.
|
||||
* out of time - also on our elapsed time check.
|
||||
*/
|
||||
if (count > 0) {
|
||||
#if 0 /* disabled after 1.6.0 - see comment above */
|
||||
|
||||
+1
-1
@@ -440,7 +440,7 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
|
||||
state_array[use_idx].reparse_display = 1;
|
||||
|
||||
gettimeofday(&(info_array[use_idx].start_time), NULL);
|
||||
pv_elapsedtime_read(&(info_array[use_idx].start_time));
|
||||
|
||||
state_array[use_idx].initial_offset = 0;
|
||||
info_array[use_idx].position = 0;
|
||||
|
||||
Reference in New Issue
Block a user