]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Convert counters to a class (#548)
authorThomas Otto <thomas.otto@pdv-fs.de>
Sun, 1 Mar 2020 21:07:54 +0000 (22:07 +0100)
committerGitHub <noreply@github.com>
Sun, 1 Mar 2020 21:07:54 +0000 (22:07 +0100)
Also remove file writing logic from `stats_update_size()` and
delete unused declaration of `stats_timestamp()`.

15 files changed:
Makefile.in
src/Context.cpp
src/Context.hpp
src/Counters.cpp [moved from unittest/test_stats.cpp with 57% similarity]
src/Counters.hpp [moved from src/counters.hpp with 70% similarity]
src/ccache.cpp
src/ccache.hpp
src/compress.cpp
src/counters.cpp [deleted file]
src/result.cpp
src/stats.cpp
src/stats.hpp
test/suites/base.bash
unittest/main.cpp
unittest/test_counters.cpp [deleted file]

index 4657726425c82b8df2bc6e59d444f1cf4096159c..6600dd3d45f7d4f016e522f46c99d916ad405fbf 100644 (file)
@@ -40,6 +40,7 @@ non_third_party_sources = \
     src/Compressor.cpp \
     src/Config.cpp \
     src/Context.cpp \
+    src/Counters.cpp \
     src/Decompressor.cpp \
     src/NullCompressor.cpp \
     src/NullDecompressor.cpp \
@@ -53,7 +54,6 @@ non_third_party_sources = \
     src/cleanup.cpp \
     src/compopt.cpp \
     src/compress.cpp \
-    src/counters.cpp \
     src/execute.cpp \
     src/exitfn.cpp \
     src/hash.cpp \
@@ -94,12 +94,10 @@ test_suites += unittest/test_ZstdCompression.cpp
 test_suites += unittest/test_args.cpp
 test_suites += unittest/test_argument_processing.cpp
 test_suites += unittest/test_compopt.cpp
-test_suites += unittest/test_counters.cpp
 test_suites += unittest/test_hash.cpp
 test_suites += unittest/test_hashutil.cpp
 test_suites += unittest/test_legacy_util.cpp
 test_suites += unittest/test_lockfile.cpp
-test_suites += unittest/test_stats.cpp
 
 test_sources += unittest/catch2_tests.cpp
 test_sources += unittest/framework.cpp
index 58564f7ce9fc4e02d8e822a20fe0c942522175e9..aaaff793000f41dc90a946935d3e905ee3b1d3b7 100644 (file)
@@ -18,9 +18,9 @@
 
 #include "Context.hpp"
 
+#include "Counters.hpp"
 #include "Util.hpp"
 #include "args.hpp"
-#include "counters.hpp"
 
 Context::Context()
   : actual_cwd(Util::get_actual_cwd()),
@@ -38,6 +38,4 @@ Context::~Context()
     free(ignore_headers[i]);
   }
   free(ignore_headers);
-
-  counters_free(counter_updates);
 }
index 6da6f66cac2ea43e1bb2893ed980dec3435042e2..7b122ad20a3d75d161d9b06c8668ecbb9d0b1421 100644 (file)
@@ -44,10 +44,6 @@ struct Context : NonCopyable
   // Current working directory according to $PWD (falling back to getcwd(3)).
   std::string apparent_cwd;
 
-  // Full path to the statistics file in the subdirectory where the cached
-  // result belongs (<cache_dir>/<x>/stats).
-  std::string stats_file;
-
   // The original argument list.
   struct args* orig_args = nullptr;
 
@@ -94,5 +90,10 @@ struct Context : NonCopyable
   char** ignore_headers = nullptr;
   size_t ignore_headers_len = 0;
 
-  struct counters* counter_updates = nullptr;
+  // Full path to the statistics file in the subdirectory where the cached
+  // result belongs (<cache_dir>/<x>/stats).
+  std::string stats_file;
+
+  // Statistics which get written into the `stats_file` upon exit.
+  Counters counter_updates;
 };
similarity index 57%
rename from unittest/test_stats.cpp
rename to src/Counters.cpp
index 402ae1b5880605421f50db7e408c5b85fe2fed99..8c0a7b7186172f4f89216cad3ab047bcf5212b66 100644 (file)
 // this program; if not, write to the Free Software Foundation, Inc., 51
 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
-// This file contains tests for statistics handling.
+#include "Counters.hpp"
 
