#include <algorithm>
-Counters::Counters() : m_counters(STATS_END)
+Counters::Counters() : m_counters(static_cast<size_t>(Statistic::END))
{
}
// clang-format off
unsigned&
-Counters::operator[](size_t index)
+Counters::operator[](Statistic index)
// clang-format on
{
- if (index >= m_counters.size()) {
- m_counters.resize(index + 1);
+ const size_t i = static_cast<size_t>(index);
+ if (i >= m_counters.size()) {
+ m_counters.resize(i + 1);
}
- return m_counters.at(index);
+ return m_counters.at(i);
}
// clang-format off
unsigned
-Counters::operator[](size_t index) const
+Counters::operator[](Statistic index) const
// clang-format on
{
- return index < m_counters.size() ? m_counters.at(index) : 0;
+ const size_t i = static_cast<size_t>(index);
+ return i < m_counters.size() ? m_counters.at(i) : 0;
}
size_t
#include <vector>
+enum class Statistic;
+
// A simple wrapper around a vector of integers
// used for the statistics counters.
class Counters
public:
Counters();
- unsigned& operator[](size_t index);
- unsigned operator[](size_t index) const;
+ unsigned& operator[](Statistic index);
+ unsigned operator[](Statistic index) const;
size_t size() const;
}
}
-optional<enum stats>
+optional<Statistic>
process_arg(Context& ctx,
Args& args,
size_t& args_index,
i++;
if (i == args.size()) {
log("--ccache-skip lacks an argument");
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
state.common_args.push_back(args[i]);
return nullopt;
// Special case for -E.
if (args[i] == "-E") {
- return STATS_PREPROCESSING;
+ return Statistic::called_for_preprocessing;
}
// Handle "@file" argument.
auto file_args = Args::from_gcc_atfile(argpath);
if (!file_args) {
log("Couldn't read arg file {}", argpath);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
args.replace(i, *file_args);
&& (args[i] == "-optf" || args[i] == "--options-file")) {
if (i == args.size() - 1) {
log("Expected argument after {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
++i;
auto file_args = Args::from_gcc_atfile(*it);
if (!file_args) {
log("Couldn't read CUDA options file {}", *it);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
args.insert(i + 1, *file_args);
if (compopt_too_hard(args[i]) || Util::starts_with(args[i], "-fdump-")
|| Util::starts_with(args[i], "-MJ")) {
log("Compiler option {} is unsupported", args[i]);
- return STATS_UNSUPPORTED_OPTION;
+ return Statistic::unsupported_compiler_option;
}
// These are too hard in direct mode.
// -Xarch_* options are too hard.
if (Util::starts_with(args[i], "-Xarch_")) {
log("Unsupported compiler option: {}", args[i]);
- return STATS_UNSUPPORTED_OPTION;
+ return Statistic::unsupported_compiler_option;
}
// Handle -arch options.
&& args[i] == "-Werror")) {
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
state.compiler_only_args.push_back(args[i + 1]);
++i;
if (!config.depend_mode() || !config.direct_mode()) {
log("Compiler option {} is unsupported without direct depend mode",
args[i]);
- return STATS_CANTUSEMODULES;
+ return Statistic::could_not_use_modules;
} else if (!(config.sloppiness() & SLOPPY_MODULES)) {
log(
"You have to specify \"modules\" sloppiness when using"
" -fmodules to get hits");
- return STATS_CANTUSEMODULES;
+ return Statistic::could_not_use_modules;
}
}
if (args[i] == "-x") {
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
if (args_info.input_file.empty()) {
state.explicit_language = args[i + 1];
if (args[i] == "-o") {
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
args_info.output_obj = Util::make_relative_path(ctx, args[i + 1]);
i++;
// -MF arg
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
dep_file = args[i + 1];
i++;
// -MQ arg or -MT arg
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
state.dep_args.push_back(args[i]);
std::string relpath = Util::make_relative_path(ctx, args[i + 1]);
|| args[i] == "-fbranch-probabilities") {
if (!process_profiling_option(ctx, args[i])) {
// The failure is logged by process_profiling_option.
- return STATS_UNSUPPORTED_OPTION;
+ return Statistic::unsupported_compiler_option;
}
state.common_args.push_back(args[i]);
return nullopt;
if (args[i] == "--sysroot") {
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
state.common_args.push_back(args[i]);
auto relpath = Util::make_relative_path(ctx, args[i + 1]);
if (args[i] == "-target") {
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
state.common_args.push_back(args[i]);
state.common_args.push_back(args[i + 1]);
// from compiling the preprocessed file will not be equal to the object
// file produced when compiling without ccache.
log("Too hard option -Wp,-P detected");
- return STATS_UNSUPPORTED_OPTION;
+ return Statistic::unsupported_compiler_option;
} else if (Util::starts_with(args[i], "-Wp,-MD,")
&& args[i].find(',', 8) == std::string::npos) {
args_info.generating_dependencies = true;
if (args[i] == "--serialize-diagnostics") {
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
args_info.generating_diagnostics = true;
args_info.output_dia = Util::make_relative_path(ctx, args[i + 1]);
if (compopt_takes_path(args[i])) {
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
// In the -Xclang -include-(pch/pth) -Xclang <path> case, the path is one
if (!detect_pch(
ctx, args[i], args[i + next], next == 2, &state.found_pch)) {
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
std::string relpath = Util::make_relative_path(ctx, args[i + next]);
if (compopt_takes_arg(args[i])) {
if (i == args.size() - 1) {
log("Missing argument to {}", args[i]);
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
if (compopt_affects_cpp(args[i])) {
if (!args_info.input_file.empty()) {
if (!language_for_file(args[i]).empty()) {
log("Multiple input files: {} and {}", args_info.input_file, args[i]);
- return STATS_MULTIPLE;
+ return Statistic::multiple_source_files;
} else if (!state.found_c_opt && !state.found_dc_opt) {
log("Called for link with {}", args[i]);
if (args[i].find("conftest.") != std::string::npos) {
- return STATS_CONFTEST;
+ return Statistic::autoconf_test;
} else {
- return STATS_LINK;
+ return Statistic::called_for_link;
}
} else {
log("Unsupported source extension: {}", args[i]);
- return STATS_SOURCELANG;
+ return Statistic::unsupported_source_language;
}
}
} // namespace
-optional<enum stats>
+optional<Statistic>
process_args(Context& ctx,
Args& preprocessor_args,
Args& extra_args_to_hash,
if (args_info.input_file.empty()) {
log("No input file found");
- return STATS_NOINPUT;
+ return Statistic::no_input_file;
}
if (state.found_pch || state.found_fpch_preprocess) {
"You have to specify \"time_macros\" sloppiness when using"
" precompiled headers to get direct hits");
log("Disabling direct mode");
- return STATS_CANTUSEPCH;
+ return Statistic::could_not_use_precompiled_header;
}
}
if (!state.explicit_language.empty()) {
if (!language_is_supported(state.explicit_language)) {
log("Unsupported language: {}", state.explicit_language);
- return STATS_SOURCELANG;
+ return Statistic::unsupported_source_language;
}
args_info.actual_language = state.explicit_language;
} else {
log(
"You have to specify \"pch_defines,time_macros\" sloppiness when"
" creating precompiled headers");
- return STATS_CANTUSEPCH;
+ return Statistic::could_not_use_precompiled_header;
}
if (!state.found_c_opt && !state.found_dc_opt && !state.found_S_opt) {
// Having a separate statistic for autoconf tests is useful, as they are
// the dominant form of "called for link" in many cases.
return args_info.input_file.find("conftest.") != std::string::npos
- ? STATS_CONFTEST
- : STATS_LINK;
+ ? Statistic::autoconf_test
+ : Statistic::called_for_link;
}
}
if (args_info.actual_language.empty()) {
log("Unsupported source extension: {}", args_info.input_file);
- return STATS_SOURCELANG;
+ return Statistic::unsupported_source_language;
}
if (!config.run_second_cpp() && args_info.actual_language == "cu") {
// Don't try to second guess the compilers heuristics for stdout handling.
if (args_info.output_obj == "-") {
log("Output file is -");
- return STATS_OUTSTDOUT;
+ return Statistic::output_to_stdout;
}
if (args_info.output_obj.empty()) {
size_t pos = args_info.output_obj.rfind('.');
if (pos == std::string::npos || pos == args_info.output_obj.size() - 1) {
log("Badly formed object filename");
- return STATS_ARGS;
+ return Statistic::bad_compiler_arguments;
}
args_info.output_dwo = Util::change_extension(args_info.output_obj, ".dwo");
auto st = Stat::stat(args_info.output_obj);
if (st && !st.is_regular()) {
log("Not a regular file: {}", args_info.output_obj);
- return STATS_BADOUTPUTFILE;
+ return Statistic::bad_output_file;
}
}
auto st = Stat::stat(output_dir);
if (!st || !st.is_directory()) {
log("Directory does not exist: {}", output_dir);
- return STATS_BADOUTPUTFILE;
+ return Statistic::bad_output_file;
}
// Some options shouldn't be passed to the real compiler when it compiles
//
// Returns nullopt on success, otherwise the statistics counter that should be
// incremented.
-nonstd::optional<enum stats> process_args(Context& ctx,
- Args& preprocessor_args,
- Args& extra_args_to_hash,
- Args& compiler_args);
+nonstd::optional<Statistic> process_args(Context& ctx,
+ Args& preprocessor_args,
+ Args& extra_args_to_hash,
+ Args& compiler_args);
log(
"Found unsupported .inc"
"bin directive in source code");
- throw Failure(STATS_UNSUPPORTED_DIRECTIVE);
+ throw Failure(Statistic::unsupported_code_directive);
} else if (pump && strncmp(q, "_________", 9) == 0) {
// Unfortunately the distcc-pump wrapper outputs standard output lines:
// __________Using distcc-pump from /usr/bin
tmp_stdout.path.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600));
if (!tmp_stdout.fd) {
log("Failed to truncate {}: {}", tmp_stdout.path, strerror(errno));
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
tmp_stderr.fd = Fd(open(
tmp_stderr.path.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600));
if (!tmp_stderr.fd) {
log("Failed to truncate {}: {}", tmp_stderr.path, strerror(errno));
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
ctx.diagnostics_color_failed = true;
if (unlink(ctx.args_info.output_dwo.c_str()) != 0 && errno != ENOENT
&& errno != ESTALE) {
log("Failed to unlink {}: {}", ctx.args_info.output_dwo, strerror(errno));
- throw Failure(STATS_BADOUTPUTFILE);
+ throw Failure(Statistic::bad_output_file);
}
}
auto st = Stat::stat(tmp_stdout_path, Stat::OnError::log);
if (!st) {
// The stdout file was removed - cleanup in progress? Better bail out.
- throw Failure(STATS_MISSING);
+ throw Failure(Statistic::missing_cache_file);
}
// distcc-pump outputs lines like this:
// __________Using # distcc servers in pump mode
if (st.size() != 0 && ctx.guessed_compiler != GuessedCompiler::pump) {
log("Compiler produced stdout");
- throw Failure(STATS_STDOUT);
+ throw Failure(Statistic::compiler_produced_stdout);
}
// Merge stderr from the preprocessor (if any) and stderr from the real
// We can output stderr immediately instead of rerunning the compiler.
Util::send_to_stderr(ctx, Util::read_file(tmp_stderr_path));
- throw Failure(STATS_STATUS, status);
+ throw Failure(Statistic::compile_failed, status);
}
if (ctx.config.depend_mode()) {
assert(depend_mode_hash);
auto result_name = result_name_from_depfile(ctx, *depend_mode_hash);
if (!result_name) {
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
ctx.set_result_name(*result_name);
}
st = Stat::stat(ctx.args_info.output_obj);
if (!st) {
log("Compiler didn't produce an object file");
- throw Failure(STATS_NOOUTPUT);
+ throw Failure(Statistic::compiler_produced_no_output);
}
if (st.size() == 0) {
log("Compiler produced an empty object file");
- throw Failure(STATS_EMPTYOUTPUT);
+ throw Failure(Statistic::compiler_produced_empty_output);
}
st = Stat::stat(tmp_stderr_path, Stat::OnError::log);
if (!st) {
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
auto orig_dest_stat = Stat::stat(ctx.result_path());
auto new_dest_stat = Stat::stat(ctx.result_path(), Stat::OnError::log);
if (!new_dest_stat) {
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
stats_update_size(ctx.counter_updates,
new_dest_stat.size_on_disk()
if (status != 0) {
log("Preprocessor gave exit status {}", status);
- throw Failure(STATS_PREPROCESSOR);
+ throw Failure(Statistic::preprocessor_error);
}
hash.hash_delimiter("cpp");
bool is_pump = ctx.guessed_compiler == GuessedCompiler::pump;
if (!process_preprocessed_file(ctx, hash, stdout_path, is_pump)) {
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
hash.hash_delimiter("cppstderr");
if (!ctx.args_info.direct_i_file && !hash.hash_file(stderr_path)) {
// Somebody removed the temporary file?
log("Failed to open {}: {}", stderr_path, strerror(errno));
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
if (ctx.args_info.direct_i_file) {
hash, ctx.config.compiler_check(), ctx.orig_args[0])) {
log("Failure running compiler check command: {}",
ctx.config.compiler_check());
- throw Failure(STATS_COMPCHECK);
+ throw Failure(Statistic::compiler_check_failed);
}
}
}
auto st = Stat::stat(compiler_path, Stat::OnError::log);
if (!st) {
- throw Failure(STATS_COMPILER);
+ throw Failure(Statistic::could_not_find_compiler);
}
// Hash information about the compiler.
log("Hashing sanitize blacklist {}", sanitize_blacklist);
hash.hash("sanitizeblacklist");
if (!hash_binary_file(ctx, hash, sanitize_blacklist)) {
- throw Failure(STATS_BADEXTRAFILE);
+ throw Failure(Statistic::error_hashing_extra_file);
}
}
log("Hashing extra file {}", path);
hash.hash_delimiter("extrafile");
if (!hash_binary_file(ctx, hash, path)) {
- throw Failure(STATS_BADEXTRAFILE);
+ throw Failure(Statistic::error_hashing_extra_file);
}
}
}
if (ctx.args_info.profile_use && !hash_profile_data_file(ctx, hash)) {
log("No profile data file found");
- throw Failure(STATS_NOINPUT);
+ throw Failure(Statistic::no_input_file);
}
// Adding -arch to hash since cpp output is affected.
hash.hash_delimiter("sourcecode");
int result = hash_source_code_file(ctx, hash, ctx.args_info.input_file);
if (result & HASH_SOURCE_CODE_ERROR) {
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
if (result & HASH_SOURCE_CODE_FOUND_TIME) {
log("Disabling direct mode");
}
// Try to return the compile result from cache.
-static optional<enum stats>
+static optional<Statistic>
from_cache(Context& ctx, enum fromcache_call_mode mode)
{
UmaskScope umask_scope(ctx.original_umask);
MTR_END("cache", "from_cache");
- return mode == FROMCACHE_DIRECT_MODE ? STATS_CACHEHIT_DIR
- : STATS_CACHEHIT_CPP;
+ return mode == FROMCACHE_DIRECT_MODE ? Statistic::direct_cache_hit
+ : Statistic::preprocessed_cache_hit;
}
// Find the real compiler. We just search the PATH to find an executable of the
std::string stats_dir = fmt::format("{}/0", config.cache_dir());
if (Stat::stat(stats_dir)) {
stats_get_obsolete_limits(stats_dir, &max_files, &max_size);
- // STATS_MAXFILES and STATS_MAXSIZE was stored for each top directory.
+ // Max files and max size were stored for each top directory.
max_files *= 16;
max_size *= 16;
} else {
dup(STDERR_FILENO); // The file descriptor is intentionally leaked.
if (uncached_fd == -1) {
log("dup(2) failed: {}", strerror(errno));
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
Util::setenv("UNCACHED_ERR_FD", fmt::format("{}", uncached_fd));
}
static int cache_compilation(int argc, const char* const* argv);
-static enum stats do_cache_compilation(Context& ctx, const char* const* argv);
+static Statistic do_cache_compilation(Context& ctx, const char* const* argv);
// The entry point when invoked to cache a compilation.
static int
MTR_END("main", "find_compiler");
try {
- enum stats stat = do_cache_compilation(*ctx, argv);
+ Statistic stat = do_cache_compilation(*ctx, argv);
stats_update(*ctx, stat);
return EXIT_SUCCESS;
} catch (const Failure& e) {
- if (e.stat() != STATS_NONE) {
+ if (e.stat() != Statistic::none) {
stats_update(*ctx, e.stat());
}
}
}
-static enum stats
+static Statistic
do_cache_compilation(Context& ctx, const char* const* argv)
{
if (ctx.actual_cwd.empty()) {
log("Unable to determine current working directory: {}", strerror(errno));
- throw Failure(STATS_ERROR);
+ throw Failure(Statistic::internal_error);
}
MTR_BEGIN("main", "clean_up_internal_tempdir");
if (ctx.config.disable()) {
log("ccache is disabled");
- // STATS_CACHEMISS is a dummy to trigger stats_flush.
- throw Failure(STATS_CACHEMISS);
+ // Statistic::cache_miss is a dummy to trigger stats_flush.
+ throw Failure(Statistic::cache_miss);
}
MTR_BEGIN("main", "set_up_uncached_err");
if (ctx.config.read_only_direct()) {
log("Read-only direct mode; running real compiler");
- throw Failure(STATS_CACHEMISS);
+ throw Failure(Statistic::cache_miss);
}
if (!ctx.config.depend_mode()) {
if (ctx.config.read_only()) {
log("Read-only mode; running real compiler");
- throw Failure(STATS_CACHEMISS);
+ throw Failure(Statistic::cache_miss);
}
add_prefix(ctx, compiler_args, ctx.config.prefix_command());
update_manifest_file(ctx);
MTR_END("cache", "to_cache");
- return STATS_CACHEMISS;
+ return Statistic::cache_miss;
}
// The main program when not doing a compile.
// Throw a Failure if ccache did not succeed in getting or putting a result in
// the cache. If `exit_code` is set, just exit with that code directly,
// otherwise execute the real compiler and exit with its exit code. Also updates
-// statistics counter `stat` if it's not STATS_NONE.
+// statistics counter `stat` if it's not `Statistic::none`.
class Failure : public std::exception
{
public:
- Failure(enum stats stat, nonstd::optional<int> exit_code = nonstd::nullopt);
+ Failure(Statistic stat, nonstd::optional<int> exit_code = nonstd::nullopt);
nonstd::optional<int> exit_code() const;
- enum stats stat() const;
+ Statistic stat() const;
private:
- enum stats m_stat;
+ Statistic m_stat;
nonstd::optional<int> m_exit_code;
};
-inline Failure::Failure(enum stats stat, nonstd::optional<int> exit_code)
+inline Failure::Failure(Statistic stat, nonstd::optional<int> exit_code)
: m_stat(stat), m_exit_code(exit_code)
{
}
return m_exit_code;
}
-inline enum stats
+inline Statistic
Failure::stat() const
{
return m_stat;
static std::string format_timestamp(uint64_t timestamp);
// Statistics fields in display order.
-static struct
+static const struct
{
- enum stats stat;
+ Statistic stat;
const char* id; // for --print-stats
const char* message; // for --show-stats
format_fn format; // nullptr -> use plain integer format
unsigned flags;
} stats_info[] = {
- {STATS_ZEROTIMESTAMP,
+ {Statistic::stats_zeroed_timestamp,
"stats_zeroed_timestamp",
"stats zeroed",
format_timestamp,
FLAG_ALWAYS},
- {STATS_CACHEHIT_DIR,
+ {Statistic::direct_cache_hit,
"direct_cache_hit",
"cache hit (direct)",
nullptr,
FLAG_ALWAYS},
- {STATS_CACHEHIT_CPP,
+ {Statistic::preprocessed_cache_hit,
"preprocessed_cache_hit",
"cache hit (preprocessed)",
nullptr,
FLAG_ALWAYS},
- {STATS_CACHEMISS, "cache_miss", "cache miss", nullptr, FLAG_ALWAYS},
- {STATS_LINK, "called_for_link", "called for link", nullptr, 0},
- {STATS_PREPROCESSING,
+ {Statistic::cache_miss, "cache_miss", "cache miss", nullptr, FLAG_ALWAYS},
+ {Statistic::called_for_link,
+ "called_for_link",
+ "called for link",
+ nullptr,
+ 0},
+ {Statistic::called_for_preprocessing,
"called_for_preprocessing",
"called for preprocessing",
nullptr,
0},
- {STATS_MULTIPLE,
+ {Statistic::multiple_source_files,
"multiple_source_files",
"multiple source files",
nullptr,
0},
- {STATS_STDOUT,
+ {Statistic::compiler_produced_stdout,
"compiler_produced_stdout",
"compiler produced stdout",
nullptr,
0},
- {STATS_NOOUTPUT,
+ {Statistic::compiler_produced_no_output,
"compiler_produced_no_output",
"compiler produced no output",
nullptr,
0},
- {STATS_EMPTYOUTPUT,
+ {Statistic::compiler_produced_empty_output,
"compiler_produced_empty_output",
"compiler produced empty output",
nullptr,
0},
- {STATS_STATUS, "compile_failed", "compile failed", nullptr, 0},
- {STATS_ERROR, "internal_error", "ccache internal error", nullptr, 0},
- {STATS_PREPROCESSOR, "preprocessor_error", "preprocessor error", nullptr, 0},
- {STATS_CANTUSEPCH,
+ {Statistic::compile_failed, "compile_failed", "compile failed", nullptr, 0},
+ {Statistic::internal_error,
+ "internal_error",
+ "ccache internal error",
+ nullptr,
+ 0},
+ {Statistic::preprocessor_error,
+ "preprocessor_error",
+ "preprocessor error",
+ nullptr,
+ 0},
+ {Statistic::could_not_use_precompiled_header,
"could_not_use_precompiled_header",
"can't use precompiled header",
nullptr,
0},
- {STATS_CANTUSEMODULES,
+ {Statistic::could_not_use_modules,
"could_not_use_modules",
"can't use modules",
nullptr,
0},
- {STATS_COMPILER,
+ {Statistic::could_not_find_compiler,
"could_not_find_compiler",
"couldn't find the compiler",
nullptr,
0},
- {STATS_MISSING, "missing_cache_file", "cache file missing", nullptr, 0},
- {STATS_ARGS, "bad_compiler_arguments", "bad compiler arguments", nullptr, 0},
- {STATS_SOURCELANG,
+ {Statistic::missing_cache_file,
+ "missing_cache_file",
+ "cache file missing",
+ nullptr,
+ 0},
+ {Statistic::bad_compiler_arguments,
+ "bad_compiler_arguments",
+ "bad compiler arguments",
+ nullptr,
+ 0},
+ {Statistic::unsupported_source_language,
"unsupported_source_language",
"unsupported source language",
nullptr,
0},
- {STATS_COMPCHECK,
+ {Statistic::compiler_check_failed,
"compiler_check_failed",
"compiler check failed",
nullptr,
0},
- {STATS_CONFTEST, "autoconf_test", "autoconf compile/link", nullptr, 0},
- {STATS_UNSUPPORTED_OPTION,
+ {Statistic::autoconf_test,
+ "autoconf_test",
+ "autoconf compile/link",
+ nullptr,
+ 0},
+ {Statistic::unsupported_compiler_option,
"unsupported_compiler_option",
"unsupported compiler option",
nullptr,
0},
- {STATS_UNSUPPORTED_DIRECTIVE,
+ {Statistic::unsupported_code_directive,
"unsupported_code_directive",
"unsupported code directive",
nullptr,
0},
- {STATS_OUTSTDOUT, "output_to_stdout", "output to stdout", nullptr, 0},
- {STATS_BADOUTPUTFILE,
+ {Statistic::output_to_stdout,
+ "output_to_stdout",
+ "output to stdout",
+ nullptr,
+ 0},
+ {Statistic::bad_output_file,
"bad_output_file",
"could not write to output file",
nullptr,
0},
- {STATS_NOINPUT, "no_input_file", "no input file", nullptr, 0},
- {STATS_BADEXTRAFILE,
+ {Statistic::no_input_file, "no_input_file", "no input file", nullptr, 0},
+ {Statistic::error_hashing_extra_file,
"error_hashing_extra_file",
"error hashing extra file",
nullptr,
0},
- {STATS_NUMCLEANUPS,
+ {Statistic::cleanups_performed,
"cleanups_performed",
"cleanups performed",
nullptr,
FLAG_ALWAYS},
- {STATS_NUMFILES,
+ {Statistic::files_in_cache,
"files_in_cache",
"files in cache",
nullptr,
FLAG_NOZERO | FLAG_ALWAYS},
- {STATS_TOTALSIZE,
+ {Statistic::cache_size_kibibyte,
"cache_size_kibibyte",
"cache size",
format_size_times_1024,
FLAG_NOZERO | FLAG_ALWAYS},
- {STATS_OBSOLETE_MAXFILES,
+ {Statistic::obsolete_max_files,
"OBSOLETE",
"OBSOLETE",
nullptr,
FLAG_NOZERO | FLAG_NEVER},
- {STATS_OBSOLETE_MAXSIZE,
+ {Statistic::obsolete_max_size,
"OBSOLETE",
"OBSOLETE",
nullptr,
FLAG_NOZERO | FLAG_NEVER},
- {STATS_NONE, nullptr, nullptr, nullptr, 0}};
+ {Statistic::none, nullptr, nullptr, nullptr, 0}};
static std::string
format_size(uint64_t size)
if (p2 == p) {
break;
}
- counters[i] += val;
+ counters[static_cast<Statistic>(i)] += val;
i++;
p = p2;
}
{
AtomicFile file(path, AtomicFile::Mode::text);
for (size_t i = 0; i < counters.size(); ++i) {
- file.write(fmt::format("{}\n", counters[i]));
+ file.write(fmt::format("{}\n", counters[static_cast<Statistic>(i)]));
}
try {
file.commit();
static double
stats_hit_rate(const Counters& counters)
{
- unsigned direct = counters[STATS_CACHEHIT_DIR];
- unsigned preprocessed = counters[STATS_CACHEHIT_CPP];
+ unsigned direct = counters[Statistic::direct_cache_hit];
+ unsigned preprocessed = counters[Statistic::preprocessed_cache_hit];
unsigned hit = direct + preprocessed;
- unsigned miss = counters[STATS_CACHEMISS];
+ unsigned miss = counters[Statistic::cache_miss];
unsigned total = hit + miss;
return total > 0 ? (100.0 * hit) / total : 0.0;
}
fname = fmt::format("{}/{:x}/stats", config.cache_dir(), dir);
}
- counters[STATS_ZEROTIMESTAMP] = 0; // Don't add
+ counters[Statistic::stats_zeroed_timestamp] = 0; // Don't add
stats_read(fname, counters);
- zero_timestamp = std::max(counters[STATS_ZEROTIMESTAMP], zero_timestamp);
+ zero_timestamp =
+ std::max(counters[Statistic::stats_zeroed_timestamp], zero_timestamp);
auto st = Stat::stat(fname);
if (st && st.mtime() > *last_updated) {
*last_updated = st.mtime();
}
}
- counters[STATS_ZEROTIMESTAMP] = zero_timestamp;
+ counters[Statistic::stats_zeroed_timestamp] = zero_timestamp;
}
// Record that a number of bytes and files have been added to the cache. Size
return;
}
- counters[STATS_TOTALSIZE] += size / 1024;
- counters[STATS_NUMFILES] += files;
+ counters[Statistic::cache_size_kibibyte] += size / 1024;
+ counters[Statistic::files_in_cache] += files;
}
// Read in the stats from one directory and add to the counters.
}
stats_read(sfile, counters);
- for (int i = 0; i < STATS_END; ++i) {
- counters[i] += updates[i];
+ for (size_t i = 0; i < static_cast<size_t>(Statistic::END); ++i) {
+ counters[static_cast<Statistic>(i)] += updates[static_cast<Statistic>(i)];
}
stats_write(sfile, counters);
}
bool need_cleanup = false;
if (config.max_files() != 0
- && counters[STATS_NUMFILES] > config.max_files() / 16) {
+ && counters[Statistic::files_in_cache] > config.max_files() / 16) {
log("Need to clean up {} since it holds {} files (limit: {} files)",
subdir,
- counters[STATS_NUMFILES],
+ counters[Statistic::files_in_cache],
config.max_files() / 16);
need_cleanup = true;
}
if (config.max_size() != 0
- && counters[STATS_TOTALSIZE] > config.max_size() / 1024 / 16) {
+ && counters[Statistic::cache_size_kibibyte]
+ > config.max_size() / 1024 / 16) {
log("Need to clean up {} since it holds {} KiB (limit: {} KiB)",
subdir,
- counters[STATS_TOTALSIZE],
+ counters[Statistic::cache_size_kibibyte],
config.max_size() / 1024 / 16);
need_cleanup = true;
}
// Update a normal stat.
void
-stats_update(Context& ctx, enum stats stat)
+stats_update(Context& ctx, Statistic stat)
{
- assert(stat > STATS_NONE && stat < STATS_END);
+ assert(stat > Statistic::none && stat < Statistic::END);
ctx.counter_updates[stat] += 1;
}
// ...and display them.
for (int i = 0; stats_info[i].message; i++) {
- enum stats stat = stats_info[i].stat;
+ Statistic stat = stats_info[i].stat;
if (stats_info[i].flags & FLAG_NEVER) {
continue;
fmt::print("{:31} {}\n", stats_info[i].message, value);
}
- if (stat == STATS_CACHEMISS) {
+ if (stat == Statistic::cache_miss) {
double percent = stats_hit_rate(counters);
fmt::print("cache hit rate {:6.2f} %\n", percent);
}
counters[stats_info[i].stat] = 0;
}
}
- counters[STATS_ZEROTIMESTAMP] = timestamp;
+ counters[Statistic::stats_zeroed_timestamp] = timestamp;
stats_write(fname, counters);
}
}
Counters counters;
std::string sname = dir + "/stats";
stats_read(sname, counters);
- *maxfiles = counters[STATS_OBSOLETE_MAXFILES];
- *maxsize = static_cast<uint64_t>(counters[STATS_OBSOLETE_MAXSIZE]) * 1024;
+ *maxfiles = counters[Statistic::obsolete_max_files];
+ *maxsize =
+ static_cast<uint64_t>(counters[Statistic::obsolete_max_size]) * 1024;
}
// Set the per-directory sizes.
Lockfile lock(statsfile);
if (lock.acquired()) {
stats_read(statsfile, counters);
- counters[STATS_NUMFILES] = num_files;
- counters[STATS_TOTALSIZE] = total_size / 1024;
+ counters[Statistic::files_in_cache] = num_files;
+ counters[Statistic::cache_size_kibibyte] = total_size / 1024;
stats_write(statsfile, counters);
}
}
Lockfile lock(statsfile);
if (lock.acquired()) {
stats_read(statsfile, counters);
- counters[STATS_NUMCLEANUPS] += count;
+ counters[Statistic::cleanups_performed] += count;
stats_write(statsfile, counters);
}
}
class Context;
// Statistics fields in storage order.
-enum stats {
- STATS_NONE = 0,
- STATS_STDOUT = 1,
- STATS_STATUS = 2,
- STATS_ERROR = 3,
- STATS_CACHEMISS = 4,
- STATS_PREPROCESSOR = 5,
- STATS_COMPILER = 6,
- STATS_MISSING = 7,
- STATS_CACHEHIT_CPP = 8,
- STATS_ARGS = 9,
- STATS_LINK = 10,
- STATS_NUMFILES = 11,
- STATS_TOTALSIZE = 12,
- STATS_OBSOLETE_MAXFILES = 13,
- STATS_OBSOLETE_MAXSIZE = 14,
- STATS_SOURCELANG = 15,
- STATS_BADOUTPUTFILE = 16,
- STATS_NOINPUT = 17,
- STATS_MULTIPLE = 18,
- STATS_CONFTEST = 19,
- STATS_UNSUPPORTED_OPTION = 20,
- STATS_OUTSTDOUT = 21,
- STATS_CACHEHIT_DIR = 22,
- STATS_NOOUTPUT = 23,
- STATS_EMPTYOUTPUT = 24,
- STATS_BADEXTRAFILE = 25,
- STATS_COMPCHECK = 26,
- STATS_CANTUSEPCH = 27,
- STATS_PREPROCESSING = 28,
- STATS_NUMCLEANUPS = 29,
- STATS_UNSUPPORTED_DIRECTIVE = 30,
- STATS_ZEROTIMESTAMP = 31,
- STATS_CANTUSEMODULES = 32,
+enum class Statistic {
+ none = 0,
+ compiler_produced_stdout = 1,
+ compile_failed = 2,
+ internal_error = 3,
+ cache_miss = 4,
+ preprocessor_error = 5,
+ could_not_find_compiler = 6,
+ missing_cache_file = 7,
+ preprocessed_cache_hit = 8,
+ bad_compiler_arguments = 9,
+ called_for_link = 10,
+ files_in_cache = 11,
+ cache_size_kibibyte = 12,
+ obsolete_max_files = 13,
+ obsolete_max_size = 14,
+ unsupported_source_language = 15,
+ bad_output_file = 16,
+ no_input_file = 17,
+ multiple_source_files = 18,
+ autoconf_test = 19,
+ unsupported_compiler_option = 20,
+ output_to_stdout = 21,
+ direct_cache_hit = 22,
+ compiler_produced_no_output = 23,
+ compiler_produced_empty_output = 24,
+ error_hashing_extra_file = 25,
+ compiler_check_failed = 26,
+ could_not_use_precompiled_header = 27,
+ called_for_preprocessing = 28,
+ cleanups_performed = 29,
+ unsupported_code_directive = 30,
+ stats_zeroed_timestamp = 31,
+ could_not_use_modules = 32,
- STATS_END
+ END
};
-void stats_update(Context& ctx, enum stats stat);
+void stats_update(Context& ctx, Statistic stat);
void stats_flush(Context& ctx);
void stats_flush_to_file(const Config& config,
const std::string& sfile,
Util::write_file("foo.c", "");
CHECK(process_args(ctx, preprocessed, extra, compiler)
- == STATS_PREPROCESSING);
+ == Statistic::called_for_preprocessing);
}
TEST_CASE("dash_M_should_be_unsupported")
Util::write_file("foo.c", "");
CHECK(process_args(ctx, preprocessed, extra, compiler)
- == STATS_UNSUPPORTED_OPTION);
+ == Statistic::unsupported_compiler_option);
}
TEST_CASE("dependency_args_to_preprocessor_if_run_second_cpp_is_false")