return DurationOrErr.takeError();
Policy.Expiration = *DurationOrErr;
} else if (Key == "cache_size") {
- if (Value.back() != '%')
- return make_error<StringError>("'" + Value + "' must be a percentage",
- inconvertibleErrorCode());
- StringRef SizeStr = Value.slice(0, Value.size() - 1);
+ if (Value.back() != '%')
+ return make_error<StringError>("'" + Value + "' must be a percentage",
+ inconvertibleErrorCode());
+ StringRef SizeStr = Value.drop_back();
uint64_t Size;
if (SizeStr.getAsInteger(0, Size))
return make_error<StringError>("'" + SizeStr + "' not an integer",
return make_error<StringError>("'" + SizeStr +
"' must be between 0 and 100",
inconvertibleErrorCode());
- Policy.PercentageOfAvailableSpace = Size;
+ Policy.MaxSizePercentageOfAvailableSpace = Size;
+ } else if (Key == "cache_size_bytes") {
+ uint64_t Mult = 1;
+ switch (Value.back()) {
+ case 'k':
+ Mult = 1024;
+ Value = Value.drop_back();
+ break;
+ case 'm':
+ Mult = 1024 * 1024;
+ Value = Value.drop_back();
+ break;
+ case 'g':
+ Mult = 1024 * 1024 * 1024;
+ Value = Value.drop_back();
+ break;
+ }
+ uint64_t Size;
+ if (Value.getAsInteger(0, Size))
+ return make_error<StringError>("'" + Value + "' not an integer",
+ inconvertibleErrorCode());
+ Policy.MaxSizeBytes = Size * Mult;
} else {
return make_error<StringError>("Unknown key: '" + Key + "'",
inconvertibleErrorCode());
if (!isPathDir)
return false;
- Policy.PercentageOfAvailableSpace =
- std::min(Policy.PercentageOfAvailableSpace, 100u);
+ Policy.MaxSizePercentageOfAvailableSpace =
+ std::min(Policy.MaxSizePercentageOfAvailableSpace, 100u);
if (Policy.Expiration == seconds(0) &&
- Policy.PercentageOfAvailableSpace == 0) {
+ Policy.MaxSizePercentageOfAvailableSpace == 0 &&
+ Policy.MaxSizeBytes == 0) {
DEBUG(dbgs() << "No pruning settings set, exit early\n");
// Nothing will be pruned, early exit
return false;
writeTimestampFile(TimestampFile);
}
- bool ShouldComputeSize = (Policy.PercentageOfAvailableSpace > 0);
+ bool ShouldComputeSize =
+ (Policy.MaxSizePercentageOfAvailableSpace > 0 || Policy.MaxSizeBytes > 0);
// Keep track of space
std::set<std::pair<uint64_t, std::string>> FileSizes;
}
sys::fs::space_info SpaceInfo = ErrOrSpaceInfo.get();
auto AvailableSpace = TotalSize + SpaceInfo.free;
- auto FileAndSize = FileSizes.rbegin();
+
+ if (Policy.MaxSizePercentageOfAvailableSpace == 0)
+ Policy.MaxSizePercentageOfAvailableSpace = 100;
+ if (Policy.MaxSizeBytes == 0)
+ Policy.MaxSizeBytes = AvailableSpace;
+ auto TotalSizeTarget = std::min<uint64_t>(
+ AvailableSpace * Policy.MaxSizePercentageOfAvailableSpace / 100ull,
+ Policy.MaxSizeBytes);
+
DEBUG(dbgs() << "Occupancy: " << ((100 * TotalSize) / AvailableSpace)
- << "% target is: " << Policy.PercentageOfAvailableSpace
- << "\n");
+ << "% target is: " << Policy.MaxSizePercentageOfAvailableSpace
+ << "%, " << Policy.MaxSizeBytes << " bytes\n");
+
+ auto FileAndSize = FileSizes.rbegin();
// Remove the oldest accessed files first, till we get below the threshold
- while (((100 * TotalSize) / AvailableSpace) >
- Policy.PercentageOfAvailableSpace &&
- FileAndSize != FileSizes.rend()) {
+ while (TotalSize > TotalSizeTarget && FileAndSize != FileSizes.rend()) {
// Remove the file.
sys::fs::remove(FileAndSize->second);
// Update size
ASSERT_TRUE(bool(P));
EXPECT_EQ(std::chrono::seconds(1200), P->Interval);
EXPECT_EQ(std::chrono::hours(7 * 24), P->Expiration);
- EXPECT_EQ(75u, P->PercentageOfAvailableSpace);
+ EXPECT_EQ(75u, P->MaxSizePercentageOfAvailableSpace);
}
TEST(CachePruningPolicyParser, Interval) {
EXPECT_EQ(std::chrono::seconds(1), P->Expiration);
}
-TEST(CachePruningPolicyParser, PercentageOfAvailableSpace) {
+TEST(CachePruningPolicyParser, MaxSizePercentageOfAvailableSpace) {
auto P = parseCachePruningPolicy("cache_size=100%");
ASSERT_TRUE(bool(P));
- EXPECT_EQ(100u, P->PercentageOfAvailableSpace);
+ EXPECT_EQ(100u, P->MaxSizePercentageOfAvailableSpace);
+ EXPECT_EQ(0u, P->MaxSizeBytes);
+}
+
+TEST(CachePruningPolicyParser, MaxSizeBytes) {
+ auto P = parseCachePruningPolicy("cache_size_bytes=1");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(75u, P->MaxSizePercentageOfAvailableSpace);
+ EXPECT_EQ(1u, P->MaxSizeBytes);
+ P = parseCachePruningPolicy("cache_size_bytes=2k");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(75u, P->MaxSizePercentageOfAvailableSpace);
+ EXPECT_EQ(2u * 1024u, P->MaxSizeBytes);
+ P = parseCachePruningPolicy("cache_size_bytes=3m");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(75u, P->MaxSizePercentageOfAvailableSpace);
+ EXPECT_EQ(3u * 1024u * 1024u, P->MaxSizeBytes);
+ P = parseCachePruningPolicy("cache_size_bytes=4g");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(75u, P->MaxSizePercentageOfAvailableSpace);
+ EXPECT_EQ(4ull * 1024ull * 1024ull * 1024ull, P->MaxSizeBytes);
}
TEST(CachePruningPolicyParser, Multiple) {
ASSERT_TRUE(bool(P));
EXPECT_EQ(std::chrono::seconds(1200), P->Interval);
EXPECT_EQ(std::chrono::seconds(1), P->Expiration);
- EXPECT_EQ(50u, P->PercentageOfAvailableSpace);
+ EXPECT_EQ(50u, P->MaxSizePercentageOfAvailableSpace);
}
TEST(CachePruningPolicyParser, Errors) {
toString(parseCachePruningPolicy("cache_size=foo%").takeError()));
EXPECT_EQ("'101' must be between 0 and 100",
toString(parseCachePruningPolicy("cache_size=101%").takeError()));
+ EXPECT_EQ(
+ "'foo' not an integer",
+ toString(parseCachePruningPolicy("cache_size_bytes=foo").takeError()));
+ EXPECT_EQ(
+ "'foo' not an integer",
+ toString(parseCachePruningPolicy("cache_size_bytes=foom").takeError()));
EXPECT_EQ("Unknown key: 'foo'",
toString(parseCachePruningPolicy("foo=bar").takeError()));
}