-#include "../src/counters.hpp"
-#include "../src/stats.hpp"
-#include "framework.hpp"
-#include "util.hpp"
+#include "stats.hpp"
 
-TEST_SUITE(stats)
+#include <algorithm>
 
-TEST(forward_compatibility)
+Counters::Counters() : m_counters(STATS_END)
 {
-  unsigned i;
-  FILE* f;
-  struct counters* counters = counters_init(0);
+}
 
-  f = fopen("stats", "w");
-  for (i = 0; i < 100; i++) {
-    fprintf(f, "%u\n", i);
+unsigned& Counters::operator[](size_t index)
+{
+  if (index >= m_counters.size()) {
+    m_counters.resize(index + 1);
   }
-  fclose(f);
-
-  stats_read("stats", counters);
-  CHECK_INT_EQ(100, counters->size);
-  CHECK_INT_EQ(73, counters->data[73]);
+  return m_counters.at(index);
+}
 
-  stats_write("stats", counters);
-  CHECK_INT_EQ(100, counters->size);
-  CHECK_INT_EQ(99, counters->data[99]);
+unsigned Counters::operator[](size_t index) const
+{
+  return index < m_counters.size() ? m_counters.at(index) : 0;
+}
 
-  counters_free(counters);
+size_t
+Counters::size() const
+{
+  return m_counters.size();
 }
 
-TEST_SUITE_END
+bool
+Counters::all_zero() const
+{
+  return !std::any_of(
+    m_counters.begin(), m_counters.end(), [](unsigned v) { return v != 0; });
+}
similarity index 70%
rename from src/counters.hpp
rename to src/Counters.hpp
index 22698e9ff96be7e7e66c8784546a22387c742cf4..1e05245e6bd2909b34177e6382b5c372ec4c93dd 100644 (file)
 
 #include "system.hpp"
 
-#include <cstddef>
+#include <vector>
 
-struct counters
+// A simple wrapper around a vector of integers
+// used for the statistics counters.
+class Counters
 {
-  unsigned* data;   // counter value
-  size_t size;      // logical array size
-  size_t allocated; // allocated size
-};
+public:
+  Counters();
+
+  unsigned& operator[](size_t index);
+  unsigned operator[](size_t index) const;
+
+  size_t size() const;
 
-struct counters* counters_init(size_t initial_size);
-void counters_resize(struct counters* c, size_t new_size);
-void counters_free(struct counters* c);
+  // Return true if all counters are zero, false otherwise.
+  bool all_zero() const;
+
+private:
+  std::vector<unsigned> m_counters;
+};
index bbad353392aeb5375d960058d530cda78cefc4ee..1431ff35c12da2b66218f0b5bb082e1e04aa360b 100644 (file)
@@ -1047,10 +1047,17 @@ update_manifest_file(Context& ctx)
     cc_log("Failed to add result name to %s", ctx.manifest_path.c_str());
   } else {
     auto st = Stat::stat(ctx.manifest_path, Stat::OnError::log);
-    stats_update_size(ctx,
-                      ctx.manifest_stats_file,
-                      st.size_on_disk() - old_st.size_on_disk(),
-                      !old_st && st ? 1 : 0);
+
+    int64_t size_delta = st.size_on_disk() - old_st.size_on_disk();
+    int nof_files_delta = !old_st && st ? 1 : 0;
+
+    if (ctx.stats_file == ctx.manifest_stats_file) {
+      stats_update_size(ctx.counter_updates, size_delta, nof_files_delta);
+    } else {
+      Counters counters;
+      stats_update_size(counters, size_delta, nof_files_delta);
+      stats_flush_to_file(ctx.config, ctx.manifest_stats_file, counters);
+    }
   }
   MTR_END("manifest", "manifest_put");
 }
