]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
refactor: Extract timestamp logic from Manifest
authorJoel Rosdahl <joel@rosdahl.net>
Tue, 13 Sep 2022 20:00:08 +0000 (22:00 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Wed, 21 Sep 2022 15:06:31 +0000 (17:06 +0200)
src/ccache.cpp
src/core/Manifest.cpp
src/core/Manifest.hpp

index ec46ca81307f5b43afad8636e4003e93fcb93e34..8edb551ce08a8d41da5ce0cf8dae449e903e1a5e 100644 (file)
@@ -777,14 +777,32 @@ update_manifest(Context& ctx,
 
   MTR_SCOPE("manifest", "manifest_put");
 
-  // See comment in core::Manifest::get_file_info_index for why saving of
-  // timestamps is forced for precompiled headers.
+  // {m,c}time() have a resolution of 1 second, so we can cache the file's mtime
+  // and ctime only if they're at least one second older than
+  // time_of_compilation.
+  //
+  // ctime() may be 0, so we have to check time_of_compilation against
+  // MAX(mtime, ctime).
+  //
+  // ccache only reads mtime/ctime if file_stat_matches sloppiness is enabled,
+  // so mtimes/ctimes are stored as a dummy value (-1) if not enabled. This
+  // reduces the number of file_info entries for the common case.
   const bool save_timestamp =
     (ctx.config.sloppiness().is_enabled(core::Sloppy::file_stat_matches))
     || ctx.args_info.output_is_precompiled_header;
 
   const bool added = ctx.manifest.add_result(
-    result_key, ctx.included_files, ctx.time_of_compilation, save_timestamp);
+    result_key, ctx.included_files, [&](const std::string& path) {
+      auto stat = Stat::stat(path, Stat::OnError::log);
+      bool cache_time =
+        save_timestamp
+        && ctx.time_of_compilation > std::max(stat.mtime(), stat.ctime());
+      return core::Manifest::FileStats{
+        stat.size(),
+        stat && cache_time ? stat.mtime() : -1,
+        stat && cache_time ? stat.ctime() : -1,
+      };
+    });
   if (added) {
     core::CacheEntry::Header header(ctx.config, core::CacheEntryType::manifest);
     ctx.storage.put(manifest_key,
index f2a3e9cc2b8d78714cf3554f4aec866cba5ee25a..060fd930eda39179eaf127e99663de0c72a6b373 100644 (file)
@@ -143,8 +143,7 @@ bool
 Manifest::add_result(
   const Digest& result_key,
   const std::unordered_map<std::string, Digest>& included_files,
-  const time_t time_of_compilation,
-  const bool save_timestamp)
+  const FileStater& stat_file_function)
 {
   if (m_results.size() > k_max_manifest_entries) {
     // Normally, there shouldn't be many result entries in the manifest since
@@ -183,12 +182,8 @@ Manifest::add_result(
   file_info_indexes.reserve(included_files.size());
 
   for (const auto& [path, digest] : included_files) {
-    file_info_indexes.push_back(get_file_info_index(path,
-                                                    digest,
-                                                    mf_files,
-                                                    mf_file_infos,
-                                                    time_of_compilation,
-                                                    save_timestamp));
+    file_info_indexes.push_back(get_file_info_index(
+      path, digest, mf_files, mf_file_infos, stat_file_function));
   }
 
   ResultEntry entry{std::move(file_info_indexes), result_key};
@@ -287,8 +282,7 @@ Manifest::get_file_info_index(
   const Digest& digest,
   const std::unordered_map<std::string, uint32_t>& mf_files,
   const std::unordered_map<FileInfo, uint32_t>& mf_file_infos,
-  const time_t time_of_compilation,
-  const bool save_timestamp)
+  const FileStater& file_stater)
 {
   FileInfo fi;
 
@@ -302,34 +296,10 @@ Manifest::get_file_info_index(
 
   fi.digest = digest;
 
-  // file_stat.{m,c}time() have a resolution of 1 second, so we can cache the
-  // file's mtime and ctime only if they're at least one second older than
-  // time_of_compilation.
-  //
-  // file_stat.ctime() may be 0, so we have to check time_of_compilation against
-  // MAX(mtime, ctime).
-  //
-  // ccache only reads mtime/ctime if file_stat_match sloppiness is enabled, so
-  // mtimes/ctimes are stored as a dummy value (-1) if not enabled. This reduces
-  // the number of file_info entries for the common case.
-
-  const auto file_stat = Stat::stat(path, Stat::OnError::log);
-  if (file_stat) {
-    if (save_timestamp
-        && time_of_compilation
-             > std::max(file_stat.mtime(), file_stat.ctime())) {
-      fi.mtime = file_stat.mtime();
-      fi.ctime = file_stat.ctime();
-    } else {
-      fi.mtime = -1;
-      fi.ctime = -1;
-    }
-    fi.fsize = file_stat.size();
-  } else {
-    fi.mtime = -1;
-    fi.ctime = -1;
-    fi.fsize = 0;
-  }
+  const auto file_stat = file_stater(path);
+  fi.mtime = file_stat.mtime;
+  fi.ctime = file_stat.ctime;
+  fi.fsize = file_stat.size;
 
   const auto fi_it = mf_file_infos.find(fi);
   if (fi_it != mf_file_infos.end()) {
index f277093f39929112aaf93a0d61554de5491d56db..399194bc4aa1baf04a8d8afcee6982d6dfd9640f 100644 (file)
@@ -24,6 +24,7 @@
 #include <third_party/nonstd/span.hpp>
 
 #include <cstdint>
+#include <functional>
 #include <optional>
 #include <string>
 #include <unordered_map>
@@ -38,6 +39,15 @@ class Manifest : public Serializer
 public:
   static const uint8_t k_format_version;
 
+  struct FileStats
+  {
+    uint64_t size;
+    int64_t mtime;
+    int64_t ctime;
+  };
+
+  using FileStater = std::function<FileStats(std::string)>;
+
   Manifest() = default;
 
   void read(nonstd::span<const uint8_t> data);
@@ -46,8 +56,7 @@ public:
 
   bool add_result(const Digest& result_key,
                   const std::unordered_map<std::string, Digest>& included_files,
-                  time_t time_of_compilation,
-                  bool save_timestamp);
+                  const FileStater& stat_file);
 
   // core::Serializer
   uint32_t serialized_size() const override;
@@ -56,13 +65,6 @@ public:
   void inspect(FILE* stream) const;
 
 private:
-  struct FileStats
-  {
-    uint64_t size;
-    int64_t mtime;
-    int64_t ctime;
-  };
-
   struct FileInfo
   {
     uint32_t index; // Index to m_files.
@@ -95,8 +97,7 @@ private:
     const Digest& digest,
     const std::unordered_map<std::string, uint32_t>& mf_files,
     const std::unordered_map<FileInfo, uint32_t>& mf_file_infos,
-    time_t time_of_compilation,
-    bool save_timestamp);
+    const FileStater& file_state);
 
   bool
   result_matches(const Context& ctx,