]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add and use Checksum class
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 18 Sep 2019 19:17:47 +0000 (21:17 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 5 Oct 2019 21:03:48 +0000 (23:03 +0200)
The class wraps an XXH64 state.

15 files changed:
Makefile.in
dev.mk.in
src/Checksum.hpp [new file with mode: 0644]
src/common_header.cpp
src/common_header.hpp
src/compr_none.cpp
src/compr_zstd.cpp
src/compression.hpp
src/decompr_none.cpp
src/decompr_zstd.cpp
src/manifest.cpp
src/result.cpp
unittest/test_Checksum.cpp [new file with mode: 0644]
unittest/test_compr_none.cpp
unittest/test_compr_zstd.cpp

index 36d1eb53123f98aeff8733d6dc4fd0a18174b169..0b58e3e3a77b6bd7649a59f39d53bd6a6613d9a3 100644 (file)
@@ -73,6 +73,7 @@ non_third_party_objs = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(non_third_p
 ccache_sources = src/main.cpp $(base_sources)
 ccache_objs = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(ccache_sources)))
 
+test_suites += unittest/test_Checksum.cpp
 test_suites += unittest/test_Config.cpp
 test_suites += unittest/test_args.cpp
 test_suites += unittest/test_argument_processing.cpp
index c8527c96d5bb9ff6d7efa7e4b89ac754e0c167ff..4399297fe63039eabf5a8e1c9501d306ab91c0cf 100644 (file)
--- a/dev.mk.in
+++ b/dev.mk.in
@@ -37,6 +37,7 @@ built_dist_files = $(generated_sources) $(generated_docs)
 non_third_party_headers = \
     src/AtomicFile.hpp \
     src/CacheFile.hpp \
+    src/Checksum.hpp \
     src/Config.hpp \
     src/Error.hpp \
     src/ProgressBar.hpp \
