]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-compression: Implement min/default/max getters
authorAki Tuomi <aki.tuomi@open-xchange.com>
Thu, 1 Apr 2021 06:26:10 +0000 (09:26 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Tue, 13 Apr 2021 06:18:28 +0000 (09:18 +0300)
src/lib-compression/compression.c
src/lib-compression/ostream-bzlib.c
src/lib-compression/ostream-lz4.c
src/lib-compression/ostream-zlib.c
src/lib-compression/ostream-zlib.h
src/lib-compression/ostream-zstd.c

index 483824d50f5fd19dedbd89d1e34d45a92043ec31..e562e7390d1da14acb5b24d0e47b61163cc5ee56 100644 (file)
 #  define o_stream_create_gz NULL
 #  define i_stream_create_deflate NULL
 #  define o_stream_create_deflate NULL
+#  define compression_get_min_level_gz NULL
+#  define compression_get_default_level_gz NULL
+#  define compression_get_max_level_gz NULL
 #endif
 #ifndef HAVE_BZLIB
 #  define i_stream_create_bz2 NULL
 #  define o_stream_create_bz2 NULL
+#  define compression_get_min_level_bz2 NULL
+#  define compression_get_default_level_bz2 NULL
+#  define compression_get_max_level_bz2 NULL
 #endif
 #ifndef HAVE_LZMA
 #  define i_stream_create_lzma NULL
 #ifndef HAVE_LZ4
 #  define i_stream_create_lz4 NULL
 #  define o_stream_create_lz4 NULL
+#  define compression_get_min_level_lz4 NULL
+#  define compression_get_default_level_lz4 NULL
+#  define compression_get_max_level_lz4 NULL
 #endif
 #ifndef HAVE_ZSTD
 #  define i_stream_create_zstd NULL
 #  define o_stream_create_zstd NULL
+#  define compression_get_min_level_zstd NULL
+#  define compression_get_default_level_zstd NULL
+#  define compression_get_max_level_zstd NULL
 #endif
 
 static bool is_compressed_zlib(struct istream *input)
@@ -153,6 +165,21 @@ int compression_lookup_handler_from_ext(const char *path,
        return -1;
 }
 
+static int compression_get_min_level_unsupported(void)
+{
+       return -1;
+}
+
+static int compression_get_default_level_unsupported(void)
+{
+       return -1;
+}
+
+static int compression_get_max_level_unsupported(void)
+{
+       return -1;
+}
+
 const struct compression_handler compression_handlers[] = {
        {
                .name = "gz",
@@ -160,6 +187,9 @@ const struct compression_handler compression_handlers[] = {
                .is_compressed = is_compressed_zlib,
                .create_istream = i_stream_create_gz,
                .create_ostream = o_stream_create_gz,
+               .get_min_level = compression_get_min_level_gz,
+               .get_default_level = compression_get_default_level_gz,
+               .get_max_level = compression_get_max_level_gz,
        },
        {
                .name = "bz2",
@@ -167,6 +197,9 @@ const struct compression_handler compression_handlers[] = {
                .is_compressed = is_compressed_bzlib,
                .create_istream = i_stream_create_bz2,
                .create_ostream = o_stream_create_bz2,
+               .get_min_level = compression_get_min_level_bz2,
+               .get_default_level = compression_get_default_level_bz2,
+               .get_max_level = compression_get_max_level_bz2,
        },
        {
                .name = "deflate",
@@ -174,6 +207,9 @@ const struct compression_handler compression_handlers[] = {
                .is_compressed = NULL,
                .create_istream = i_stream_create_deflate,
                .create_ostream = o_stream_create_deflate,
+               .get_min_level = compression_get_min_level_gz,
+               .get_default_level = compression_get_default_level_gz,
+               .get_max_level = compression_get_max_level_gz,
        },
        {
                .name = "xz",
@@ -181,6 +217,9 @@ const struct compression_handler compression_handlers[] = {
                .is_compressed = is_compressed_xz,
                .create_istream = i_stream_create_lzma,
                .create_ostream = NULL,
+               .get_min_level = compression_get_min_level_unsupported,
+               .get_default_level = compression_get_default_level_unsupported,
+               .get_max_level = compression_get_max_level_unsupported,
        },
        {
                .name = "lz4",
@@ -188,6 +227,9 @@ const struct compression_handler compression_handlers[] = {
                .is_compressed = is_compressed_lz4,
                .create_istream = i_stream_create_lz4,
                .create_ostream = o_stream_create_lz4,
+               .get_min_level = compression_get_min_level_lz4, /* does not actually support any of this */
+               .get_default_level = compression_get_default_level_lz4,
+               .get_max_level = compression_get_max_level_lz4,
        },
        {
                .name = "zstd",
@@ -195,6 +237,9 @@ const struct compression_handler compression_handlers[] = {
                .is_compressed = is_compressed_zstd,
                .create_istream = i_stream_create_zstd,
                .create_ostream = o_stream_create_zstd,
+               .get_min_level = compression_get_min_level_zstd,
+               .get_default_level = compression_get_default_level_zstd,
+               .get_max_level = compression_get_max_level_zstd,
        },
        {
                .name = "unsupported",
index eef9269b10e70b5c7e4f82bcb969b1b93bebd590..4d072b2bc37a22dc501f8b1579fc9df9dd4ecc83 100644 (file)
@@ -20,6 +20,52 @@ struct bzlib_ostream {
        bool flushed:1;
 };
 
+/* in bzlib, level is actually block size. From bzlib manual:
+
+   The block size affects both the compression ratio achieved,
+   and the amount of memory needed for compression and decompression.
+
+   BlockSize 1 through BlockSize 9 specify the block size to be 100,000 bytes
+   through 900,000 bytes respectively. The default is to use the maximum block
+   size.
+
+   Larger block sizes give rapidly diminishing marginal returns.
+   Most of the compression comes from the first two or three hundred k of
+   block size, a fact worth bearing in mind when using bzip2 on small machines.
+   It is also important to appreciate that the decompression memory
+   requirement is set at compression time by the choice of block size.
+
+   * In general, try and use the largest block size memory constraints
+     allow, since that maximises the compression achieved.
+   * Compression and decompression speed are virtually unaffected by block
+     size.
+
+   Another significant point applies to files which fit in a single block -
+   that means most files you'd encounter using a large block size. The
+   amount of real memory touched is proportional to the size of the file,
+   since the file is smaller than a block. For example, compressing a file
+   20,000 bytes long with the flag BlockSize 9 will cause the compressor to
+   allocate around 7600k of memory, but only touch 400k + 20000 * 8 = 560 kbytes
+   of it. Similarly, the decompressor will allocate 3700k but only
+   touch 100k + 20000 * 4 = 180 kbytes.
+*/
+
+int compression_get_min_level_bz2(void)
+{
+       return 1;
+}
+
+int compression_get_default_level_bz2(void)
+{
+       /* default is maximum level */
+       return 9;
+}
+
+int compression_get_max_level_bz2(void)
+{
+       return 9;
+}
+
 static void o_stream_bzlib_close(struct iostream_private *stream,
                                 bool close_parent)
 {
index 7c82cbee079586bec00ac67b96e9b6274a5ba4d9..360f475d7d05b11fc1f32b1e6ce79c3b0334c37b 100644 (file)
@@ -23,6 +23,23 @@ struct lz4_ostream {
        unsigned int outbuf_offset, outbuf_used;
 };
 
+/* There is no actual compression level in LZ4, so for legacy
+   reasons we allow 1-9 to avoid breaking anyone's config. */
+int compression_get_min_level_lz4(void)
+{
+       return 1;
+}
+
+int compression_get_default_level_lz4(void)
+{
+       return 1;
+}
+
+int compression_get_max_level_lz4(void)
+{
+       return 9;
+}
+
 static void o_stream_lz4_close(struct iostream_private *stream,
                               bool close_parent)
 {
index f3bf4321088bf1b3e4cefe1be15ead07b2d6ecb3..116d063e6c58e9166f2c5223991a7ae5a5e76f28 100644 (file)
@@ -27,6 +27,21 @@ struct zlib_ostream {
        bool flushed:1;
 };
 
+int compression_get_min_level_gz(void)
+{
+       return Z_NO_COMPRESSION;
+}
+
+int compression_get_default_level_gz(void)
+{
+       return Z_DEFAULT_COMPRESSION;
+}
+
+int compression_get_max_level_gz(void)
+{
+       return Z_BEST_COMPRESSION;
+}
+
 static void o_stream_zlib_close(struct iostream_private *stream,
                                bool close_parent)
 {
@@ -323,7 +338,8 @@ o_stream_create_zlib(struct ostream *output, int level, bool gz)
        struct zlib_ostream *zstream;
        int ret;
 
-       i_assert(level >= 1 && level <= 9);
+       /* accepted range is 0..9 and -1 is default compression */
+       i_assert(level >= -1 && level <= 9);
 
        zstream = i_new(struct zlib_ostream, 1);
        zstream->ostream.sendv = o_stream_zlib_sendv;
index 101d1c76309086b3dec5f8f513ecd0578e8c7bb7..ac038b559abfcc309994ed2c1604e1a1ab0532a5 100644 (file)
@@ -7,4 +7,20 @@ struct ostream *o_stream_create_bz2(struct ostream *output, int level);
 struct ostream *o_stream_create_lz4(struct ostream *output, int level);
 struct ostream *o_stream_create_zstd(struct ostream *output, int level);
 
+int compression_get_min_level_gz(void);
+int compression_get_default_level_gz(void);
+int compression_get_max_level_gz(void);
+
+int compression_get_min_level_bz2(void);
+int compression_get_default_level_bz2(void);
+int compression_get_max_level_bz2(void);
+
+int compression_get_min_level_lz4(void);
+int compression_get_default_level_lz4(void);
+int compression_get_max_level_lz4(void);
+
+int compression_get_min_level_zstd(void);
+int compression_get_default_level_zstd(void);
+int compression_get_max_level_zstd(void);
+
 #endif
index c17401d925acc1171383226f0fb8619265639af5..fa248ee98be3cc6f91c0d4f088bed9ab70a40767 100644 (file)
@@ -25,6 +25,30 @@ struct zstd_ostream {
        bool finished:1;
 };
 
+int compression_get_min_level_zstd(void)
+{
+#if HAVE_DECL_ZSTD_MINCLEVEL == 1
+       return ZSTD_minCLevel();
+#else
+       return 1;
+#endif
+}
+
+int compression_get_default_level_zstd(void)
+{
+#ifdef ZSTD_CLEVEL_DEFAULT
+       return ZSTD_CLEVEL_DEFAULT;
+#else
+       /* This means default */
+       return 0;
+#endif
+}
+
+int compression_get_max_level_zstd(void)
+{
+       return ZSTD_maxCLevel();
+}
+
 static void o_stream_zstd_write_error(struct zstd_ostream *zstream, size_t err)
 {
        ZSTD_ErrorCode errcode = zstd_version_errcode(ZSTD_getErrorCode(err));