Skip to content
This repository was archived by the owner on Apr 10, 2025. It is now read-only.

Commit ccea83f

Browse files
jeffkaufmancrowell
authored andcommitted
cache-cleaning: allow people to turn it off
Support 'FileCacheCleanIntervalMs -1' to turn off cache cleaning. Fixes #1343
1 parent 59a1982 commit ccea83f

File tree

4 files changed

+75
-7
lines changed

4 files changed

+75
-7
lines changed

pagespeed/kernel/cache/file_cache.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ FileCache::FileCache(const GoogleString& path, FileSystem* file_system,
9494
message_handler_(handler),
9595
cache_policy_(policy),
9696
mutex_(thread_system->NewMutex()),
97+
next_clean_ms_(INT64_MAX),
9798
path_length_limit_(file_system_->MaxPathLength(path)),
9899
clean_time_path_(path),
99100
clean_lock_path_(path),
@@ -102,7 +103,9 @@ FileCache::FileCache(const GoogleString& path, FileSystem* file_system,
102103
evictions_(stats->GetVariable(kEvictions)),
103104
bytes_freed_in_cleanup_(stats->GetVariable(kBytesFreedInCleanup)),
104105
write_errors_(stats->GetVariable(kWriteErrors)) {
105-
next_clean_ms_ = policy->timer->NowMs() + policy->clean_interval_ms / 2;
106+
if (policy->cleaning_enabled()) {
107+
next_clean_ms_ = policy->timer->NowMs() + policy->clean_interval_ms / 2;
108+
}
106109
EnsureEndsInSlash(&clean_time_path_);
107110
StrAppend(&clean_time_path_, kCleanTimeName);
108111
EnsureEndsInSlash(&clean_lock_path_);
@@ -182,6 +185,7 @@ const int64 kEmptyDirCleanAgeSec = 60;
182185
} // namespace
183186

184187
bool FileCache::Clean(int64 target_size_bytes, int64 target_inode_count) {
188+
DCHECK(cache_policy_->cleaning_enabled());
185189
// TODO(jud): this function can delete .lock and .outputlock files, is this
186190
// problematic?
187191
message_handler_->Message(kInfo,
@@ -305,6 +309,10 @@ void FileCache::CleanWithLocking(int64 next_clean_time_ms) {
305309
}
306310

307311
bool FileCache::ShouldClean(int64* suggested_next_clean_time_ms) {
312+
if (!cache_policy_->cleaning_enabled()) {
313+
return false;
314+
}
315+
308316
bool to_return = false;
309317
const int64 now_ms = cache_policy_->timer->NowMs();
310318
{

pagespeed/kernel/cache/file_cache.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class FileCache : public CacheInterface {
5050
int64 clean_interval_ms;
5151
int64 target_size_bytes;
5252
int64 target_inode_count;
53+
bool cleaning_enabled() { return clean_interval_ms != kDisableCleaning; }
5354
private:
5455
DISALLOW_COPY_AND_ASSIGN(CachePolicy);
5556
};
@@ -88,6 +89,10 @@ class FileCache : public CacheInterface {
8889
static const char kEvictions[];
8990
static const char kWriteErrors[];
9091

92+
// What to set clean_interval_ms to in order to disable cleaning. This needs
93+
// to be -1, because that's what we have in our public documentation.
94+
static const int kDisableCleaning = -1;
95+
9196
private:
9297
class CacheCleanFunction;
9398
friend class FileCacheTest;

pagespeed/kernel/cache/file_cache_test.cc

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,7 @@ class FileCacheTest : public CacheTestBase {
5353
kTargetInodeLimit(10),
5454
stats_(thread_system_.get()) {
5555
FileCache::InitStats(&stats_);
56-
cache_.reset(new FileCache(
57-
GTestTempDir(), &file_system_, thread_system_.get(), &worker_,
58-
new FileCache::CachePolicy(&mock_timer_, &hasher_, kCleanIntervalMs,
59-
kTargetSize, kTargetInodeLimit),
60-
&stats_, &message_handler_));
56+
ResetFileCache(kCleanIntervalMs, kTargetSize);
6157
disk_checks_ = stats_.GetVariable(FileCache::kDiskChecks);
6258
cleanups_ = stats_.GetVariable(FileCache::kCleanups);
6359
evictions_ = stats_.GetVariable(FileCache::kEvictions);
@@ -69,6 +65,14 @@ class FileCacheTest : public CacheTestBase {
6965
file_system_.set_advance_time_on_update(true, &mock_timer_);
7066
}
7167

68+
void ResetFileCache(int64 clean_interval_ms, int64 target_size_bytes) {
69+
cache_.reset(new FileCache(
70+
GTestTempDir(), &file_system_, thread_system_.get(), &worker_,
71+
new FileCache::CachePolicy(&mock_timer_, &hasher_, clean_interval_ms,
72+
target_size_bytes, kTargetInodeLimit),
73+
&stats_, &message_handler_));
74+
}
75+
7276
void CheckCleanTimestamp(int64 min_time_ms) {
7377
GoogleString buffer;
7478
file_system_.ReadFile(cache_->clean_time_path_.c_str(), &buffer,
@@ -278,4 +282,54 @@ TEST_F(FileCacheTest, CheckClean) {
278282
CheckCleanTimestamp(time_ms);
279283
}
280284

285+
// Test cleaning doesn't mean deleting everything in the cache.
286+
TEST_F(FileCacheTest, CheckPartialClean) {
287+
// Set the cache capacity to be big enough to hold two entries. We clean down
288+
// to something like 75% full, though, so after cleaning only one entry will
289+
// be left.
290+
const int target_size = StrCat("Name1", "Value1",
291+
"Name2", "Value2").length();
292+
ResetFileCache(kCleanIntervalMs, target_size);
293+
294+
CheckPut("Name1", "Value1");
295+
CheckPut("Name2", "Value2");
296+
// Advance time to make sure we clean the old ones first.
297+
mock_timer_.SleepMs(1);
298+
CheckPut("Name3", "Value3");
299+
mock_timer_.SleepMs(kCleanIntervalMs + 1);
300+
301+
// The cache is now oversize. Run clean. It deletes entries 1 and 2.
302+
RunClean();
303+
304+
CheckNotFound("Name1"); // cleaned
305+
CheckNotFound("Name2"); // cleaned
306+
CheckGet("Name3", "Value3");
307+
}
308+
309+
// Test that if we disable cleaning then cleaning doesn't happen. This is the
310+
// same as CheckPartialClean, with cleaning disabled.
311+
TEST_F(FileCacheTest, CheckPartialCleanWithCleaningDisabled) {
312+
// Set the cache capacity to be big enough to hold two entries. We clean down
313+
// to something like 75% full, though, so after cleaning only one entry will
314+
// be left.
315+
const int target_size = StrCat("Name1", "Value1",
316+
"Name2", "Value2").length();
317+
ResetFileCache(FileCache::kDisableCleaning, target_size);
318+
319+
CheckPut("Name1", "Value1");
320+
CheckPut("Name2", "Value2");
321+
// Advance time for consistency with the yes-clean version above.
322+
mock_timer_.SleepMs(1);
323+
CheckPut("Name3", "Value3");
324+
mock_timer_.SleepMs(kCleanIntervalMs + 1);
325+
326+
// The cache is now oversize, but we won't clean because that's turned off.
327+
RunClean();
328+
329+
// Everything is still there.
330+
CheckGet("Name1", "Value1");
331+
CheckGet("Name2", "Value2");
332+
CheckGet("Name3", "Value3");
333+
}
334+
281335
} // namespace net_instaweb

pagespeed/system/system_rewrite_options.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ void SystemRewriteOptions::AddProperties() {
130130
AddSystemProperty(
131131
Timer::kHourMs, &SystemRewriteOptions::file_cache_clean_interval_ms_,
132132
"afcci", RewriteOptions::kFileCacheCleanIntervalMs,
133-
"Set the interval (in ms) for cleaning the file cache", true);
133+
"Set the interval (in ms) for cleaning the file cache, -1 to disable "
134+
"cleaning", true);
134135
AddSystemProperty(100 * 1024 /* 100 megabytes */,
135136
&SystemRewriteOptions::file_cache_clean_size_kb_,
136137
"afc", RewriteOptions::kFileCacheCleanSizeKb,

0 commit comments

Comments
 (0)