diff options
Diffstat (limited to 'src/xz/coder.c')
-rw-r--r-- | src/xz/coder.c | 495 |
1 files changed, 222 insertions, 273 deletions
diff --git a/src/xz/coder.c b/src/xz/coder.c index 4efaa802b9bb..5e41f0df6802 100644 --- a/src/xz/coder.c +++ b/src/xz/coder.c @@ -11,6 +11,7 @@ /////////////////////////////////////////////////////////////////////////////// #include "private.h" +#include "tuklib_integer.h" /// Return value type for coder_init(). @@ -27,6 +28,8 @@ bool opt_auto_adjust = true; bool opt_single_stream = false; uint64_t opt_block_size = 0; block_list_entry *opt_block_list = NULL; +uint64_t block_list_largest; +uint32_t block_list_chain_mask; /// Stream used to communicate with liblzma static lzma_stream strm = LZMA_STREAM_INIT; @@ -35,25 +38,19 @@ static lzma_stream strm = LZMA_STREAM_INIT; /// and 9 other filter chains can be specified with --filtersX. #define NUM_FILTER_CHAIN_MAX 10 -/// The default filter chain is in filters[0]. It is used for encoding +/// The default filter chain is in chains[0]. It is used for encoding /// in all supported formats and also for decdoing raw streams. The other /// filter chains are set by --filtersX to support changing filters with /// the --block-list option. -static lzma_filter filters[NUM_FILTER_CHAIN_MAX][LZMA_FILTERS_MAX + 1]; +static lzma_filter chains[NUM_FILTER_CHAIN_MAX][LZMA_FILTERS_MAX + 1]; -/// Bit mask representing the filters that are actually used when encoding -/// in the xz format. This is needed since a filter chain could be -/// specified in --filtersX (or the default filter chain), but never used -/// in --block-list. The default filter chain is always assumed to be used, -/// unless --block-list is specified and does not have a block using the -/// default filter chain. -static uint32_t filters_used_mask = 1; - -#ifdef HAVE_ENCODERS -/// Track the memory usage for all filter chains (default or --filtersX). -/// The memory usage may need to be scaled down depending on the memory limit. -static uint64_t filter_memusages[ARRAY_SIZE(filters)]; -#endif +/// Bitmask indicating which filter chains are actually used when encoding +/// in the .xz format. This is needed since the filter chains specified using +/// --filtersX (or the default filter chain) might in reality be unneeded +/// if they are never used in --block-list. When --block-list isn't +/// specified, only the default filter chain is used, thus the initial +/// value of this variable is 1U << 0 (the number of the default chain is 0). +static uint32_t chains_used_mask = 1U << 0; /// Input and output buffers static io_buf in_buf; @@ -105,7 +102,7 @@ forget_filter_chain(void) // Setting a preset or using --filters makes us forget // the earlier custom filter chain (if any). if (filters_count > 0) { - lzma_filters_free(filters[0], NULL); + lzma_filters_free(chains[0], NULL); filters_count = 0; } @@ -142,11 +139,12 @@ coder_add_filter(lzma_vli id, void *options) if (string_to_filter_used) forget_filter_chain(); - filters[0][filters_count].id = id; - filters[0][filters_count].options = options; + chains[0][filters_count].id = id; + chains[0][filters_count].options = options; + // Terminate the filter chain with LZMA_VLI_UNKNOWN to simplify // implementation of forget_filter_chain(). - filters[0][++filters_count].id = LZMA_VLI_UNKNOWN; + chains[0][++filters_count].id = LZMA_VLI_UNKNOWN; // Setting a custom filter chain makes us forget the preset options. // This makes a difference if one specifies e.g. "xz -9 --lzma2 -e" @@ -163,7 +161,7 @@ str_to_filters(const char *str, uint32_t index, uint32_t flags) { int error_pos; const char *err = lzma_str_to_filters(str, &error_pos, - filters[index], flags, NULL); + chains[index], flags, NULL); if (err != NULL) { char filter_num[2] = ""; @@ -199,7 +197,7 @@ coder_add_filters_from_str(const char *filter_str) // Set the filters_count to be the number of filters converted from // the string. - for (filters_count = 0; filters[0][filters_count].id + for (filters_count = 0; chains[0][filters_count].id != LZMA_VLI_UNKNOWN; ++filters_count) ; @@ -212,12 +210,12 @@ extern void coder_add_block_filters(const char *str, size_t slot) { // Free old filters first, if they were previously allocated. - if (filters_used_mask & (1U << slot)) - lzma_filters_free(filters[slot], NULL); + if (chains_used_mask & (1U << slot)) + lzma_filters_free(chains[slot], NULL); str_to_filters(str, slot, 0); - filters_used_mask |= 1U << slot; + chains_used_mask |= 1U << slot; } @@ -233,29 +231,26 @@ memlimit_too_small(uint64_t memory_usage) #ifdef HAVE_ENCODERS -// For a given opt_block_list index, validate that the filter has been -// set. If it has not been set, we must exit with error to avoid using -// an uninitialized filter chain. -static void -validate_block_list_filter(const uint32_t filter_num) -{ - if (!(filters_used_mask & (1U << filter_num))) - message_fatal(_("filter chain %u used by --block-list but " - "not specified with --filters%u="), - (unsigned)filter_num, (unsigned)filter_num); -} - - -// Sets the memory usage for each filter chain. It will return the maximum -// memory usage of all of the filter chains. +/// \brief Calculate the memory usage of each filter chain. +/// +/// \param chains_memusages If non-NULL, the memusage of the encoder +/// or decoder for each chain is stored in +/// this array. +/// \param mt If non-NULL, calculate memory usage of +/// multithreaded encoder. +/// \param encode Whether to calculate encoder or decoder +/// memory usage. This must be true if +/// mt != NULL. +/// +/// \return Return the highest memory usage of all of the filter chains. static uint64_t -filters_memusage_max(const lzma_mt *mt, bool encode) +get_chains_memusage(uint64_t *chains_memusages, const lzma_mt *mt, bool encode) { uint64_t max_memusage = 0; #ifdef MYTHREAD_ENABLED - // Copy multithreaded options to a temporary struct since the - // filters member needs to be changed + // Copy multithreading options to a temporary struct since the + // "filters" member needs to be changed. lzma_mt mt_local; if (mt != NULL) mt_local = *mt; @@ -263,40 +258,39 @@ filters_memusage_max(const lzma_mt *mt, bool encode) (void)mt; #endif - for (uint32_t i = 0; i < ARRAY_SIZE(filters); i++) { - if (!(filters_used_mask & (1U << i))) + for (uint32_t i = 0; i < ARRAY_SIZE(chains); i++) { + if (!(chains_used_mask & (1U << i))) continue; uint64_t memusage = UINT64_MAX; #ifdef MYTHREAD_ENABLED if (mt != NULL) { - mt_local.filters = filters[i]; + assert(encode); + mt_local.filters = chains[i]; memusage = lzma_stream_encoder_mt_memusage(&mt_local); - filter_memusages[i] = memusage; - } - else + } else #endif - if (encode) { - memusage = lzma_raw_encoder_memusage(filters[i]); - filter_memusages[i] = memusage; + memusage = lzma_raw_encoder_memusage(chains[i]); } - #ifdef HAVE_DECODERS else { - memusage = lzma_raw_decoder_memusage(filters[i]); + memusage = lzma_raw_decoder_memusage(chains[i]); } #endif + if (chains_memusages != NULL) + chains_memusages[i] = memusage; + if (memusage > max_memusage) max_memusage = memusage; } return max_memusage; } - #endif + extern void coder_set_compression_settings(void) { @@ -305,65 +299,65 @@ coder_set_compression_settings(void) assert(opt_format != FORMAT_LZIP); #endif -#ifdef HAVE_ENCODERS -# ifdef MYTHREAD_ENABLED - // Represents the largest Block size specified with --block-list. This - // is needed to help reduce the Block size in the multithreaded encoder - // so memory is not wasted. - uint64_t max_block_list_size = 0; -# endif + // The default check type is CRC64, but fallback to CRC32 + // if CRC64 isn't supported by the copy of liblzma we are + // using. CRC32 is always supported. + if (check_default) { + check = LZMA_CHECK_CRC64; + if (!lzma_check_is_supported(check)) + check = LZMA_CHECK_CRC32; + } +#ifdef HAVE_ENCODERS if (opt_block_list != NULL) { - // This mask tracks the filters actually referenced in - // --block-list. It is used to help remove bits from - // filters_used_mask when a filter chain was specified - // but never actually used. - uint32_t filters_ref_mask = 0; - - for (uint32_t i = 0; opt_block_list[i].size != 0; i++) { - validate_block_list_filter( - opt_block_list[i].filters_index); - - // Mark the current filter as referenced. - filters_ref_mask |= 1U << - opt_block_list[i].filters_index; - -# ifdef MYTHREAD_ENABLED - if (opt_block_list[i].size > max_block_list_size) - max_block_list_size = opt_block_list[i].size; -# endif + // args.c ensures these. + assert(opt_mode == MODE_COMPRESS); + assert(opt_format == FORMAT_XZ); + + // Find out if block_list_chain_mask has a bit set that + // isn't set in chains_used_mask. + const uint32_t missing_chains_mask + = (block_list_chain_mask ^ chains_used_mask) + & block_list_chain_mask; + + // If a filter chain was specified in --block-list but no + // matching --filtersX option was used, exit with an error. + if (missing_chains_mask != 0) { + // Get the number of the first missing filter chain + // and show it in the error message. + const unsigned first_missing + = (unsigned)ctz32(missing_chains_mask); + + message_fatal(_("filter chain %u used by " + "--block-list but not specified " + "with --filters%u="), + first_missing, first_missing); } - assert(filters_ref_mask != 0); - // Note: The filters that were initialized but not used do - // not free their options and do not have the filter - // IDs set to LZMA_VLI_UNKNOWN. Filter chains are not - // freed outside of debug mode and the default filter - // chain is never freed. - filters_used_mask = filters_ref_mask; + // Omit the unused filter chains from mask of used chains. + // + // (FIXME? When built with debugging, coder_free() will free() + // the filter chains (except the default chain) which makes + // Valgrind show fewer reachable allocations. But coder_free() + // uses this mask to determine which chains to free. Thus it + // won't free the ones that are cleared here from the mask. + // In practice this doesn't matter.) + chains_used_mask &= block_list_chain_mask; } else { // Reset filters used mask in case --block-list is not // used, but --filtersX is used. - filters_used_mask = 1; + chains_used_mask = 1U << 0; } #endif - // The default check type is CRC64, but fallback to CRC32 - // if CRC64 isn't supported by the copy of liblzma we are - // using. CRC32 is always supported. - if (check_default) { - check = LZMA_CHECK_CRC64; - if (!lzma_check_is_supported(check)) - check = LZMA_CHECK_CRC32; - } // Options for LZMA1 or LZMA2 in case we are using a preset. static lzma_options_lzma opt_lzma; - // The first filter in the filters[] array is for the default + // The first filter in the chains[] array is for the default // filter chain. - lzma_filter *default_filters = filters[0]; + lzma_filter *default_filters = chains[0]; - if (filters_count == 0 && filters_used_mask & 1) { + if (filters_count == 0 && chains_used_mask & 1) { // We are using a preset. This is not a good idea in raw mode // except when playing around with things. Different versions // of this software may use different options in presets, and @@ -403,14 +397,16 @@ coder_set_compression_settings(void) "the LZMA1 filter")); // If we are using the .xz format, make sure that there is no LZMA1 - // filter to prevent LZMA_PROG_ERROR. - if (opt_format == FORMAT_XZ && filters_used_mask & 1) + // filter to prevent LZMA_PROG_ERROR. With the chains from --filtersX + // we have already ensured this by calling lzma_str_to_filters() + // without setting the flags that would allow non-.xz filters. + if (opt_format == FORMAT_XZ && chains_used_mask & 1) for (size_t i = 0; i < filters_count; ++i) if (default_filters[i].id == LZMA_FILTER_LZMA1) message_fatal(_("LZMA1 cannot be used " "with the .xz format")); - if (filters_used_mask & 1) { + if (chains_used_mask & 1) { // Print the selected default filter chain. message_filters_show(V_DEBUG, default_filters); } @@ -419,11 +415,11 @@ coder_set_compression_settings(void) // from the filter chain. Currently the threaded encoder doesn't // support LZMA_SYNC_FLUSH so single-threaded mode must be used. if (opt_mode == MODE_COMPRESS && opt_flush_timeout != 0) { - for (uint32_t i = 0; i < ARRAY_SIZE(filters); ++i) { - if (!(filters_used_mask & (1U << i))) + for (unsigned i = 0; i < ARRAY_SIZE(chains); ++i) { + if (!(chains_used_mask & (1U << i))) continue; - const lzma_filter *fc = filters[i]; + const lzma_filter *fc = chains[i]; for (size_t j = 0; fc[j].id != LZMA_VLI_UNKNOWN; j++) { switch (fc[j].id) { case LZMA_FILTER_LZMA2: @@ -434,7 +430,7 @@ coder_set_compression_settings(void) message_fatal(_("Filter chain %u is " "incompatible with " "--flush-timeout"), - (unsigned)i); + i); } } } @@ -446,17 +442,22 @@ coder_set_compression_settings(void) } } - // Get the memory usage and memory limit. The memory usage is the - // maximum of the default filters[] and any filters specified by - // --filtersX. - // Note that if --format=raw was used, we can be decompressing and - // do not need to account for any filter chains created - // with --filtersX. + // Get memory limit and the memory usage of the used filter chains. + // Note that if --format=raw was used, we can be decompressing + // using the default filter chain. // // If multithreaded .xz compression is done, the memory limit // will be replaced. uint64_t memory_limit = hardware_memlimit_get(opt_mode); uint64_t memory_usage = UINT64_MAX; + +#ifdef HAVE_ENCODERS + // Memory usage for each encoder filter chain (default + // or --filtersX). The encoder options may need to be + // scaled down depending on the memory usage limit. + uint64_t encoder_memusages[ARRAY_SIZE(chains)]; +#endif + if (opt_mode == MODE_COMPRESS) { #ifdef HAVE_ENCODERS # ifdef MYTHREAD_ENABLED @@ -465,16 +466,17 @@ coder_set_compression_settings(void) mt_options.threads = hardware_threads_get(); uint64_t block_size = opt_block_size; + // If opt_block_size is not set, find the maximum // recommended Block size based on the filter chains if (block_size == 0) { - for (uint32_t i = 0; i < ARRAY_SIZE(filters); + for (unsigned i = 0; i < ARRAY_SIZE(chains); i++) { - if (!(filters_used_mask & (1U << i))) + if (!(chains_used_mask & (1U << i))) continue; uint64_t size = lzma_mt_block_size( - filters[i]); + chains[i]); // If this returns an error, then one // of the filter chains in use is @@ -483,33 +485,28 @@ coder_set_compression_settings(void) if (size == UINT64_MAX) message_fatal(_("Unsupported " "options in filter " - "chain %u"), - (unsigned)i); + "chain %u"), i); if (size > block_size) block_size = size; } - // If the largest block size specified - // with --block-list is less than the - // recommended Block size, then it is a waste - // of RAM to use a larger Block size. It may - // even allow more threads to be used in some - // situations. If the special 0 Block size is - // used (encode all remaining data in 1 Block) - // then max_block_list_size will be set to - // UINT64_MAX, so the recommended Block size - // will always be used in this case. - if (max_block_list_size > 0 - && max_block_list_size - < block_size) - block_size = max_block_list_size; + // If --block-list was used and our current + // Block size exceeds the largest size + // in --block-list, reduce the Block size of + // the multithreaded encoder. The extra size + // would only be a waste of RAM. With a + // smaller Block size we might even be able + // to use more threads in some cases. + if (block_list_largest > 0 && block_size + > block_list_largest) + block_size = block_list_largest; } mt_options.block_size = block_size; mt_options.check = check; - memory_usage = filters_memusage_max( + memory_usage = get_chains_memusage(encoder_memusages, &mt_options, true); if (memory_usage != UINT64_MAX) message(V_DEBUG, _("Using up to %" PRIu32 @@ -518,7 +515,8 @@ coder_set_compression_settings(void) } else # endif { - memory_usage = filters_memusage_max(NULL, true); + memory_usage = get_chains_memusage(encoder_memusages, + NULL, true); } #endif } else { @@ -533,21 +531,13 @@ coder_set_compression_settings(void) // Print memory usage info before possible dictionary // size auto-adjusting. // - // NOTE: If only encoder support was built, we cannot show the + // NOTE: If only encoder support was built, we cannot show // what the decoder memory usage will be. message_mem_needed(V_DEBUG, memory_usage); -#ifdef HAVE_DECODERS - if (opt_mode == MODE_COMPRESS) { -#ifdef HAVE_ENCODERS - const uint64_t decmem = - filters_memusage_max(NULL, false); -#else - // If encoders are not enabled, then --block-list is never - // usable, so the other filter chains 1-9 can never be used. - // So there is no need to find the maximum decoder memory - // required in this case. - const uint64_t decmem = lzma_raw_decoder_memusage(filters[0]); -#endif + +#if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS) + if (opt_mode == MODE_COMPRESS && message_verbosity_get() >= V_DEBUG) { + const uint64_t decmem = get_chains_memusage(NULL, NULL, false); if (decmem != UINT64_MAX) message(V_DEBUG, _("Decompression will need " "%s MiB of memory."), uint64_to_str( @@ -574,14 +564,21 @@ coder_set_compression_settings(void) // Reduce the number of threads by one and check // the memory usage. --mt_options.threads; - memory_usage = filters_memusage_max( + memory_usage = get_chains_memusage(encoder_memusages, &mt_options, true); if (memory_usage == UINT64_MAX) message_bug(); if (memory_usage <= memory_limit) { // The memory usage is now low enough. - message(V_WARNING, _("Reduced the number of " + // + // Since 5.6.1: This is only shown at + // V_DEBUG instead of V_WARNING because + // changing the number of threads doesn't + // affect the output. On some systems this + // message would be too common now that + // multithreaded compression is the default. + message(V_DEBUG, _("Reduced the number of " "threads from %s to %s to not exceed " "the memory usage limit of %s MiB"), uint64_to_str( @@ -600,8 +597,11 @@ coder_set_compression_settings(void) // way -T0 won't use insane amount of memory but at the same // time the soft limit will never make xz fail and never make // xz change settings that would affect the compressed output. + // + // Since 5.6.1: Like above, this is now shown at V_DEBUG + // instead of V_WARNING. if (hardware_memlimit_mtenc_is_default()) { - message(V_WARNING, _("Reduced the number of threads " + message(V_DEBUG, _("Reduced the number of threads " "from %s to one. The automatic memory usage " "limit of %s MiB is still being exceeded. " "%s MiB of memory is required. " @@ -627,7 +627,8 @@ coder_set_compression_settings(void) // the multithreaded mode but the output // is also different. hardware_threads_set(1); - memory_usage = filters_memusage_max(NULL, true); + memory_usage = get_chains_memusage(encoder_memusages, + NULL, true); message(V_WARNING, _("Switching to single-threaded mode " "to not exceed the memory usage limit of %s MiB"), uint64_to_str(round_up_to_mib(memory_limit), 0)); @@ -642,137 +643,84 @@ coder_set_compression_settings(void) if (!opt_auto_adjust) memlimit_too_small(memory_usage); - // Decrease the dictionary size until we meet the memory usage limit. - // The struct is used to track data needed to correctly reduce the - // memory usage and report which filters were adjusted. - typedef struct { - // Pointer to the filter chain that needs to be reduced. - // NULL indicates that this filter chain was either never - // set or was never above the memory limit. - lzma_filter *filters; - - // Original dictionary sizes are used to show how each - // filter's dictionary was reduced. - uint64_t orig_dict_size; - - // Index of the LZMA filter in the filters member. We only - // adjust this filter's memusage because we don't know how - // to reduce the memory usage of the other filters. - uint32_t lzma_idx; - - // Indicates if the filter's dictionary size needs to be - // reduced to fit under the memory limit (true) or if the - // filter chain is unused or is already under the memory - // limit (false). - bool reduce_dict_size; - } memusage_reduction_data; - - memusage_reduction_data memusage_reduction[ARRAY_SIZE(filters)]; - - // Counter represents how many filter chains are above the memory - // limit. - size_t count = 0; - - for (uint32_t i = 0; i < ARRAY_SIZE(filters); i++) { - // The short var name "r" will reduce the number of lines - // of code needed since less lines will stretch past 80 - // characters. - memusage_reduction_data *r = &memusage_reduction[i]; - r->filters = NULL; - r->reduce_dict_size = false; - - if (!(filters_used_mask & (1U << i))) + // Adjust each filter chain that is exceeding the memory usage limit. + for (unsigned i = 0; i < ARRAY_SIZE(chains); i++) { + // Skip unused chains. + if (!(chains_used_mask & (1U << i))) continue; - for (uint32_t j = 0; filters[i][j].id != LZMA_VLI_UNKNOWN; - j++) - if ((filters[i][j].id == LZMA_FILTER_LZMA2 - || filters[i][j].id - == LZMA_FILTER_LZMA1) - && filter_memusages[i] - > memory_limit) { - count++; - r->filters = filters[i]; - r->lzma_idx = j; - r->reduce_dict_size = true; - - lzma_options_lzma *opt = r->filters - [r->lzma_idx].options; - r->orig_dict_size = opt->dict_size; - opt->dict_size &= ~((UINT32_C(1) << 20) - 1); - } - } - - // Loop until all filters use <= memory_limit, or exit. - while (count > 0) { - for (uint32_t i = 0; i < ARRAY_SIZE(memusage_reduction); i++) { - memusage_reduction_data *r = &memusage_reduction[i]; + // Skip chains that already meet the memory usage limit. + if (encoder_memusages[i] <= memory_limit) + continue; - if (!r->reduce_dict_size) - continue; + // Look for the last filter if it is LZMA2 or LZMA1, so we + // can make it use less RAM. We cannot adjust other filters. + unsigned j = 0; + while (chains[i][j].id != LZMA_FILTER_LZMA2 + && chains[i][j].id != LZMA_FILTER_LZMA1) { + // NOTE: This displays the too high limit of this + // particular filter chain. If multiple chains are + // specified and another one would need more then + // this message could be confusing. As long as LZMA2 + // is the only memory hungry filter in .xz this + // doesn't matter at all in practice. + // + // FIXME? However, it's sort of odd still if we had + // switched from multithreaded mode to single-threaded + // mode because single-threaded produces different + // output. So the messages could perhaps be clearer. + // Another case of this is a few lines below. + if (chains[i][j].id == LZMA_VLI_UNKNOWN) + memlimit_too_small(encoder_memusages[i]); + + ++j; + } - lzma_options_lzma *opt = - r->filters[r->lzma_idx].options; + // Decrease the dictionary size until we meet the memory + // usage limit. First round down to full mebibytes. + lzma_options_lzma *opt = chains[i][j].options; + const uint32_t orig_dict_size = opt->dict_size; + opt->dict_size &= ~((UINT32_C(1) << 20) - 1); + while (true) { // If it is below 1 MiB, auto-adjusting failed. - // We could be more sophisticated and scale it - // down even more, but nobody has complained so far. + // + // FIXME? See the FIXME a few lines above. if (opt->dict_size < (UINT32_C(1) << 20)) - memlimit_too_small(memory_usage); + memlimit_too_small(encoder_memusages[i]); - uint64_t filt_mem_usage = - lzma_raw_encoder_memusage(r->filters); - - if (filt_mem_usage == UINT64_MAX) + encoder_memusages[i] + = lzma_raw_encoder_memusage(chains[i]); + if (encoder_memusages[i] == UINT64_MAX) message_bug(); - if (filt_mem_usage < memory_limit) { - r->reduce_dict_size = false; - count--; - } - else { - opt->dict_size -= UINT32_C(1) << 20; - } - } - } - - // Tell the user that we decreased the dictionary size for - // each filter that was adjusted. - for (uint32_t i = 0; i < ARRAY_SIZE(memusage_reduction); i++) { - memusage_reduction_data *r = &memusage_reduction[i]; - - // If the filters were never set, then the memory usage - // was never adjusted. - if (r->filters == NULL) - continue; + // Accept it if it is low enough. + if (encoder_memusages[i] <= memory_limit) + break; - lzma_filter *filter_lzma = &(r->filters[r->lzma_idx]); - lzma_options_lzma *opt = filter_lzma->options; + // Otherwise adjust it 1 MiB down and try again. + opt->dict_size -= UINT32_C(1) << 20; + } - // The first index is the default filter chain. The message - // should be slightly different if the default filter chain - // or if --filtersX was adjusted. + // Tell the user that we decreased the dictionary size. + // The message is slightly different between the default + // filter chain (0) or and chains from --filtersX. + const char lzma_num = chains[i][j].id == LZMA_FILTER_LZMA2 + ? '2' : '1'; + const char *from_size = uint64_to_str(orig_dict_size >> 20, 0); + const char *to_size = uint64_to_str(opt->dict_size >> 20, 1); + const char *limit_size = uint64_to_str(round_up_to_mib( + memory_limit), 2); if (i == 0) message(V_WARNING, _("Adjusted LZMA%c dictionary " "size from %s MiB to %s MiB to not exceed the " "memory usage limit of %s MiB"), - filter_lzma->id == LZMA_FILTER_LZMA2 - ? '2' : '1', - uint64_to_str(r->orig_dict_size >> 20, 0), - uint64_to_str(opt->dict_size >> 20, 1), - uint64_to_str(round_up_to_mib( - memory_limit), 2)); + lzma_num, from_size, to_size, limit_size); else message(V_WARNING, _("Adjusted LZMA%c dictionary size " "for --filters%u from %s MiB to %s MiB to not " "exceed the memory usage limit of %s MiB"), - filter_lzma->id == LZMA_FILTER_LZMA2 - ? '2' : '1', - (unsigned)i, - uint64_to_str(r->orig_dict_size >> 20, 0), - uint64_to_str(opt->dict_size >> 20, 1), - uint64_to_str(round_up_to_mib( - memory_limit), 2)); + lzma_num, i, from_size, to_size, limit_size); } #endif @@ -870,11 +818,11 @@ coder_init(file_pair *pair) allow_trailing_input = false; // Set the first filter chain. If the --block-list option is not - // used then use the default filter chain (filters[0]). + // used then use the default filter chain (chains[0]). // Otherwise, use first filter chain from the block list. lzma_filter *active_filters = opt_block_list == NULL - ? filters[0] - : filters[opt_block_list[0].filters_index]; + ? chains[0] + : chains[opt_block_list[0].chain_num]; if (opt_mode == MODE_COMPRESS) { #ifdef HAVE_ENCODERS @@ -1119,11 +1067,11 @@ split_block(uint64_t *block_remaining, ++*list_pos; // Update the filters if needed. - if (opt_block_list[*list_pos - 1].filters_index - != opt_block_list[*list_pos].filters_index) { - const uint32_t filter_idx = opt_block_list - [*list_pos].filters_index; - const lzma_filter *next = filters[filter_idx]; + if (opt_block_list[*list_pos - 1].chain_num + != opt_block_list[*list_pos].chain_num) { + const unsigned chain_num + = opt_block_list[*list_pos].chain_num; + const lzma_filter *next = chains[chain_num]; const lzma_ret ret = lzma_filters_update( &strm, next); @@ -1139,7 +1087,7 @@ split_block(uint64_t *block_remaining, message_fatal( _("Error changing to " "filter chain %u: %s"), - (unsigned)filter_idx, + chain_num, message_strm(ret)); } } @@ -1278,9 +1226,10 @@ coder_normal(file_pair *pair) ret = lzma_code(&strm, action); // Write out if the output buffer became full. - if (strm.avail_out == 0) + if (strm.avail_out == 0) { if (coder_write_output(pair)) break; + } #ifdef HAVE_ENCODERS if (ret == LZMA_STREAM_END && (action == LZMA_SYNC_FLUSH @@ -1514,9 +1463,9 @@ coder_free(void) // in coder_set_compression_settings(). Since this is only run in // debug mode and will be freed when the process ends anyway, we // don't worry about freeing it. - for (uint32_t i = 1; i < ARRAY_SIZE(filters); i++) { - if (filters_used_mask & (1U << i)) - lzma_filters_free(filters[i], NULL); + for (uint32_t i = 1; i < ARRAY_SIZE(chains); i++) { + if (chains_used_mask & (1U << i)) + lzma_filters_free(chains[i], NULL); } lzma_end(&strm); |