diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2013-07-04 14:18:46 +0300 |
---|---|---|
committer | Lasse Collin <lasse.collin@tukaani.org> | 2013-07-04 14:18:46 +0300 |
commit | dee6ad3d5915422bc30a6821efeacaeb8ca8ef00 (patch) | |
tree | 1d7ed417efbe88860df208afaf0b96ed7ed07afd /src/xz/file_io.c | |
parent | xz: Don't set src_eof=true after an I/O error because it's useless. (diff) | |
download | xz-dee6ad3d5915422bc30a6821efeacaeb8ca8ef00.tar.xz |
xz: Add preliminary support for --flush-timeout=TIMEOUT.
When --flush-timeout=TIMEOUT is used, xz will use
LZMA_SYNC_FLUSH if read() would block and at least
TIMEOUT milliseconds has elapsed since the previous flush.
This can be useful in realtime-like use cases where the
data is simultanously decompressed by another process
(possibly on a different computer). If new uncompressed
input data is produced slowly, without this option xz could
buffer the data for a long time until it would become
decompressible from the output.
If TIMEOUT is 0, the feature is disabled. This is the default.
This commit affects the compression side. Using xz for
the decompression side for the above purpose doesn't work
yet so well because there is quite a bit of input and
output buffering when decompressing.
The --long-help or man page were not updated yet.
The details of this feature may change.
Diffstat (limited to 'src/xz/file_io.c')
-rw-r--r-- | src/xz/file_io.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/src/xz/file_io.c b/src/xz/file_io.c index 921f79d1..fb8d64bd 100644 --- a/src/xz/file_io.c +++ b/src/xz/file_io.c @@ -38,6 +38,13 @@ static bool warn_fchown; #endif +typedef enum { + IO_WAIT_MORE, // Reading or writing is possible. + IO_WAIT_ERROR, // Error or user_abort + IO_WAIT_TIMEOUT, // poll() timed out +} io_wait_ret; + + /// If true, try to create sparse files when decompressing. static bool try_sparse = true; @@ -130,8 +137,8 @@ io_no_sparse(void) /// pops up again. There are pselect() (POSIX-1.2001) and ppoll() (not in /// POSIX) but neither is portable enough in 2013. The self-pipe trick is /// old and very portable. -static bool -io_wait(file_pair *pair, bool is_reading) +static io_wait_ret +io_wait(file_pair *pair, int timeout, bool is_reading) { struct pollfd pfd[2]; @@ -147,10 +154,10 @@ io_wait(file_pair *pair, bool is_reading) pfd[1].events = POLLIN; while (true) { - const int ret = poll(pfd, 2, -1); + const int ret = poll(pfd, 2, timeout); if (user_abort) - return true; + return IO_WAIT_ERROR; if (ret == -1) { if (errno == EINTR || errno == EAGAIN) @@ -160,10 +167,17 @@ io_wait(file_pair *pair, bool is_reading) is_reading ? pair->src_name : pair->dest_name, strerror(errno)); + return IO_WAIT_ERROR; + } + + if (ret == 0) { + assert(opt_flush_timeout != 0); + flush_needed = true; + return IO_WAIT_TIMEOUT; } if (pfd[0].revents != 0) - return false; + return IO_WAIT_MORE; } } #endif @@ -583,10 +597,10 @@ io_open_src_real(file_pair *pair) // will work when open() is used with O_NONBLOCK. if (!S_ISREG(pair->src_st.st_mode)) { signals_unblock(); - const bool ret = io_wait(pair, true); + const io_wait_ret ret = io_wait(pair, -1, true); signals_block(); - if (ret) + if (ret != IO_WAIT_MORE) goto error; } #endif @@ -1001,10 +1015,22 @@ io_read(file_pair *pair, io_buf *buf_union, size_t size) #ifndef TUKLIB_DOSLIKE if (errno == EAGAIN || errno == EWOULDBLOCK) { - if (!io_wait(pair, true)) + const io_wait_ret ret = io_wait(pair, + mytime_get_flush_timeout(), + true); + switch (ret) { + case IO_WAIT_MORE: continue; - return SIZE_MAX; + case IO_WAIT_ERROR: + return SIZE_MAX; + + case IO_WAIT_TIMEOUT: + return size - left; + + default: + message_bug(); + } } #endif @@ -1077,7 +1103,7 @@ io_write_buf(file_pair *pair, const uint8_t *buf, size_t size) #ifndef TUKLIB_DOSLIKE if (errno == EAGAIN || errno == EWOULDBLOCK) { - if (!io_wait(pair, false)) + if (io_wait(pair, -1, false) == IO_WAIT_MORE) continue; return true; |