Previously, --block-list and --block-size only worked together in threaded mode. Boundaries are specified by --block-list, but --block-size specifies the maximum size for block. Now this works in single-threaded mode too. --- src/xz/coder.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-)
diff --git a/src/xz/coder.c b/src/xz/coder.c index 61aa1f4..e035a4a 100644 --- a/src/xz/coder.c +++ b/src/xz/coder.c @@ -514,6 +514,43 @@ coder_init(file_pair *pair) } +/// Resolve conflicts between opt_block_size and opt_block_list in single +/// threaded mode. We want to default to opt_block_list, except when it is +/// larger than opt_block_size. If this is the case for the current block +/// at list_pos, then we break into smaller blocks. Otherwise advance +/// to the next block in opt_block_list, and break apart if needed. +static void +split_block(uint64_t *block_remaining, + uint64_t *next_block_remaining, + uint64_t *list_pos) +{ + if (*next_block_remaining > 0) { + /// The block at list_pos has previously been split up + if (*next_block_remaining > opt_block_size) { + /// We have to split the current block at list_pos + /// into another opt_block_size length block + *block_remaining = opt_block_size; + } else { + /// This is the last remaining split block for the + /// block at list_pos + *block_remaining = *next_block_remaining; + } + *next_block_remaining -= *block_remaining; + } else { + /// The block at list_pos is finished processing + if (opt_block_list[*list_pos + 1] != 0) + *list_pos = *list_pos + 1; + + *block_remaining = opt_block_list[*list_pos]; + if (*block_remaining > opt_block_size) { + *next_block_remaining = *block_remaining - + opt_block_size; + *block_remaining = opt_block_size; + } + } +} + + /// Compress or decompress using liblzma. static bool coder_normal(file_pair *pair) @@ -537,6 +574,10 @@ coder_normal(file_pair *pair) // only a single block is created. uint64_t block_remaining = UINT64_MAX; + // next_block_remining for when we are in single threaded mode and + // the block in --block-list is larger than the --block-size=SIZE. + uint64_t next_block_remaining = 0; + // Position in opt_block_list. Unused if --block-list wasn't used. size_t list_pos = 0; @@ -557,8 +598,14 @@ coder_normal(file_pair *pair) // at maximum and --block-list will simultaneously cause new // Blocks to be started at specified intervals. To keep things // logical, the same should be done in single-threaded mode. - if (opt_block_list != NULL) - block_remaining = opt_block_list[list_pos]; + if (opt_block_list != NULL) { + if (block_remaining < opt_block_list[list_pos]) { + next_block_remaining = opt_block_list[list_pos] + - block_remaining; + } else { + block_remaining = opt_block_list[list_pos]; + } + } } strm.next_out = out_buf.u8; @@ -623,9 +670,12 @@ coder_normal(file_pair *pair) // Start a new Block after LZMA_FULL_BARRIER. if (opt_block_list == NULL) { block_remaining = opt_block_size; + } else if (hardware_threads_get() == 1 && + opt_block_size > 0) { + split_block(&block_remaining, + &next_block_remaining, + &list_pos); } else { - // FIXME: Make it work together with - // --block-size. if (opt_block_list[list_pos + 1] != 0) ++list_pos; -- 1.8.3.2