From: Joel Rosdahl Date: Sun, 16 Jun 2019 15:43:36 +0000 (+0200) Subject: Refactor compression type/level calculation X-Git-Tag: v4.0~941 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=30e4d6e0c8a55550bb28648b32cd99adc843c2a2;p=thirdparty%2Fccache.git Refactor compression type/level calculation In preparation for introducing a new manifest format. --- diff --git a/Makefile.in b/Makefile.in index 9e1ddecbd..0f199c4bd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -36,6 +36,7 @@ non_3pp_sources = \ src/compopt.c \ src/compr_none.c \ src/compr_zlib.c \ + src/compression.c \ src/conf.c \ src/confitems.c \ src/counters.c \ diff --git a/src/ccache.c b/src/ccache.c index 3e0e28a88..3096e640d 100644 --- a/src/ccache.c +++ b/src/ccache.c @@ -1401,8 +1401,7 @@ to_cache(struct args *args, struct hash *depend_mode_hash) } struct stat orig_dest_st; bool orig_dest_existed = stat(cached_result, &orig_dest_st) == 0; - int compression_level = conf->compression ? conf->compression_level : 0; - result_put(cached_result, filelist, compression_level); + result_put(cached_result, filelist); filelist_free(filelist); cc_log("Stored in cache: %s", cached_result); diff --git a/src/compr_none.c b/src/compr_none.c index 2aec2a22b..ccb448f22 100644 --- a/src/compr_none.c +++ b/src/compr_none.c @@ -37,7 +37,7 @@ compr_none_free(struct compr_state *handle) return ferror(output) == 0; } -struct compressor compr_none = { +struct compressor compressor_none_impl = { compr_none_init, compr_none_write, compr_none_free diff --git a/src/compr_zlib.c b/src/compr_zlib.c index 83cc28e79..a174ecf2a 100644 --- a/src/compr_zlib.c +++ b/src/compr_zlib.c @@ -92,7 +92,7 @@ compr_zlib_free(struct compr_state *handle) return success; } -struct compressor compr_zlib = { +struct compressor compressor_zlib_impl = { compr_zlib_init, compr_zlib_write, compr_zlib_free diff --git a/src/compression.c b/src/compression.c new file mode 100644 index 000000000..0523e7810 --- /dev/null +++ b/src/compression.c @@ -0,0 +1,72 @@ +// Copyright (C) 2019 Joel Rosdahl +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include "compression.h" +#include "conf.h" + +extern struct conf *conf; + +int8_t compression_level_from_config(void) +{ + return conf->compression ? conf->compression_level : 0; +} + +enum compression_type compression_type_from_config(void) +{ + return conf->compression ? COMPR_TYPE_ZLIB : COMPR_TYPE_NONE; +} + +const char *compression_type_to_string(enum compression_type type) +{ + switch (type) { + case COMPR_TYPE_NONE: + return "none"; + + case COMPR_TYPE_ZLIB: + return "zlib"; + } + + return "unknown"; +} + +struct compressor *compressor_from_type(enum compression_type type) +{ + switch (type) { + case COMPR_TYPE_NONE: + return &compressor_none_impl; + + case COMPR_TYPE_ZLIB: + return &compressor_zlib_impl; + } + + return NULL; +} + +struct decompressor *decompressor_from_type(enum compression_type type) +{ + switch (type) { + case COMPR_TYPE_NONE: + return &decompressor_none_impl; + + case COMPR_TYPE_ZLIB: + return &decompressor_zlib_impl; + + } + + return NULL; +} + + diff --git a/src/compression.h b/src/compression.h index 89bf1469f..d30b5125a 100644 --- a/src/compression.h +++ b/src/compression.h @@ -19,10 +19,21 @@ struct decompressor { bool (*free)(struct decompr_state *state); }; -extern struct compressor compr_none; -extern struct decompressor decompr_none; +enum compression_type { + COMPR_TYPE_NONE = 0, + COMPR_TYPE_ZLIB = 1 +}; + +extern struct compressor compressor_none_impl; +extern struct decompressor decompressor_none_impl; + +extern struct compressor compressor_zlib_impl; +extern struct decompressor decompressor_zlib_impl; -extern struct compressor compr_zlib; -extern struct decompressor decompr_zlib; +int8_t compression_level_from_config(void); +enum compression_type compression_type_from_config(void); +const char *compression_type_to_string(enum compression_type type); +struct compressor *compressor_from_type(enum compression_type type); +struct decompressor *decompressor_from_type(enum compression_type type); #endif diff --git a/src/decompr_none.c b/src/decompr_none.c index 4087bb957..65c8abe68 100644 --- a/src/decompr_none.c +++ b/src/decompr_none.c @@ -36,7 +36,7 @@ decompr_none_free(struct decompr_state *handle) return ferror(input) == 0; } -struct decompressor decompr_none = { +struct decompressor decompressor_none_impl = { decompr_none_init, decompr_none_read, decompr_none_free diff --git a/src/decompr_zlib.c b/src/decompr_zlib.c index 6967f66dd..e5ddada28 100644 --- a/src/decompr_zlib.c +++ b/src/decompr_zlib.c @@ -116,7 +116,7 @@ static bool decompr_zlib_free(struct decompr_state *handle) return success; } -struct decompressor decompr_zlib = { +struct decompressor decompressor_zlib_impl = { decompr_zlib_init, decompr_zlib_read, decompr_zlib_free diff --git a/src/result.c b/src/result.c index a7f7ad6b2..b5ef3261f 100644 --- a/src/result.c +++ b/src/result.c @@ -74,11 +74,6 @@ enum { REF_MARKER = 1 }; -enum { - COMPR_TYPE_NONE = 0, - COMPR_TYPE_ZLIB = 1 -}; - struct file { char *suffix; char *path; @@ -194,7 +189,7 @@ read_result( MAGIC[0], MAGIC[1], MAGIC[2], MAGIC[3]); fprintf(dump_stream, "Version: %u\n", version); fprintf(dump_stream, "Compression type: %s\n", - compr_type == COMPR_TYPE_NONE ? "none" : "zlib"); + compression_type_to_string(compr_type)); fprintf(dump_stream, "Compression level: %d\n", compr_level); fprintf(dump_stream, "Content size: %" PRIu64 "\n", content_len); } @@ -221,16 +216,8 @@ read_result( } } - switch (compr_type) { - case COMPR_TYPE_NONE: - decompressor = &decompr_none; - break; - - case COMPR_TYPE_ZLIB: - decompressor = &decompr_zlib; - break; - - default: + decompressor = decompressor_from_type(compr_type); + if (!decompressor) { *errmsg = format("Unknown compression type: %u", compr_type); goto out; } @@ -431,7 +418,7 @@ bool result_get(const char *path, struct filelist *list) return success; } -bool result_put(const char *path, struct filelist *list, int compression_level) +bool result_put(const char *path, struct filelist *list) { bool ret = false; char *tmp_file = format("%s.tmp", path); @@ -442,11 +429,14 @@ bool result_put(const char *path, struct filelist *list, int compression_level) goto out; } + int8_t compr_level = compression_level_from_config(); + enum compression_type compr_type = compression_type_from_config(); + char header[15]; memcpy(header, MAGIC, sizeof(MAGIC)); header[4] = RESULT_VERSION; - header[5] = compression_level == 0 ? COMPR_TYPE_NONE : COMPR_TYPE_ZLIB; - header[6] = compression_level; + header[5] = compr_type; + header[6] = compr_level; uint64_t content_size = sizeof(header); content_size += 1; // n_entries for (uint32_t i = 0; i < list->n_files; i++) { @@ -463,14 +453,9 @@ bool result_put(const char *path, struct filelist *list, int compression_level) goto out; } - struct compressor *compressor; - if (compression_level == 0) { - compressor = &compr_none; - } else { - compressor = &compr_zlib; - } - - struct compr_state *compr_state = compressor->init(f, compression_level); + struct compressor *compressor = compressor_from_type(compr_type); + assert(compressor); + struct compr_state *compr_state = compressor->init(f, compr_level); if (!compr_state) { cc_log("Failed to initialize compressor"); goto out; diff --git a/src/result.h b/src/result.h index aa7ce6064..e6443320d 100644 --- a/src/result.h +++ b/src/result.h @@ -10,7 +10,7 @@ void filelist_add(struct filelist *c, const char *path, const char *suffix); void filelist_free(struct filelist *c); bool result_get(const char *path, struct filelist *list); -bool result_put(const char *path, struct filelist *list, int compression_level); +bool result_put(const char *path, struct filelist *list); bool result_dump(const char *path, FILE *stream); #endif diff --git a/unittest/test_compr_zlib.c b/unittest/test_compr_zlib.c index f5bc1a142..0993da58a 100644 --- a/unittest/test_compr_zlib.c +++ b/unittest/test_compr_zlib.c @@ -23,29 +23,31 @@ TEST_SUITE(compr_zlib) TEST(zlib_small_roundtrip) { FILE *f = fopen("data.zlib", "w"); - struct compr_state *c_state = compr_zlib.init(f, -1); + struct compressor *compr_zlib = compressor_from_type(COMPR_TYPE_ZLIB); + struct compr_state *c_state = compr_zlib->init(f, -1); CHECK(c_state); - CHECK(compr_zlib.write(c_state, "foobar", 6)); + CHECK(compr_zlib->write(c_state, "foobar", 6)); - CHECK(compr_zlib.free(c_state)); + CHECK(compr_zlib->free(c_state)); fclose(f); f = fopen("data.zlib", "r"); - struct decompr_state *d_state = decompr_zlib.init(f); + struct decompressor *decompr_zlib = decompressor_from_type(COMPR_TYPE_ZLIB); + struct decompr_state *d_state = decompr_zlib->init(f); CHECK(d_state); char buffer[4]; - CHECK(decompr_zlib.read(d_state, buffer, 4)); + CHECK(decompr_zlib->read(d_state, buffer, 4)); CHECK(memcmp(buffer, "foob", 4) == 0); - CHECK(decompr_zlib.read(d_state, buffer, 2)); + CHECK(decompr_zlib->read(d_state, buffer, 2)); CHECK(memcmp(buffer, "ar", 2) == 0); // Nothing left to read. - CHECK(!decompr_zlib.read(d_state, buffer, 1)); + CHECK(!decompr_zlib->read(d_state, buffer, 1)); // Error state is remembered. - CHECK(!decompr_zlib.free(d_state)); + CHECK(!decompr_zlib->free(d_state)); fclose(f); } @@ -54,31 +56,33 @@ TEST(zlib_large_compressible_roundtrip) char data[] = "The quick brown fox jumps over the lazy dog"; FILE *f = fopen("data.zlib", "w"); - struct compr_state *c_state = compr_zlib.init(f, 1); + struct compressor *compr_zlib = compressor_from_type(COMPR_TYPE_ZLIB); + struct compr_state *c_state = compr_zlib->init(f, 1); CHECK(c_state); for (size_t i = 0; i < 1000; i++) { - CHECK(compr_zlib.write(c_state, data, sizeof(data))); + CHECK(compr_zlib->write(c_state, data, sizeof(data))); } - CHECK(compr_zlib.free(c_state)); + CHECK(compr_zlib->free(c_state)); fclose(f); f = fopen("data.zlib", "r"); - struct decompr_state *d_state = decompr_zlib.init(f); + struct decompressor *decompr_zlib = decompressor_from_type(COMPR_TYPE_ZLIB); + struct decompr_state *d_state = decompr_zlib->init(f); CHECK(d_state); char buffer[sizeof(data)]; for (size_t i = 0; i < 1000; i++) { - CHECK(decompr_zlib.read(d_state, buffer, sizeof(buffer))); + CHECK(decompr_zlib->read(d_state, buffer, sizeof(buffer))); CHECK(memcmp(buffer, data, sizeof(data)) == 0); } // Nothing left to read. - CHECK(!decompr_zlib.read(d_state, buffer, 1)); + CHECK(!decompr_zlib->read(d_state, buffer, 1)); // Error state is remembered. - CHECK(!decompr_zlib.free(d_state)); + CHECK(!decompr_zlib->free(d_state)); fclose(f); } @@ -90,23 +94,25 @@ TEST(zlib_large_uncompressible_roundtrip) } FILE *f = fopen("data.zlib", "w"); - struct compr_state *c_state = compr_zlib.init(f, 1); + struct compressor *compr_zlib = compressor_from_type(COMPR_TYPE_ZLIB); + struct compr_state *c_state = compr_zlib->init(f, 1); CHECK(c_state); - CHECK(compr_zlib.write(c_state, data, sizeof(data))); + CHECK(compr_zlib->write(c_state, data, sizeof(data))); - CHECK(compr_zlib.free(c_state)); + CHECK(compr_zlib->free(c_state)); fclose(f); f = fopen("data.zlib", "r"); - struct decompr_state *d_state = decompr_zlib.init(f); + struct decompressor *decompr_zlib = decompressor_from_type(COMPR_TYPE_ZLIB); + struct decompr_state *d_state = decompr_zlib->init(f); CHECK(d_state); char buffer[sizeof(data)]; - CHECK(decompr_zlib.read(d_state, buffer, sizeof(buffer))); + CHECK(decompr_zlib->read(d_state, buffer, sizeof(buffer))); CHECK(memcmp(buffer, data, sizeof(data)) == 0); - CHECK(decompr_zlib.free(d_state)); + CHECK(decompr_zlib->free(d_state)); fclose(f); }