From: Joel Rosdahl Date: Tue, 13 Sep 2022 20:00:08 +0000 (+0200) Subject: refactor: Extract timestamp logic from Manifest X-Git-Tag: v4.7~52 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3fcfd751f87a445f71525481aa5206424a8e1df4;p=thirdparty%2Fccache.git refactor: Extract timestamp logic from Manifest --- diff --git a/src/ccache.cpp b/src/ccache.cpp index ec46ca813..8edb551ce 100644 --- a/src/ccache.cpp +++ b/src/ccache.cpp @@ -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, diff --git a/src/core/Manifest.cpp b/src/core/Manifest.cpp index f2a3e9cc2..060fd930e 100644 --- a/src/core/Manifest.cpp +++ b/src/core/Manifest.cpp @@ -143,8 +143,7 @@ bool Manifest::add_result( const Digest& result_key, const std::unordered_map& 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& mf_files, const std::unordered_map& 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()) { diff --git a/src/core/Manifest.hpp b/src/core/Manifest.hpp index f277093f3..399194bc4 100644 --- a/src/core/Manifest.hpp +++ b/src/core/Manifest.hpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -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; + Manifest() = default; void read(nonstd::span data); @@ -46,8 +56,7 @@ public: bool add_result(const Digest& result_key, const std::unordered_map& 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& mf_files, const std::unordered_map& mf_file_infos, - time_t time_of_compilation, - bool save_timestamp); + const FileStater& file_state); bool result_matches(const Context& ctx,