Clear the entire cache, removing all cached files, but keeping the
configuration file.
+*`--evict-older-than`* _NUM_::
+
+ This is another cleanup mechanism (independent of max_files and max_size).
+ It instructs ccache to perform cleanup based on age of the stored files.
+ The value _NUM_ is duration and means any cache entry older than it from CURRENT_TIME
+ should be deleted. _NUM_ should be an unsigned number with a suffix:
+ d(ays)/s(econds).
+ This cleanup can be performed from the cli with this option only. During the
+ cleanup max_files/max_size will not be taken into consideration.
+
*`-h`*, *`--help`*::
Print an options summary page.
file << data;
}
+unsigned
+parse_duration_with_suffix_to_seconds(const std::string& value)
+{
+ size_t end;
+ long result;
+ bool failed = false;
+
+ try {
+ result = std::stol(value, &end, 10);
+ } catch (std::exception&) {
+ failed = true;
+ }
+
+ if (failed || result < 0) {
+ throw Error(fmt::format("invalid unsigned integer: \"{}\"", value));
+ }
+
+ if (end + 1 != value.size()) {
+ throw Error(
+ fmt::format("Invalid suffix, Supported: d(ay)/s(econd): \"{}\"", value));
+ }
+
+ switch (value[end]) {
+ case 'd':
+ result *= 24 * 3600;
+ case 's':
+ break;
+ default:
+ throw Error(
+ fmt::format("Invalid suffix, Supported: d(ay)/s(econd): \"{}\"", value));
+ }
+ return result;
+}
} // namespace Util
const std::string& data,
std::ios_base::openmode open_mode = std::ios::binary);
+// Parse the given string into an unsigned integer. Then based on suffix
+// provided convert the number to seconds possible suffixes = d(ays)/s(econds)
+//
+// Throws `Error` for any other suffix
+// Throws `Error` if parse value is <0
+unsigned parse_duration_with_suffix_to_seconds(const std::string& value);
+
} // namespace Util
(normally not needed as this is done
automatically)
-C, --clear clear the cache completely (except configuration)
+ --evict-older-than N delete files older than N (days/seconds) (this will not
+ take max_files, max_size into consideration).
+ N should be an unsigned number with a suffix:
+ d(ays)/s(econds).
-F, --max-files NUM set maximum number of files in cache to NUM (use 0
for no limit)
-M, --max-size SIZE set maximum size of cache to SIZE (use 0 for no
DUMP_MANIFEST,
DUMP_RESULT,
EXTRACT_RESULT,
+ EVICT_OLDER_THAN,
HASH_FILE,
PRINT_STATS,
};
{"dump-manifest", required_argument, nullptr, DUMP_MANIFEST},
{"dump-result", required_argument, nullptr, DUMP_RESULT},
{"extract-result", required_argument, nullptr, EXTRACT_RESULT},
+ {"evict-older-than", required_argument, nullptr, EVICT_OLDER_THAN},
{"get-config", required_argument, nullptr, 'k'},
{"hash-file", required_argument, nullptr, HASH_FILE},
{"help", no_argument, nullptr, 'h'},
return error ? EXIT_FAILURE : EXIT_SUCCESS;
}
+ case EVICT_OLDER_THAN: {
+ unsigned seconds = Util::parse_duration_with_suffix_to_seconds(optarg);
+ ProgressBar progress_bar("Clearing ...");
+ clean_old(
+ ctx, [&](double progress) { progress_bar.update(progress); }, seconds);
+ if (isatty(STDOUT_FILENO)) {
+ printf("\n");
+ }
+ break;
+ }
+
case HASH_FILE: {
Hash hash;
if (str_eq(optarg, "-")) {
clean_up_dir(const std::string& subdir,
uint64_t max_size,
uint32_t max_files,
+ time_t max_age,
const Util::ProgressReceiver& progress_receiver)
{
cc_log("Cleaning up cache directory %s", subdir.c_str());
}
if ((max_size == 0 || cache_size <= max_size)
- && (max_files == 0 || files_in_cache <= max_files)) {
+ && (max_files == 0 || files_in_cache <= max_files)
+ && (max_age == 0 || file->lstat().mtime() > (current_time - max_age))) {
break;
}
clean_up_dir(subdir,
config.max_size() / 16,
config.max_files() / 16,
+ 0,
sub_progress_receiver);
},
progress_receiver);
ctx.inode_cache.drop();
#endif
}
+
+void
+clean_old(const Context& ctx,
+ const Util::ProgressReceiver& progress_receiver,
+ time_t max_age)
+{
+ Util::for_each_level_1_subdir(
+ ctx.config.cache_dir(),
+ [&](const std::string& subdir,
+ const Util::ProgressReceiver& sub_progress_receiver) {
+ clean_up_dir(subdir, 0, 0, max_age, sub_progress_receiver);
+ },
+ progress_receiver);
+}
void clean_up_dir(const std::string& subdir,
uint64_t max_size,
uint32_t max_files,
+ time_t max_age,
const Util::ProgressReceiver& progress_receiver);
void clean_up_all(const Config& config,
void wipe_all(const Context& ctx,
const Util::ProgressReceiver& progress_receiver);
+
+void clean_old(const Context& ctx,
+ const Util::ProgressReceiver& progress_receiver,
+ time_t max_age);
double factor = config.limit_multiple() / 16;
uint64_t max_size = round(config.max_size() * factor);
uint32_t max_files = round(config.max_files() * factor);
- clean_up_dir(subdir, max_size, max_files, [](double /*progress*/) {});
+ uint32_t max_age = 0;
+ clean_up_dir(
+ subdir, max_size, max_files, max_age, [](double /*progress*/) {});
}
}
$CCACHE -c >/dev/null
expect_file_count 1 '.nfs*' $CCACHE_DIR
expect_stat 'files in cache' 10
+ # -------------------------------------------------------------------------
+ TEST "cleanup of old files by age"
+
+ prepare_cleanup_test_dir $CCACHE_DIR/a
+ touch $CCACHE_DIR/a/now.result
+ $CCACHE -F 0 -M 0 >/dev/null
+
+ $CCACHE --evict-older-than 1d >/dev/null
+ expect_file_count 1 '*.result' $CCACHE_DIR
+ expect_stat 'files in cache' 1
+
+ $CCACHE --evict-older-than 1d >/dev/null
+ expect_file_count 1 '*.result' $CCACHE_DIR
+ expect_stat 'files in cache' 1
+
+ backdate $CCACHE_DIR/a/now.result
+ $CCACHE --evict-older-than 10s >/dev/null
+ expect_stat 'files in cache' 0
}
}
}
+TEST_CASE("Util::parse_duration_with_suffix_to_seconds")
+{
+ CHECK(Util::parse_duration_with_suffix_to_seconds("0s") == 0);
+ CHECK(Util::parse_duration_with_suffix_to_seconds("2s") == 2);
+ CHECK(Util::parse_duration_with_suffix_to_seconds("1d") == 3600 * 24);
+ CHECK(Util::parse_duration_with_suffix_to_seconds("2d") == 2 * 3600 * 24);
+ CHECK_THROWS_WITH(Util::parse_duration_with_suffix_to_seconds("-2"),
+ "invalid unsigned integer: \"-2\"");
+ CHECK_THROWS_WITH(Util::parse_duration_with_suffix_to_seconds("2x"),
+ "Invalid suffix, Supported: d(ay)/s(econd): \"2x\"");
+ CHECK_THROWS_WITH(Util::parse_duration_with_suffix_to_seconds("2"),
+ "Invalid suffix, Supported: d(ay)/s(econd): \"2\"");
+}
+
TEST_SUITE_END();