@@ -1321,8 +1328,7 @@ to_cache(Context& ctx,
   if (!new_dest_stat) {
     failed(STATS_ERROR);
   }
-  stats_update_size(ctx,
-                    ctx.stats_file,
+  stats_update_size(ctx.counter_updates,
                     new_dest_stat.size_on_disk()
                       - orig_dest_stat.size_on_disk(),
                     orig_dest_stat ? 0 : 1);
index c114c64903c2fc2139e890cb9db30d2e17d1a35b..97c9f6e0ddd5bb55620bc7e03346f103ef4787cc 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "system.hpp"
 
-#include "counters.hpp"
+#include "Counters.hpp"
 #include "stats.hpp"
 
 #include "third_party/nonstd/optional.hpp"
index 055aaa73528f4eccd65820aa72833cf8cf4fd1b1..c5e17732a772468ec007ff123f31a614686a60f8 100644 (file)
@@ -127,7 +127,15 @@ recompress_file(Context& ctx,
   uint64_t new_size =
     Stat::stat(cache_file.path(), Stat::OnError::log).size_on_disk();
 
-  stats_update_size(ctx, stats_file, new_size - old_size, 0);
+  size_t size_delta = new_size - old_size;
+  if (ctx.stats_file == stats_file) {
+    stats_update_size(ctx.counter_updates, size_delta, 0);
+  } else {
+    Counters counters;
+    stats_update_size(counters, size_delta, 0);
+    stats_flush_to_file(ctx.config, stats_file, counters);
+  }
+
   cc_log("Recompression of %s done", cache_file.path().c_str());
 }
 
diff --git a/src/counters.cpp b/src/counters.cpp
deleted file mode 100644 (file)
index 6eda43a..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (C) 2010-2020 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
-
-// A simple array of unsigned integers used for the statistics counters.
-
-#include "counters.hpp"
-
-#include "legacy_util.hpp"
-
-// Allocate and initialize a struct counters. Data entries up to the size are
-// set to 0.
-struct counters*
-counters_init(size_t initial_size)
-{
-  auto c = static_cast<counters*>(x_malloc(sizeof(counters)));
-  c->data = nullptr;
-  c->size = 0;
-  c->allocated = 0;
-  counters_resize(c, initial_size);
-  return c;
-}
-
-// Free a counters struct.
-void
-counters_free(struct counters* c)
-{
-  if (c) {
-    free(c->data);
-    free(c);
-  }
-}
-
-// Set a new size. New data entries are set to 0.
-void
-counters_resize(struct counters* c, size_t new_size)
-{
-  if (new_size > c->size) {
-    bool realloc = false;
-    while (c->allocated < new_size) {
-      c->allocated += 32 + c->allocated;
-      realloc = true;
-    }
-    if (realloc) {
-      c->data = static_cast<unsigned*>(
-        x_realloc(c->data, c->allocated * sizeof(c->data[0])));
-    }
-    for (size_t i = c->size; i < new_size; i++) {
-      c->data[i] = 0;
-    }
-  }
-
-  c->size = new_size;
-}
index 558cf61a6f249e2ec0e6867a2415aa042f0ac7fe..c1f7f328f4683b0c9d6dd51c7867e44e24d8ef04 100644 (file)
@@ -417,8 +417,7 @@ write_raw_file_entry(Context& ctx,
   }
   auto new_stat = Stat::stat(raw_file);
 
-  stats_update_size(ctx,
-                    ctx.stats_file,
+  stats_update_size(ctx.counter_updates,
                     new_stat.size_on_disk() - old_stat.size_on_disk(),
                     (new_stat ? 1 : 0) - (old_stat ? 1 : 0));
 }
index 992bd6f412474df4dc134217db5af50a3c3e32b7..2008445c005da022274e1f99fe9586efa139f0b5 100644 (file)
@@ -24,8 +24,8 @@
 
 #include "AtomicFile.hpp"
 #include "Context.hpp"
+#include "Counters.hpp"
 #include "cleanup.hpp"
-#include "counters.hpp"
 #include "hashutil.hpp"
 #include "lockfile.hpp"
 #include "logging.hpp"
@@ -54,9 +54,6 @@ typedef char* (*format_fn)(uint64_t value);
 
 static char* format_size_times_1024(uint64_t size);
 static char* format_timestamp(uint64_t timestamp);
-static void stats_flush_to_file(const Config& config,
-                                std::string sfile,
-                                struct counters* updates);
 
 // Statistics fields in display order.
 static struct
@@ -219,7 +216,7 @@ format_timestamp(uint64_t timestamp)
 
 // Parse a stats file from a buffer, adding to the counters.
 static void
-parse_stats(struct counters* counters, const char* buf)
+parse_stats(Counters& counters, const char* buf)
 {
   size_t i = 0;
   const char* p = buf;
@@ -229,10 +226,7 @@ parse_stats(struct counters* counters, const char* buf)
     if (p2 == p) {
       break;
     }
-    if (counters->size < i + 1) {
-      counters_resize(counters, i + 1);
-    }
-    counters->data[i] += val;
+    counters[i] += val;
     i++;
     p = p2;
   }
@@ -240,11 +234,11 @@ parse_stats(struct counters* counters, const char* buf)
 
 // Write out a stats file.
 void
-stats_write(const std::string& path, struct counters* counters)
+stats_write(const std::string& path, const Counters& counters)
 {
   AtomicFile file(path, AtomicFile::Mode::text);
-  for (size_t i = 0; i < counters->size; ++i) {
-    file.write(fmt::format("{}\n", counters->data[i]));
+  for (size_t i = 0; i < counters.size(); ++i) {
+    file.write(fmt::format("{}\n", counters[i]));
   }
   try {
     file.commit();
@@ -255,29 +249,19 @@ stats_write(const std::string& path, struct counters* counters)
   }
 }
 
-static void
-init_counter_updates(Context& ctx)
-{
-  if (!ctx.counter_updates) {
-    ctx.counter_updates = counters_init(STATS_END);
-  }
-}
-
 static double
-stats_hit_rate(struct counters* counters)
+stats_hit_rate(const Counters& counters)
 {
-  unsigned direct = counters->data[STATS_CACHEHIT_DIR];
-  unsigned preprocessed = counters->data[STATS_CACHEHIT_CPP];
+  unsigned direct = counters[STATS_CACHEHIT_DIR];
+  unsigned preprocessed = counters[STATS_CACHEHIT_CPP];
   unsigned hit = direct + preprocessed;
-  unsigned miss = counters->data[STATS_CACHEMISS];
+  unsigned miss = counters[STATS_CACHEMISS];
   unsigned total = hit + miss;
   return total > 0 ? (100.0 * hit) / total : 0.0;
 }
 
 static void
-stats_collect(const Config& config,
-              struct counters* counters,
-              time_t* last_updated)
+stats_collect(const Config& config, Counters& counters, time_t* last_updated)
 {
   unsigned zero_timestamp = 0;
 
@@ -293,10 +277,9 @@ stats_collect(const Config& config,
       fname = format("%s/%1x/stats", config.cache_dir().c_str(), dir);
     }
 
-    counters->data[STATS_ZEROTIMESTAMP] = 0; // Don't add
+    counters[STATS_ZEROTIMESTAMP] = 0; // Don't add
     stats_read(fname, counters);
-    zero_timestamp =
-      std::max(counters->data[STATS_ZEROTIMESTAMP], zero_timestamp);
+    zero_timestamp = std::max(counters[STATS_ZEROTIMESTAMP], zero_timestamp);
     auto st = Stat::stat(fname);
     if (st && st.mtime() > *last_updated) {
       *last_updated = st.mtime();
@@ -304,39 +287,25 @@ stats_collect(const Config& config,
     free(fname);
   }
 
-  counters->data[STATS_ZEROTIMESTAMP] = zero_timestamp;
+  counters[STATS_ZEROTIMESTAMP] = zero_timestamp;
 }
 
 // Record that a number of bytes and files have been added to the cache. Size
 // is in bytes.
 void
-stats_update_size(Context& ctx,
-                  const std::string& sfile,
-                  int64_t size,
-                  int files)
+stats_update_size(Counters& counters, int64_t size, int files)
 {
   if (size == 0 && files == 0) {
     return;
   }
 
-  struct counters* updates;
-  if (sfile == ctx.stats_file) {
-    init_counter_updates(ctx);
-    updates = ctx.counter_updates;
-  } else {
-    updates = counters_init(STATS_END);
-  }
-  updates->data[STATS_NUMFILES] += files;
-  updates->data[STATS_TOTALSIZE] += size / 1024;
-  if (sfile != ctx.stats_file) {
-    stats_flush_to_file(ctx.config, sfile, updates);
-    counters_free(updates);
-  }
+  counters[STATS_TOTALSIZE] += size / 1024;
+  counters[STATS_NUMFILES] += files;
 }
 
 // Read in the stats from one directory and add to the counters.
 void
-stats_read(const std::string& sfile, struct counters* counters)
+stats_read(const std::string& sfile, Counters& counters)
 {
   char* data = read_text_file(sfile.c_str(), 1024);
   if (data) {
@@ -346,12 +315,12 @@ stats_read(const std::string& sfile, struct counters* counters)
 }
 
 // Write counter updates in updates to sfile.
-static void
+void
 stats_flush_to_file(const Config& config,
                     std::string sfile,
-                    struct counters* updates)
+                    const Counters& updates)
 {
-  if (!updates) {
+  if (updates.all_zero()) {
     return;
   }
 
@@ -363,7 +332,7 @@ stats_flush_to_file(const Config& config,
 
   if (!config.log_file().empty() || config.debug()) {
     for (auto& info : stats_info) {
-      if (updates->data[info.stat] != 0 && !(info.flags & FLAG_NOZERO)) {
+      if (updates[info.stat] != 0 && !(info.flags & FLAG_NOZERO)) {
         cc_log("Result: %s", info.message);
       }
     }
@@ -373,17 +342,6 @@ stats_flush_to_file(const Config& config,
     return;
   }
 
-  bool should_flush = false;
-  for (int i = 0; i < STATS_END; ++i) {
-    if (updates->data[i] > 0) {
-      should_flush = true;
-      break;
-    }
-  }
-  if (!should_flush) {
-    return;
-  }
-
   if (sfile.empty()) {
     // An empty sfile means that we didn't get past calculate_object_hash(), so
     // we just choose one of stats files in the 16 subdirectories.
@@ -395,10 +353,10 @@ stats_flush_to_file(const Config& config,
     return;
   }
 
-  struct counters* counters = counters_init(STATS_END);
+  Counters counters;
   stats_read(sfile, counters);
   for (int i = 0; i < STATS_END; ++i) {
-    counters->data[i] += updates->data[i];
+    counters[i] += updates[i];
   }
   stats_write(sfile, counters);
   lockfile_release(sfile.c_str());
@@ -407,18 +365,18 @@ stats_flush_to_file(const Config& config,
   bool need_cleanup = false;
 
   if (config.max_files() != 0
-      && counters->data[STATS_NUMFILES] > config.max_files() / 16) {
+      && counters[STATS_NUMFILES] > config.max_files() / 16) {
     cc_log("Need to clean up %s since it holds %u files (limit: %u files)",
            subdir.c_str(),
-           counters->data[STATS_NUMFILES],
+           counters[STATS_NUMFILES],
            config.max_files() / 16);
     need_cleanup = true;
   }
   if (config.max_size() != 0
-      && counters->data[STATS_TOTALSIZE] > config.max_size() / 1024 / 16) {
+      && counters[STATS_TOTALSIZE] > config.max_size() / 1024 / 16) {
     cc_log("Need to clean up %s since it holds %u KiB (limit: %lu KiB)",
            subdir.c_str(),
-           counters->data[STATS_TOTALSIZE],
+           counters[STATS_TOTALSIZE],
            (unsigned long)config.max_size() / 1024 / 16);
     need_cleanup = true;
   }
@@ -429,8 +387,6 @@ stats_flush_to_file(const Config& config,
     uint32_t max_files = round(config.max_files() * factor);
     clean_up_dir(subdir, max_size, max_files, [](double) {});
   }
-
-  counters_free(counters);
 }
 
 // Write counter updates in counter_updates to disk.
@@ -446,15 +402,14 @@ void
 stats_update(Context& ctx, enum stats stat)
 {
   assert(stat > STATS_NONE && stat < STATS_END);
-  init_counter_updates(ctx);
-  ctx.counter_updates->data[stat]++;
+  ctx.counter_updates[stat] += 1;
 }
 
 // Sum and display the total stats for all cache dirs.
 void
 stats_summary(const Config& config)
 {
-  struct counters* counters = counters_init(STATS_END);
+  Counters counters;
   time_t last_updated;
   stats_collect(config, counters, &last_updated);
 
@@ -478,15 +433,15 @@ stats_summary(const Config& config)
     if (stats_info[i].flags & FLAG_NEVER) {
       continue;
     }
-    if (counters->data[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) {
+    if (counters[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) {
       continue;
     }
 
     char* value;
     if (stats_info[i].format) {
-      value = stats_info[i].format(counters->data[stat]);
+      value = stats_info[i].format(counters[stat]);
     } else {
-      value = format("%8u", counters->data[stat]);
+      value = format("%8u", counters[stat]);
     }
     if (value) {
       printf("%-31s %s\n", stats_info[i].message, value);
@@ -507,15 +462,13 @@ stats_summary(const Config& config)
     printf("max cache size                  %s\n", value);
     free(value);
   }
-
-  counters_free(counters);
 }
 
 // Print machine-parsable (tab-separated) statistics counters.
 void
 stats_print(const Config& config)
 {
-  struct counters* counters = counters_init(STATS_END);
+  Counters counters;
   time_t last_updated;
   stats_collect(config, counters, &last_updated);
 
@@ -523,11 +476,9 @@ stats_print(const Config& config)
 
   for (int i = 0; stats_info[i].message; i++) {
     if (!(stats_info[i].flags & FLAG_NEVER)) {
-      printf("%s\t%u\n", stats_info[i].id, counters->data[stats_info[i].stat]);
+      printf("%s\t%u\n", stats_info[i].id, counters[stats_info[i].stat]);
     }
   }
-
-  counters_free(counters);
 }
 
 // Zero all the stats structures.
@@ -541,7 +492,7 @@ stats_zero(const Config& config)
   time_t timestamp = time(nullptr);
 
   for (int dir = 0; dir <= 0xF; dir++) {
-    struct counters* counters = counters_init(STATS_END);
+    Counters counters;
     fname = format("%s/%1x/stats", config.cache_dir().c_str(), dir);
     if (!Stat::stat(fname)) {
       // No point in trying to reset the stats file if it doesn't exist.
@@ -552,14 +503,13 @@ stats_zero(const Config& config)
       stats_read(fname, counters);
       for (unsigned i = 0; stats_info[i].message; i++) {
         if (!(stats_info[i].flags & FLAG_NOZERO)) {
-          counters->data[stats_info[i].stat] = 0;
+          counters[stats_info[i].stat] = 0;
         }
       }
-      counters->data[STATS_ZEROTIMESTAMP] = timestamp;
+      counters[STATS_ZEROTIMESTAMP] = timestamp;
       stats_write(fname, counters);
       lockfile_release(fname);
     }
-    counters_free(counters);
     free(fname);
   }
 }
@@ -570,44 +520,41 @@ stats_get_obsolete_limits(const char* dir,
                           unsigned* maxfiles,
                           uint64_t* maxsize)
 {
-  struct counters* counters = counters_init(STATS_END);
+  Counters counters;
   char* sname = format("%s/stats", dir);
   stats_read(sname, counters);
-  *maxfiles = counters->data[STATS_OBSOLETE_MAXFILES];
-  *maxsize = (uint64_t)counters->data[STATS_OBSOLETE_MAXSIZE] * 1024;
+  *maxfiles = counters[STATS_OBSOLETE_MAXFILES];
+  *maxsize = (uint64_t)counters[STATS_OBSOLETE_MAXSIZE] * 1024;
   free(sname);
-  counters_free(counters);
 }
 
 // Set the per-directory sizes.
 void
 stats_set_sizes(const char* dir, unsigned num_files, uint64_t total_size)
 {
-  struct counters* counters = counters_init(STATS_END);
+  Counters counters;
   char* statsfile = format("%s/stats", dir);
   if (lockfile_acquire(statsfile, k_lock_staleness_limit)) {
     stats_read(statsfile, counters);
-    counters->data[STATS_NUMFILES] = num_files;
-    counters->data[STATS_TOTALSIZE] = total_size / 1024;
+    counters[STATS_NUMFILES] = num_files;
+    counters[STATS_TOTALSIZE] = total_size / 1024;
     stats_write(statsfile, counters);
     lockfile_release(statsfile);
   }
   free(statsfile);
-  counters_free(counters);
 }
 
 // Count directory cleanup run.
 void
 stats_add_cleanup(const char* dir, unsigned count)
 {
-  struct counters* counters = counters_init(STATS_END);
+  Counters counters;
   char* statsfile = format("%s/stats", dir);
   if (lockfile_acquire(statsfile, k_lock_staleness_limit)) {
     stats_read(statsfile, counters);
-    counters->data[STATS_NUMCLEANUPS] += count;
+    counters[STATS_NUMCLEANUPS] += count;
     stats_write(statsfile, counters);
     lockfile_release(statsfile);
   }
   free(statsfile);
-  counters_free(counters);
 }
index c470285963fb67d0a0f45d24f9800eecd3e52955..dab1da32b6efe59ad803474cc287ce16e0b1e941 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "system.hpp"
 
+#include "Counters.hpp"
+
 #include <string>
 
 class Config;
@@ -66,18 +68,18 @@ enum stats {
 
 void stats_update(Context& ctx, enum stats stat);
 void stats_flush(void* context);
+void stats_flush_to_file(const Config& config,
+                         std::string sfile,
+                         const Counters& updates);
 void stats_zero(const Config& config);
 void stats_summary(const Config& config);
 void stats_print(const Config& config);
-void stats_update_size(Context& ctx,
-                       const std::string& sfile,
-                       int64_t size,
-                       int files);
+
+void stats_update_size(Counters& counters, int64_t size, int files);
 void stats_get_obsolete_limits(const char* dir,
                                unsigned* maxfiles,
                                uint64_t* maxsize);
 void stats_set_sizes(const char* dir, unsigned num_files, uint64_t total_size);
 void stats_add_cleanup(const char* dir, unsigned count);
-void stats_timestamp(time_t time, struct counters* counters);
-void stats_read(const std::string& path, struct counters* counters);
-void stats_write(const std::string& path, struct counters* counters);
+void stats_read(const std::string& path, Counters& counters);
+void stats_write(const std::string& path, const Counters& counters);
index 1c0b132dceed80ef0626010c52dd03dc20625164..63014219e7519fc56223cc7c2e9b047a549a3e9a 100644 (file)
@@ -350,6 +350,23 @@ base_tests() {
     expect_stat 'cache hit (preprocessed)' 0
     expect_stat 'cache miss' 0
 
+    # -------------------------------------------------------------------------
+    TEST "stats file forward compatibility"
+
+    mkdir -p "$CCACHE_DIR/4/"
+    stats_file="$CCACHE_DIR/4/stats"
+    touch "$CCACHE_DIR/timestamp_reference"
+
+    for i in `seq 101`; do
+       echo $i
+    done > "$stats_file"
+
+    expect_stat 'cache miss' 5
+    $CCACHE_COMPILE -c test1.c
+    expect_stat 'cache miss' 6
+    expect_file_contains "$stats_file" 101
+    expect_file_newer_than "$stats_file" "$CCACHE_DIR/timestamp_reference"
+
     # -------------------------------------------------------------------------
     TEST "CCACHE_RECACHE"
 
index 7db9d7255622048636498f97358edfd770d06c60..eb16c7625c8e8d18cbdff4082e41921930df066c 100644 (file)
@@ -25,23 +25,19 @@ unsigned suite_args(unsigned);
 unsigned suite_argument_processing(unsigned);
 unsigned suite_compopt(unsigned);
 unsigned suite_conf(unsigned);
-unsigned suite_counters(unsigned);
 unsigned suite_hash(unsigned);
 unsigned suite_hashutil(unsigned);
 unsigned suite_legacy_util(unsigned);
 unsigned suite_lockfile(unsigned);
-unsigned suite_stats(unsigned);
 
 const suite_fn k_legacy_suites[] = {
   &suite_args,
   &suite_argument_processing,
   &suite_compopt,
-  &suite_counters,
   &suite_hash,
   &suite_hashutil,
   &suite_legacy_util,
   &suite_lockfile,
-  &suite_stats,
   nullptr,
 };
 
diff --git a/unittest/test_counters.cpp b/unittest/test_counters.cpp
deleted file mode 100644 (file)
index a8439be..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2010-2020 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/counters.hpp"
-#include "framework.hpp"
-#include "util.hpp"
-
-TEST_SUITE(counters)
-
-TEST(counters_init_0_should_allocate_0)
-{
-  struct counters* counters = counters_init(0);
-
-  CHECK_INT_EQ(0, counters->allocated);
-  CHECK_INT_EQ(0, counters->size);
-
-  counters_free(counters);
-}
-
-TEST(counters_init_7_should_allocate_32)
-{
-  int i;
-  struct counters* counters = counters_init(7);
-
-  CHECK_INT_EQ(32, counters->allocated);
-  CHECK_INT_EQ(7, counters->size);
-  for (i = 0; i < 7; i++) {
-    CHECK_INT_EQ(0, counters->data[i]);
-  }
-
-  counters_free(counters);
-}
-
-TEST(counters_resize_50_should_allocate_96)
-{
-  struct counters* counters = counters_init(0);
-
-  CHECK_INT_EQ(0, counters->allocated);
-  counters_resize(counters, 50);
-  CHECK_INT_EQ(50, counters->size);
-  CHECK_INT_EQ(96, counters->allocated);
-
-  counters_free(counters);
-}
-
-TEST_SUITE_END