diff --git a/src/Checksum.hpp b/src/Checksum.hpp
new file mode 100644 (file)
index 0000000..7033b87
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2019 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// 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
+
+#pragma once
+
+#include <cstdint>
+#include <third_party/xxhash.h>
+
+class Checksum
+{
+public:
+  Checksum();
+  ~Checksum();
+
+  void reset();
+  void update(const void* data, size_t length);
+  uint64_t digest() const;
+
+private:
+  XXH64_state_t* m_state;
+};
+
+inline Checksum::Checksum() : m_state(XXH64_createState())
+{
+  reset();
+}
+
+inline Checksum::~Checksum()
+{
+  XXH64_freeState(m_state);
+}
+
+inline void
+Checksum::reset()
+{
+  XXH64_reset(m_state, 0);
+}
+
+inline void
+Checksum::update(const void* data, size_t length)
+{
+  XXH64_update(m_state, data, length);
+}
+
+inline uint64_t
+Checksum::digest() const
+{
+  return XXH64_digest(m_state);
+}
index 83f3f09cb9df9a89df77423fbadbd56f0e85f6a3..c8baba6f06e5148572241a40c5cab78d2bcc580e 100644 (file)
@@ -29,7 +29,7 @@ common_header_initialize_for_writing(struct common_header* header,
                                      uint8_t compression_type,
                                      int8_t compression_level,
                                      uint64_t content_size,
-                                     XXH64_state_t* checksum,
+                                     Checksum& checksum,
                                      struct compressor** compressor,
                                      struct compr_state** compr_state)
 {
@@ -39,12 +39,10 @@ common_header_initialize_for_writing(struct common_header* header,
   header->compression_level = compression_level;
   header->content_size = content_size;
 
-  XXH64_reset(checksum, 0);
-
   *compressor = compressor_from_type(header->compression_type);
   assert(*compressor);
   *compr_state =
-    (*compressor)->init(output, header->compression_level, checksum);
+    (*compressor)->init(output, header->compression_level, &checksum);
   if (!*compr_state) {
     cc_log("Failed to initialize compressor");
     return false;
@@ -62,7 +60,7 @@ common_header_initialize_for_writing(struct common_header* header,
     cc_log("Failed to write common file header");
     return false;
   }
-  XXH64_update(checksum, header_bytes, sizeof(header_bytes));
+  checksum.update(header_bytes, sizeof(header_bytes));
   return true;
 }
 
@@ -73,7 +71,7 @@ common_header_initialize_for_reading(struct common_header* header,
                                      uint8_t expected_version,
                                      struct decompressor** decompressor,
                                      struct decompr_state** decompr_state,
-                                     XXH64_state_t* checksum,
+                                     Checksum* checksum,
                                      char** errmsg)
 {
   uint8_t header_bytes[COMMON_HEADER_SIZE];
@@ -132,8 +130,7 @@ common_header_initialize_for_reading(struct common_header* header,
   }
 
   if (checksum) {
-    XXH64_reset(checksum, 0);
-    XXH64_update(checksum, header_bytes, sizeof(header_bytes));
+    checksum->update(header_bytes, sizeof(header_bytes));
   }
 
   *decompr_state = (*decompressor)->init(input, checksum);
index f522eaf1d18933e84b2acf03b72fa9d02716543f..5c32fb623d82e79ab7d82b618243477a4069fc83 100644 (file)
 
 #include "system.hpp"
 
+#include "Checksum.hpp"
 #include "compression.hpp"
 
-#include "third_party/xxhash.h"
-
 #define COMMON_HEADER_SIZE 15
 
 struct common_header
@@ -55,7 +54,7 @@ bool common_header_initialize_for_writing(struct common_header* header,
                                           uint8_t compression_type,
                                           int8_t compression_level,
                                           uint64_t content_size,
-                                          XXH64_state_t* checksum,
+                                          Checksum& checksum,
                                           struct compressor** compressor,
                                           struct compr_state** compr_state);
 
@@ -77,7 +76,7 @@ bool common_header_initialize_for_reading(struct common_header* header,
                                           uint8_t expected_version,
                                           struct decompressor** decompressor,
                                           struct decompr_state** decompr_state,
-                                          XXH64_state_t* checksum,
+                                          Checksum* checksum,
                                           char** errmsg);
 
 void common_header_dump(const struct common_header* header, FILE* f);
index 7093d3aa2b10b2edf2d4cb6e1613e71c729a8b19..e9dc628deb24ef27dff7d62c8dca8a39011702d1 100644 (file)
 struct state
 {
   FILE* output;
-  XXH64_state_t* checksum;
+  Checksum* checksum;
 };
 
 static struct compr_state*
-compr_none_init(FILE* output, int8_t level, XXH64_state_t* checksum)
+compr_none_init(FILE* output, int8_t level, Checksum* checksum)
 {
   auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
   state->output = output;
@@ -47,7 +47,7 @@ compr_none_write(struct compr_state* handle, const void* data, size_t size)
   struct state* state = (struct state*)handle;
   size_t ret = fwrite(data, size, 1, state->output);
   if (state->checksum) {
-    XXH64_update(state->checksum, data, size);
+    state->checksum->update(data, size);
   }
   return ret == 1;
 }
index 3f726c7f71a1c9c8b89beadfdbba8087940d6928..dd9b41ad4f326b98da2f7d0c85fea10a77bf9d28 100644 (file)
@@ -27,7 +27,7 @@
 struct state
 {
   FILE* output;
-  XXH64_state_t* checksum;
+  Checksum* checksum;
   ZSTD_CStream* stream;
   ZSTD_inBuffer in;
   ZSTD_outBuffer out;
@@ -36,7 +36,7 @@ struct state
 };
 
 static struct compr_state*
-compr_zstd_init(FILE* output, int8_t level, XXH64_state_t* checksum)
+compr_zstd_init(FILE* output, int8_t level, Checksum* checksum)
 {
   auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
   state->output = output;
@@ -92,7 +92,7 @@ compr_zstd_write(struct compr_state* handle, const void* data, size_t size)
   struct state* state = (struct state*)handle;
 
   if (state->checksum) {
-    XXH64_update(state->checksum, data, size);
+    state->checksum->update(data, size);
   }
 
   state->in.src = data;
index 93514a71103c1f334c247f3935b119597ec98d19..4bd60d030f0984f0a0d6d4ab90d39b0f5dceed8a 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "system.hpp"
 
-#include "third_party/xxhash.h"
+#include "Checksum.hpp"
 
 struct compr_state;
 
@@ -33,7 +33,7 @@ struct compressor
   // checksum: Checksum state to update (NULL for no checksum).
   struct compr_state* (*init)(FILE* output,
                               int8_t compression_level,
-                              XXH64_state_t* checksum);
+                              Checksum* checksum);
 
   // Get the actual compression level that will be used.
   int8_t (*get_actual_compression_level)(struct compr_state* state);
@@ -61,7 +61,7 @@ struct decompressor
   //
   // input: The file to read compressed data from.
   // checksum: Checksum state to update (NULL for no checksum).
-  struct decompr_state* (*init)(FILE* input, XXH64_state_t* checksum);
+  struct decompr_state* (*init)(FILE* input, Checksum* checksum);
 
   // Decompress data.
   //
index 4c40cd49b3cc97499bbb85db7b7463879abf606a..29018d22fbf092160b64a0fbb9442b2c40559549 100644 (file)
 struct state
 {
   FILE* input;
-  XXH64_state_t* checksum;
+  Checksum* checksum;
   bool failed;
 };
 
 static struct decompr_state*
-decompr_none_init(FILE* input, XXH64_state_t* checksum)
+decompr_none_init(FILE* input, Checksum* checksum)
 {
   auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
   state->input = input;
@@ -42,7 +42,7 @@ decompr_none_read(struct decompr_state* handle, void* data, size_t size)
 
   bool result = fread(data, 1, size, state->input) == size;
   if (result && state->checksum) {
-    XXH64_update(state->checksum, data, size);
+    state->checksum->update(data, size);
   }
   if (!result) {
     state->failed = true;
index 9fb895c311e08d5e4c06776d8c068c1b9f093338..e187abc330ec06f9812d0aac1b95bf9f818cf63a 100644 (file)
@@ -30,7 +30,7 @@ enum stream_state {
 struct state
 {
   FILE* input;
-  XXH64_state_t* checksum;
+  Checksum* checksum;
   char input_buffer[READ_BUFFER_SIZE];
   size_t input_size;
   size_t input_consumed;
@@ -41,7 +41,7 @@ struct state
 };
 
 static struct decompr_state*
-decompr_zstd_init(FILE* input, XXH64_state_t* checksum)
+decompr_zstd_init(FILE* input, Checksum* checksum)
 {
   auto state = static_cast<struct state*>(malloc(sizeof(struct state)));
 
@@ -95,7 +95,7 @@ decompr_zstd_read(struct decompr_state* handle, void* data, size_t size)
       return false;
     }
     if (state->checksum) {
-      XXH64_update(state->checksum, state->out.dst, state->out.pos);
+      state->checksum->update(state->out.dst, state->out.pos);
     }
     if (ret == 0) {
       state->stream_state = STREAM_STATE_END;
index f54da6df5ea1fb4363afea41731a463aebc2aec8..527f999e6a08a15db976d303538f1bc1b167f7e3 100644 (file)
 
 #include "manifest.hpp"
 
+#include "Checksum.hpp"
 #include "ccache.hpp"
 #include "common_header.hpp"
 #include "compression.hpp"
 #include "hashutil.hpp"
 #include "int_bytes_conversion.hpp"
 
-#include "third_party/xxhash.h"
-
 // Manifest data format
 // ====================
 //
@@ -145,7 +144,9 @@ template<> struct hash<FileInfo>
   operator()(const FileInfo& file_info) const
   {
     static_assert(sizeof(FileInfo) == 48, "unexpected size"); // No padding.
-    return XXH64(&file_info, sizeof(file_info), 0);
+    Checksum checksum;
+    checksum.update(&file_info, sizeof(file_info));
+    return checksum.digest();
   }
 };
 
@@ -265,7 +266,7 @@ read_manifest(const char* path, char** errmsg)
   struct decompressor* decompressor = NULL;
   struct decompr_state* decompr_state = NULL;
   *errmsg = NULL;
-  XXH64_state_t* checksum = XXH64_createState();
+  Checksum checksum;
   uint64_t actual_checksum;
   uint64_t expected_checksum;
 
@@ -281,7 +282,7 @@ read_manifest(const char* path, char** errmsg)
                                             MANIFEST_VERSION,
                                             &decompressor,
                                             &decompr_state,
-                                            checksum,
+                                            &checksum,
                                             errmsg)) {
     goto out;
   }
@@ -315,7 +316,7 @@ read_manifest(const char* path, char** errmsg)
     READ_BYTES(mf->results[i].name.bytes, DIGEST_SIZE);
   }
 
-  actual_checksum = XXH64_digest(checksum);
+  actual_checksum = checksum.digest();
   READ_UINT64(expected_checksum);
   if (actual_checksum == expected_checksum) {
     success = true;
@@ -332,9 +333,6 @@ out:
   if (f) {
     fclose(f);
   }
-  if (checksum) {
-    XXH64_freeState(checksum);
-  }
   if (!success) {
     if (!*errmsg) {
       *errmsg = x_strdup("Corrupt manifest file");
@@ -384,7 +382,6 @@ static bool
 write_manifest(FILE* f, const struct manifest* mf)
 {
   int ret = false;
-  XXH64_state_t* checksum = XXH64_createState();
 
   uint64_t content_size = COMMON_HEADER_SIZE;
   content_size += 4; // n_files
@@ -401,6 +398,7 @@ write_manifest(FILE* f, const struct manifest* mf)
   }
   content_size += 8; // checksum
 
+  Checksum checksum;
   struct common_header header;
   struct compressor* compressor;
   struct compr_state* compr_state;
@@ -441,12 +439,11 @@ write_manifest(FILE* f, const struct manifest* mf)
     WRITE_BYTES(mf->results[i].name.bytes, DIGEST_SIZE);
   }
 
-  WRITE_UINT64(XXH64_digest(checksum));
+  WRITE_UINT64(checksum.digest());
 
   ret = compressor->free(compr_state);
 
 out:
-  XXH64_freeState(checksum);
   if (!ret) {
     cc_log("Error writing to manifest file");
   }
index c7e152e0a66407b05b46d8b9c6cfc04b47288106..b3f3d2e94303f3c4e25f19ba7ef003ab46f4cb36 100644 (file)
@@ -380,7 +380,7 @@ read_result(const char* path,
   bool success = false;
   struct decompressor* decompressor = NULL;
   struct decompr_state* decompr_state = NULL;
-  XXH64_state_t* checksum = XXH64_createState();
+  Checksum checksum;
 
   FILE* f = fopen(path, "rb");
   if (!f) {
@@ -395,7 +395,7 @@ read_result(const char* path,
                                             RESULT_VERSION,
                                             &decompressor,
                                             &decompr_state,
-                                            checksum,
+                                            &checksum,
                                             errmsg)) {
     goto out;
   }
@@ -439,7 +439,7 @@ read_result(const char* path,
   }
 
   {
-    uint64_t actual_checksum = XXH64_digest(checksum);
+    uint64_t actual_checksum = checksum.digest();
     uint64_t expected_checksum;
     READ_UINT64(expected_checksum);
 
@@ -459,9 +459,6 @@ out:
   if (f) {
     fclose(f);
   }
-  if (checksum) {
-    XXH64_freeState(checksum);
-  }
   if (!success && !cache_miss && !*errmsg) {
     *errmsg = x_strdup("Corrupt result");
   }
@@ -609,7 +606,7 @@ static bool
 write_result(const struct result_files* list,
              struct compressor* compressor,
              struct compr_state* compr_state,
-             XXH64_state_t* checksum,
+             Checksum& checksum,
              const char* result_path_in_cache)
 {
   WRITE_BYTE(list->n_files);
@@ -624,7 +621,7 @@ write_result(const struct result_files* list,
     }
   }
 
-  WRITE_UINT64(XXH64_digest(checksum));
+  WRITE_UINT64(checksum.digest());
 
   return true;
 
@@ -656,7 +653,7 @@ bool
 result_put(const char* path, struct result_files* list)
 {
   bool ret = false;
-  XXH64_state_t* checksum = XXH64_createState();
+  Checksum checksum;
   bool ok;
   uint64_t content_size;
 
@@ -715,9 +712,6 @@ out:
   if (f) {
     fclose(f);
   }
-  if (checksum) {
-    XXH64_freeState(checksum);
-  }
   return ret;
 }
 
diff --git a/unittest/test_Checksum.cpp b/unittest/test_Checksum.cpp
new file mode 100644 (file)
index 0000000..0c53593
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (C) 2011-2019 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// 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 "../src/Checksum.hpp"
+
+#include <catch.hpp>
+
+TEST_CASE("Checksums")
+{
+  Checksum checksum;
+  CHECK(checksum.digest() == 0xef46db3751d8e999);
+
+  checksum.update("foo", 3);
+  CHECK(checksum.digest() == 0x33bf00a859c4ba3f);
+
+  checksum.update("t", 1);
+  CHECK(checksum.digest() == 0xef78250064b0eea7);
+
+  checksum.reset();
+  CHECK(checksum.digest() == 0xef46db3751d8e999);
+}
index f19704c0c655213ce3681eb5abb52d6ee9cf7746..69563c95f33ba24da56e28812d21602f0f27537b 100644 (file)
@@ -26,12 +26,11 @@ TEST(small_roundtrip)
 {
   const uint64_t expected_foobar_checksum = 0xa2aa05ed9085aaf9ULL;
 
-  XXH64_state_t* checksum = XXH64_createState();
-  XXH64_reset(checksum, 0);
+  Checksum checksum;
 
   FILE* f = fopen("data.uncompressed", "w");
   struct compressor* compr_none = compressor_from_type(COMPR_TYPE_NONE);
-  struct compr_state* c_state = compr_none->init(f, -1, checksum);
+  struct compr_state* c_state = compr_none->init(f, -1, &checksum);
   CHECK(c_state);
 
   CHECK(compr_none->write(c_state, "foobar", 6));
@@ -39,12 +38,12 @@ TEST(small_roundtrip)
   CHECK(compr_none->free(c_state));
   fclose(f);
 
-  CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
+  CHECK_INT_EQ(checksum.digest(), expected_foobar_checksum);
 
-  XXH64_reset(checksum, 0);
+  checksum.reset();
   f = fopen("data.uncompressed", "r");
   struct decompressor* decompr_none = decompressor_from_type(COMPR_TYPE_NONE);
-  struct decompr_state* d_state = decompr_none->init(f, checksum);
+  struct decompr_state* d_state = decompr_none->init(f, &checksum);
   CHECK(d_state);
 
   char buffer[4];
@@ -60,9 +59,7 @@ TEST(small_roundtrip)
   CHECK(!decompr_none->free(d_state));
   fclose(f);
 
-  CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
-
-  XXH64_freeState(checksum);
+  CHECK_INT_EQ(checksum.digest(), expected_foobar_checksum);
 }
 
 TEST_SUITE_END
index 393bb87649e44f2e03642d54020f30795fbce1f3..3a4859a9a28ac71de2ae3283b17e2160f85742ff 100644 (file)
@@ -26,12 +26,11 @@ TEST(small_roundtrip)
 {
   const uint64_t expected_foobar_checksum = 0xa2aa05ed9085aaf9ULL;
 
-  XXH64_state_t* checksum = XXH64_createState();
-  XXH64_reset(checksum, 0);
+  Checksum checksum;
 
   FILE* f = fopen("data.zstd", "w");
   struct compressor* compr_zstd = compressor_from_type(COMPR_TYPE_ZSTD);
-  struct compr_state* c_state = compr_zstd->init(f, -1, checksum);
+  struct compr_state* c_state = compr_zstd->init(f, -1, &checksum);
   CHECK(c_state);
 
   CHECK(compr_zstd->write(c_state, "foobar", 6));
@@ -39,12 +38,12 @@ TEST(small_roundtrip)
   CHECK(compr_zstd->free(c_state));
   fclose(f);
 
-  CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
+  CHECK_INT_EQ(checksum.digest(), expected_foobar_checksum);
 
-  XXH64_reset(checksum, 0);
+  checksum.reset();
   f = fopen("data.zstd", "r");
   struct decompressor* decompr_zstd = decompressor_from_type(COMPR_TYPE_ZSTD);
-  struct decompr_state* d_state = decompr_zstd->init(f, checksum);
+  struct decompr_state* d_state = decompr_zstd->init(f, &checksum);
   CHECK(d_state);
 
   char buffer[4];
@@ -60,9 +59,7 @@ TEST(small_roundtrip)
   CHECK(!decompr_zstd->free(d_state));
   fclose(f);
 
-  CHECK_INT_EQ(XXH64_digest(checksum), expected_foobar_checksum);
-
-  XXH64_freeState(checksum);
+  CHECK_INT_EQ(checksum.digest(), expected_foobar_checksum);
 }
 
 TEST(large_compressible_roundtrip)