Add an option "-J" / "--pipe-buffer-size" to set the size of the output pipe buffer when the output is a pipe, and when that option is not specified, automatically increase the output pipe buffer size to match that of the input, when the first input is also a pipe (#188).
This commit is contained in:
@@ -291,6 +291,14 @@ automatically switches on \*(lq\fB\-\-no\-splice\fR\*(rq.
|
|||||||
Switching on this option results in a small loss of transfer efficiency.
|
Switching on this option results in a small loss of transfer efficiency.
|
||||||
It has no effect on systems where \fBsplice\fR(2) is unavailable.
|
It has no effect on systems where \fBsplice\fR(2) is unavailable.
|
||||||
.TP
|
.TP
|
||||||
|
.BI \-J\ BYTES \fR,\ \fB\-\-pipe\-buffer\-size\ BYTES
|
||||||
|
Attempt to set the size of the output pipe buffer to \fIBYTES\fR bytes.
|
||||||
|
This will only have an effect if the output is a pipe, and will silently do
|
||||||
|
nothing if the requested size cannot be achieved.
|
||||||
|
If this option is not specified, and both the output and the first input are
|
||||||
|
pipes, then the output pipe buffer size will automatically be increased to
|
||||||
|
match the input pipe buffer, if it was smaller.
|
||||||
|
.TP
|
||||||
.B \-E, \-\-skip-errors
|
.B \-E, \-\-skip-errors
|
||||||
Ignore read errors by attempting to skip past the offending sections.
|
Ignore read errors by attempting to skip past the offending sections.
|
||||||
The corresponding parts of the output will be null bytes.
|
The corresponding parts of the output will be null bytes.
|
||||||
@@ -857,10 +865,10 @@ effective with small input files, and \*(lq\fB%nL\fR\*(rq may be a few lines
|
|||||||
out due to buffering within the pipeline itself.
|
out due to buffering within the pipeline itself.
|
||||||
.PP
|
.PP
|
||||||
Numbers passed to \*(lq\fB\-\-size\fR\*(rq, \*(lq\fB\-\-rate\-limit\fR\*(rq,
|
Numbers passed to \*(lq\fB\-\-size\fR\*(rq, \*(lq\fB\-\-rate\-limit\fR\*(rq,
|
||||||
\*(lq\fB\-\-buffer\-size\fR\*(rq, and \*(lq\fB\-\-error\-skip\-block\fR\*(rq
|
\*(lq\fB\-\-buffer\-size\fR\*(rq, \*(lq\fB\-\-pipe\-buffer\-size\fR\*(rq,
|
||||||
may all be expressed as decimals if followed by a suffix, so for example
|
and \*(lq\fB\-\-error\-skip\-block\fR\*(rq may all be expressed as decimals
|
||||||
\*(lq\fI\-\-size\~1.5G\fR\*(rq is equivalent to
|
if followed by a suffix, so for example \*(lq\fI\-\-size\~1.5G\fR\*(rq is
|
||||||
\*(lq\fI\-\-size\~1536M\fR\*(rq.
|
equivalent to \*(lq\fI\-\-size\~1536M\fR\*(rq.
|
||||||
.PP
|
.PP
|
||||||
Numbers passed to \*(lq\fB\-\-interval\fR\*(rq and
|
Numbers passed to \*(lq\fB\-\-interval\fR\*(rq and
|
||||||
\*(lq\fB\-\-delay\-start\fR\*(rq may be integers or decimals, but may not
|
\*(lq\fB\-\-delay\-start\fR\*(rq may be integers or decimals, but may not
|
||||||
|
|||||||
+13
-3
@@ -300,6 +300,15 @@ are explicitly switched on will be shown.
|
|||||||
option results in a small loss of transfer efficiency. It has no
|
option results in a small loss of transfer efficiency. It has no
|
||||||
effect on systems where **splice**(2) is unavailable.
|
effect on systems where **splice**(2) is unavailable.
|
||||||
|
|
||||||
|
**-J BYTES, \--pipe-buffer-size BYTES**
|
||||||
|
|
||||||
|
: Attempt to set the size of the output pipe buffer to *BYTES* bytes.
|
||||||
|
This will only have an effect if the output is a pipe, and will
|
||||||
|
silently do nothing if the requested size cannot be achieved. If
|
||||||
|
this option is not specified, and both the output and the first
|
||||||
|
input are pipes, then the output pipe buffer size will automatically
|
||||||
|
be increased to match the input pipe buffer, if it was smaller.
|
||||||
|
|
||||||
**-E, \--skip-errors**
|
**-E, \--skip-errors**
|
||||||
|
|
||||||
: Ignore read errors by attempting to skip past the offending
|
: Ignore read errors by attempting to skip past the offending
|
||||||
@@ -814,9 +823,10 @@ small input files, and "**%nL**" may be a few lines out due to buffering
|
|||||||
within the pipeline itself.
|
within the pipeline itself.
|
||||||
|
|
||||||
Numbers passed to "**\--size**", "**\--rate-limit**",
|
Numbers passed to "**\--size**", "**\--rate-limit**",
|
||||||
"**\--buffer-size**", and "**\--error-skip-block**" may all be expressed
|
"**\--buffer-size**", "**\--pipe-buffer-size**", and
|
||||||
as decimals if followed by a suffix, so for example "*\--size 1.5G*" is
|
"**\--error-skip-block**" may all be expressed as decimals if followed
|
||||||
equivalent to "*\--size 1536M*".
|
by a suffix, so for example "*\--size 1.5G*" is equivalent to
|
||||||
|
"*\--size 1536M*".
|
||||||
|
|
||||||
Numbers passed to "**\--interval**" and "**\--delay-start**" may be
|
Numbers passed to "**\--interval**" and "**\--delay-start**" may be
|
||||||
integers or decimals, but may not have a suffix.
|
integers or decimals, but may not have a suffix.
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ struct opts_s {
|
|||||||
size_t lastwritten; /* show N bytes last written */
|
size_t lastwritten; /* show N bytes last written */
|
||||||
off_t rate_limit; /* rate limit, in bytes per second */
|
off_t rate_limit; /* rate limit, in bytes per second */
|
||||||
size_t buffer_size; /* buffer size, in bytes (0=default) */
|
size_t buffer_size; /* buffer size, in bytes (0=default) */
|
||||||
|
size_t pipe_buffer_size; /* pipe buffer size, in bytes (0=default) */
|
||||||
off_t size; /* total size of data */
|
off_t size; /* total size of data */
|
||||||
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
||||||
pid_t remote; /* PID of pv to update settings of */
|
pid_t remote; /* PID of pv to update settings of */
|
||||||
|
|||||||
@@ -201,7 +201,8 @@ struct pvstate_s {
|
|||||||
/*@null@*/ char *default_bar_style; /* which bar style to use by default */
|
/*@null@*/ char *default_bar_style; /* which bar style to use by default */
|
||||||
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
||||||
off_t rate_limit; /* rate limit, in bytes per second */
|
off_t rate_limit; /* rate limit, in bytes per second */
|
||||||
size_t target_buffer_size; /* buffer size (0=default) */
|
size_t target_buffer_size; /* transfer buffer size (0=default) */
|
||||||
|
size_t pipe_buffer_size; /* pipe buffer size (0=default) */
|
||||||
off_t size; /* total size of data */
|
off_t size; /* total size of data */
|
||||||
unsigned int skip_errors; /* skip read errors counter */
|
unsigned int skip_errors; /* skip read errors counter */
|
||||||
int output_fd; /* fd to write output to */
|
int output_fd; /* fd to write output to */
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ extern void pv_state_sparse_output_set(pvstate_t, bool);
|
|||||||
extern void pv_state_rate_limit_set(pvstate_t, off_t);
|
extern void pv_state_rate_limit_set(pvstate_t, off_t);
|
||||||
extern void pv_state_target_buffer_size_set(pvstate_t, size_t);
|
extern void pv_state_target_buffer_size_set(pvstate_t, size_t);
|
||||||
extern void pv_state_no_splice_set(pvstate_t, bool);
|
extern void pv_state_no_splice_set(pvstate_t, bool);
|
||||||
|
extern void pv_state_pipe_buffer_size_set(pvstate_t, size_t);
|
||||||
extern void pv_state_discard_input_set(pvstate_t, bool);
|
extern void pv_state_discard_input_set(pvstate_t, bool);
|
||||||
extern void pv_state_size_set(pvstate_t, off_t);
|
extern void pv_state_size_set(pvstate_t, off_t);
|
||||||
extern void pv_state_interval_set(pvstate_t, double);
|
extern void pv_state_interval_set(pvstate_t, double);
|
||||||
|
|||||||
@@ -400,6 +400,9 @@ void display_help(void)
|
|||||||
{ "-C", "--no-splice", NULL,
|
{ "-C", "--no-splice", NULL,
|
||||||
N_("never use splice(), always use read/write"),
|
N_("never use splice(), always use read/write"),
|
||||||
{ 0, 0, 0, 0} },
|
{ 0, 0, 0, 0} },
|
||||||
|
{ "-J", "--pipe-buffer-size", N_("BYTES"),
|
||||||
|
N_("set the pipe buffer size to BYTES"),
|
||||||
|
{ 0, 0, 0, 0} },
|
||||||
{ "-E", "--skip-errors", NULL,
|
{ "-E", "--skip-errors", NULL,
|
||||||
N_("skip read errors in input"),
|
N_("skip read errors in input"),
|
||||||
{ 0, 0, 0, 0} },
|
{ 0, 0, 0, 0} },
|
||||||
|
|||||||
@@ -906,6 +906,7 @@ int main(int argc, char **argv)
|
|||||||
pv_state_rate_limit_set(state, opts->rate_limit);
|
pv_state_rate_limit_set(state, opts->rate_limit);
|
||||||
pv_state_target_buffer_size_set(state, opts->buffer_size);
|
pv_state_target_buffer_size_set(state, opts->buffer_size);
|
||||||
pv_state_no_splice_set(state, opts->no_splice);
|
pv_state_no_splice_set(state, opts->no_splice);
|
||||||
|
pv_state_pipe_buffer_size_set(state, opts->pipe_buffer_size);
|
||||||
pv_state_size_set(state, opts->size);
|
pv_state_size_set(state, opts->size);
|
||||||
pv_state_name_set(state, opts->name);
|
pv_state_name_set(state, opts->name);
|
||||||
pv_state_default_bar_style_set(state, opts->default_bar_style);
|
pv_state_default_bar_style_set(state, opts->default_bar_style);
|
||||||
|
|||||||
+6
-1
@@ -721,6 +721,7 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
|||||||
{ "no-splice", 0, NULL, (int) 'C' },
|
{ "no-splice", 0, NULL, (int) 'C' },
|
||||||
{ "skip-errors", 0, NULL, (int) 'E' },
|
{ "skip-errors", 0, NULL, (int) 'E' },
|
||||||
{ "error-skip-block", 1, NULL, (int) 'Z' },
|
{ "error-skip-block", 1, NULL, (int) 'Z' },
|
||||||
|
{ "pipe-buffer-size", 1, NULL, (int) 'J' },
|
||||||
{ "stop-at-size", 0, NULL, (int) 'S' },
|
{ "stop-at-size", 0, NULL, (int) 'S' },
|
||||||
{ "sync", 0, NULL, (int) 'Y' },
|
{ "sync", 0, NULL, (int) 'Y' },
|
||||||
{ "direct-io", 0, NULL, (int) 'K' },
|
{ "direct-io", 0, NULL, (int) 'K' },
|
||||||
@@ -743,7 +744,7 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
|||||||
/*@+nullassign@ */
|
/*@+nullassign@ */
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
#endif /* HAVE_GETOPT_LONG */
|
#endif /* HAVE_GETOPT_LONG */
|
||||||
char *short_options = "hVpteIrab8kTA:fvnqcWD:s:gl0i:w:H:N:u:F:x:L:B:CEZ:SYKOXU:R:Q:P:d:m:o:M:"
|
char *short_options = "hVpteIrab8kTA:fvnqcWD:s:gl0i:w:H:N:u:F:x:L:B:CEZ:J:SYKOXU:R:Q:P:d:m:o:M:"
|
||||||
#ifdef ENABLE_DEBUGGING
|
#ifdef ENABLE_DEBUGGING
|
||||||
"!:"
|
"!:"
|
||||||
#endif
|
#endif
|
||||||
@@ -825,6 +826,7 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
|||||||
case 'L':
|
case 'L':
|
||||||
case 'B':
|
case 'B':
|
||||||
case 'Z':
|
case 'Z':
|
||||||
|
case 'J':
|
||||||
if (!pv_getnum_check(optarg, PV_NUMTYPE_ANY_WITH_SUFFIX)) {
|
if (!pv_getnum_check(optarg, PV_NUMTYPE_ANY_WITH_SUFFIX)) {
|
||||||
/*@-mustfreefresh@ *//* see above */
|
/*@-mustfreefresh@ *//* see above */
|
||||||
pv_error("-%c: %s: %s", c, optarg, _("numeric value not understood"));
|
pv_error("-%c: %s: %s", c, optarg, _("numeric value not understood"));
|
||||||
@@ -1064,6 +1066,9 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
|||||||
case 'Z':
|
case 'Z':
|
||||||
opts->error_skip_block = pv_getnum_size(optarg, opts->decimal_units);
|
opts->error_skip_block = pv_getnum_size(optarg, opts->decimal_units);
|
||||||
break;
|
break;
|
||||||
|
case 'J':
|
||||||
|
opts->pipe_buffer_size = (size_t) pv_getnum_size(optarg, opts->decimal_units);
|
||||||
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
opts->stop_at_size = true;
|
opts->stop_at_size = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -503,6 +503,46 @@ int pv_main_loop(pvstate_t state)
|
|||||||
if (0 == state->control.target_buffer_size)
|
if (0 == state->control.target_buffer_size)
|
||||||
state->control.target_buffer_size = BUFFER_SIZE;
|
state->control.target_buffer_size = BUFFER_SIZE;
|
||||||
|
|
||||||
|
#ifdef F_GETPIPE_SZ
|
||||||
|
#ifdef F_SETPIPE_SZ
|
||||||
|
/*
|
||||||
|
* If a pipe buffer size was explicitly set, then set the output
|
||||||
|
* pipe buffer size to that.
|
||||||
|
*
|
||||||
|
* If no pipe buffer size was set, and the first input is a pipe,
|
||||||
|
* then increase the output pipe buffer size to the same as the
|
||||||
|
* input pipe buffer size, if the output buffer was smaller.
|
||||||
|
*/
|
||||||
|
if (output_is_pipe) {
|
||||||
|
size_t target_pipe_buffer_size = state->control.pipe_buffer_size;
|
||||||
|
|
||||||
|
if (0 == target_pipe_buffer_size) {
|
||||||
|
int input_pipe_size;
|
||||||
|
input_pipe_size = fcntl(input_fd, F_GETPIPE_SZ);
|
||||||
|
|
||||||
|
debug("%s %d: %s=%d", "input fd", input_fd, "pipe size", input_pipe_size);
|
||||||
|
if (input_pipe_size > 0) {
|
||||||
|
int output_pipe_size;
|
||||||
|
output_pipe_size = fcntl(output_fd, F_GETPIPE_SZ);
|
||||||
|
debug("%s %d: %s=%d", "output fd", output_fd, "pipe size", output_pipe_size);
|
||||||
|
if (output_pipe_size > 0 && output_pipe_size < input_pipe_size) {
|
||||||
|
target_pipe_buffer_size = (size_t) input_pipe_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (target_pipe_buffer_size > 0) {
|
||||||
|
int output_pipe_size;
|
||||||
|
|
||||||
|
output_pipe_size = fcntl(output_fd, F_SETPIPE_SZ, (int) target_pipe_buffer_size);
|
||||||
|
debug("%s %d: %s=%d", "output fd", output_fd, "updated pipe size", output_pipe_size);
|
||||||
|
if (output_pipe_size < 0) {
|
||||||
|
debug("%s: %s", "failed to set pipe buffer size", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* F_SETPIPE_SZ */
|
||||||
|
#endif /* F_GETPIPE_SZ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Repeat until eof_in is true, eof_out is true, and final_update is
|
* Repeat until eof_in is true, eof_out is true, and final_update is
|
||||||
* true.
|
* true.
|
||||||
|
|||||||
@@ -642,6 +642,11 @@ void pv_state_no_splice_set(pvstate_t state, bool val)
|
|||||||
state->control.no_splice = val;
|
state->control.no_splice = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pv_state_pipe_buffer_size_set(pvstate_t state, size_t val)
|
||||||
|
{
|
||||||
|
state->control.pipe_buffer_size = val;
|
||||||
|
}
|
||||||
|
|
||||||
void pv_state_size_set(pvstate_t state, off_t val)
|
void pv_state_size_set(pvstate_t state, off_t val)
|
||||||
{
|
{
|
||||||
state->control.size = val;
|
state->control.size = val;
|
||||||
|
|||||||
Reference in New Issue
Block a user