aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-05-16 12:23:42 +0200
committerGitHub <[email protected]>2023-05-16 12:23:42 +0200
commita4ff07d68eeae66c008bfac28cb87c94a92cf257 (patch)
tree630940f228c35d29fac31ced2ba7f9fd16fca1c8 /src
parentAdded CHANGELOG.md descriptions for recent changes (diff)
downloadzen-a4ff07d68eeae66c008bfac28cb87c94a92cf257.tar.xz
zen-a4ff07d68eeae66c008bfac28cb87c94a92cf257.zip
Add `--gc-projectstore-duration-seconds` option (#281)
* Add `--gc-projectstore-duration-seconds` option * Cleanup lua gc options parsing * Remove dead configuration values * changelog
Diffstat (limited to 'src')
-rw-r--r--src/zenserver/admin/admin.cpp8
-rw-r--r--src/zenserver/cache/structuredcachestore.cpp18
-rw-r--r--src/zenserver/config.cpp22
-rw-r--r--src/zenserver/config.h32
-rw-r--r--src/zenserver/projectstore/projectstore.cpp24
-rw-r--r--src/zenserver/zenserver.cpp5
-rw-r--r--src/zenstore/compactcas.cpp29
-rw-r--r--src/zenstore/filecas.cpp4
-rw-r--r--src/zenstore/gc.cpp77
-rw-r--r--src/zenstore/include/zenstore/gc.h18
10 files changed, 140 insertions, 97 deletions
diff --git a/src/zenserver/admin/admin.cpp b/src/zenserver/admin/admin.cpp
index 3a93c9aec..c37622cb6 100644
--- a/src/zenserver/admin/admin.cpp
+++ b/src/zenserver/admin/admin.cpp
@@ -54,6 +54,14 @@ HttpAdminService::HttpAdminService(GcScheduler& Scheduler) : m_GcScheduler(Sched
}
}
+ if (auto Param = Params.GetValue("maxprojectstoreduration"); Param.empty() == false)
+ {
+ if (auto Value = ParseInt<uint64_t>(Param))
+ {
+ GcParams.MaxProjectStoreDuration = std::chrono::seconds(Value.value());
+ }
+ }
+
if (auto Param = Params.GetValue("disksizesoftlimit"); Param.empty() == false)
{
if (auto Value = ParseInt<uint64_t>(Param))
diff --git a/src/zenserver/cache/structuredcachestore.cpp b/src/zenserver/cache/structuredcachestore.cpp
index d56b3cfe2..3a6e5cbc3 100644
--- a/src/zenserver/cache/structuredcachestore.cpp
+++ b/src/zenserver/cache/structuredcachestore.cpp
@@ -1006,7 +1006,7 @@ ZenCacheDiskLayer::CacheBucket::OpenLog(const bool IsNew)
{
LogEntryCount = ReadLog(LogPath, m_LogFlushPosition);
}
- else
+ else if (fs::is_regular_file(LogPath))
{
ZEN_WARN("removing invalid cas log at '{}'", LogPath);
std::filesystem::remove(LogPath);
@@ -1512,7 +1512,7 @@ ZenCacheDiskLayer::CacheBucket::GatherReferences(GcContext& GcCtx)
NiceLatencyNs(ReadBlockLongestTimeUs));
});
- const GcClock::TimePoint ExpireTime = GcCtx.ExpireTime();
+ const GcClock::TimePoint ExpireTime = GcCtx.CacheExpireTime();
const GcClock::Tick ExpireTicks = ExpireTime.time_since_epoch().count();
@@ -2976,7 +2976,7 @@ TEST_CASE("z$.gc")
GcClock::Duration MaxDuration,
std::span<const IoHash> Cids,
std::vector<IoHash>& OutKeep) {
- GcContext GcCtx(Time - MaxDuration);
+ GcContext GcCtx(Time - MaxDuration, Time - MaxDuration);
Gc.CollectGarbage(GcCtx);
OutKeep.clear();
GcCtx.FilterCids(Cids, [&OutKeep](const IoHash& Hash) { OutKeep.push_back(Hash); });
@@ -3055,7 +3055,7 @@ TEST_CASE("z$.gc")
}
{
- GcContext GcCtx(CurrentTime - std::chrono::hours(46));
+ GcContext GcCtx(CurrentTime - std::chrono::hours(46), CurrentTime - std::chrono::hours(46));
Gc.CollectGarbage(GcCtx);
@@ -3069,7 +3069,7 @@ TEST_CASE("z$.gc")
// Move forward in time and collect again
{
- GcContext GcCtx(CurrentTime + std::chrono::minutes(2));
+ GcContext GcCtx(CurrentTime + std::chrono::minutes(2), CurrentTime + std::chrono::minutes(2));
Gc.CollectGarbage(GcCtx);
for (const auto& Key : Keys)
@@ -3099,7 +3099,7 @@ TEST_CASE("z$.gc")
}
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(2));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(2), GcClock::Now() - std::chrono::hours(2));
GcCtx.CollectSmallObjects(true);
Gc.CollectGarbage(GcCtx);
@@ -3114,7 +3114,7 @@ TEST_CASE("z$.gc")
// Move forward in time and collect again
{
- GcContext GcCtx(GcClock::Now() + std::chrono::minutes(2));
+ GcContext GcCtx(GcClock::Now() + std::chrono::minutes(2), GcClock::Now() + std::chrono::minutes(2));
GcCtx.CollectSmallObjects(true);
Zcs.Flush();
@@ -3303,7 +3303,7 @@ TEST_CASE("z$.threadedinsert") // * doctest::skip(true))
C++;
}
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
GcCtx.AddRetainedCids(KeepHashes);
Zcs.CollectGarbage(GcCtx);
@@ -3351,7 +3351,7 @@ TEST_CASE("z$.threadedinsert") // * doctest::skip(true))
C++;
}
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
GcCtx.AddRetainedCids(KeepHashes);
Zcs.CollectGarbage(GcCtx);
diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp
index 5b635b89d..0e7aac079 100644
--- a/src/zenserver/config.cpp
+++ b/src/zenserver/config.cpp
@@ -506,6 +506,13 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions)
options.add_option("gc",
"",
+ "gc-projectstore-duration-seconds",
+ "Max duration in seconds before project store entries get evicted. Default set to 1209600 (2 weeks)",
+ cxxopts::value<int32_t>(ServerOptions.GcConfig.ProjectStore.MaxDurationSeconds)->default_value("1209600"),
+ "");
+
+ options.add_option("gc",
+ "",
"disk-reserve-size",
"Size of gc disk reserve in bytes. Default set to 268435456 (256 Mb). Set to zero to disable.",
cxxopts::value<uint64_t>(ServerOptions.GcConfig.DiskReserveSize)->default_value("268435456"),
@@ -522,14 +529,14 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions)
"",
"gc-low-diskspace-threshold",
"Minimum free space on disk to allow writes to disk. Default set to 268435456 (256 Mb). Set to zero to disable.",
- cxxopts::value<uint64_t>(ServerOptions.GcConfig.Cache.MinimumFreeDiskSpaceToAllowWrites)->default_value("268435456"),
+ cxxopts::value<uint64_t>(ServerOptions.GcConfig.MinimumFreeDiskSpaceToAllowWrites)->default_value("268435456"),
"");
options.add_option("gc",
"",
"gc-disksize-softlimit",
"Garbage collection disk usage soft limit. Default set to 0 (Off).",
- cxxopts::value<uint64_t>(ServerOptions.GcConfig.Cache.DiskSizeSoftLimit)->default_value("0"),
+ cxxopts::value<uint64_t>(ServerOptions.GcConfig.DiskSizeSoftLimit)->default_value("0"),
"");
options.add_option("objectstore",
@@ -878,21 +885,16 @@ ParseConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptio
ServerOptions.GcConfig.MonitorIntervalSeconds = GcConfig.value().get_or("monitorintervalseconds", 30);
ServerOptions.GcConfig.IntervalSeconds = GcConfig.value().get_or("intervalseconds", 0);
ServerOptions.GcConfig.DiskReserveSize = GcConfig.value().get_or("diskreservesize", uint64_t(1u << 28));
+ ServerOptions.GcConfig.DiskSizeSoftLimit = GcConfig.value().get_or("disksizesoftlimit", 0);
ServerOptions.GcConfig.MinimumFreeDiskSpaceToAllowWrites = GcConfig.value().get_or("lowdiskspacethreshold", 0);
if (sol::optional<sol::table> CacheGcConfig = GcConfig.value()["cache"])
{
ServerOptions.GcConfig.Cache.MaxDurationSeconds = CacheGcConfig.value().get_or("maxdurationseconds", int32_t(0));
- ServerOptions.GcConfig.Cache.DiskSizeLimit = CacheGcConfig.value().get_or("disksizelimit", ~uint64_t(0));
- ServerOptions.GcConfig.Cache.MemorySizeLimit = CacheGcConfig.value().get_or("memorysizelimit", ~uint64_t(0));
- ServerOptions.GcConfig.Cache.DiskSizeSoftLimit = CacheGcConfig.value().get_or("disksizesoftlimit", 0);
}
-
- if (sol::optional<sol::table> CasGcConfig = GcConfig.value()["cas"])
+ if (sol::optional<sol::table> CacheGcConfig = GcConfig.value()["projectstore"])
{
- ServerOptions.GcConfig.Cas.LargeStrategySizeLimit = CasGcConfig.value().get_or("largestrategysizelimit", ~uint64_t(0));
- ServerOptions.GcConfig.Cas.SmallStrategySizeLimit = CasGcConfig.value().get_or("smallstrategysizelimit", ~uint64_t(0));
- ServerOptions.GcConfig.Cas.TinyStrategySizeLimit = CasGcConfig.value().get_or("tinystrategysizelimit", ~uint64_t(0));
+ ServerOptions.GcConfig.ProjectStore.MaxDurationSeconds = CacheGcConfig.value().get_or("maxdurationseconds", int32_t(0));
}
}
diff --git a/src/zenserver/config.h b/src/zenserver/config.h
index caf4adce7..4f63e2644 100644
--- a/src/zenserver/config.h
+++ b/src/zenserver/config.h
@@ -69,32 +69,26 @@ struct ZenUpstreamCacheConfig
struct ZenCacheEvictionPolicy
{
- uint64_t DiskSizeLimit = ~uint64_t(0);
- uint64_t MemorySizeLimit = 1024 * 1024 * 1024;
- int32_t MaxDurationSeconds = 24 * 60 * 60;
- uint64_t DiskSizeSoftLimit = 0;
- uint64_t MinimumFreeDiskSpaceToAllowWrites = 256u * 1024u * 1024u;
- bool Enabled = true;
+ int32_t MaxDurationSeconds = 24 * 60 * 60;
};
-struct ZenCasEvictionPolicy
+struct ZenProjectStoreEvictionPolicy
{
- uint64_t LargeStrategySizeLimit = ~uint64_t(0);
- uint64_t SmallStrategySizeLimit = ~uint64_t(0);
- uint64_t TinyStrategySizeLimit = ~uint64_t(0);
- bool Enabled = true;
+ int32_t MaxDurationSeconds = 7 * 24 * 60 * 60;
};
struct ZenGcConfig
{
- ZenCasEvictionPolicy Cas;
- ZenCacheEvictionPolicy Cache;
- int32_t MonitorIntervalSeconds = 30;
- int32_t IntervalSeconds = 0;
- bool CollectSmallObjects = true;
- bool Enabled = true;
- uint64_t DiskReserveSize = 1ul << 28;
- uint64_t MinimumFreeDiskSpaceToAllowWrites = 1ul << 28;
+ // ZenCasEvictionPolicy Cas;
+ ZenCacheEvictionPolicy Cache;
+ ZenProjectStoreEvictionPolicy ProjectStore;
+ int32_t MonitorIntervalSeconds = 30;
+ int32_t IntervalSeconds = 0;
+ bool CollectSmallObjects = true;
+ bool Enabled = true;
+ uint64_t DiskReserveSize = 1ul << 28;
+ uint64_t DiskSizeSoftLimit = 0;
+ uint64_t MinimumFreeDiskSpaceToAllowWrites = 1ul << 28;
};
struct ZenOpenIdProviderConfig
diff --git a/src/zenserver/projectstore/projectstore.cpp b/src/zenserver/projectstore/projectstore.cpp
index 03c1e8927..0beb207ae 100644
--- a/src/zenserver/projectstore/projectstore.cpp
+++ b/src/zenserver/projectstore/projectstore.cpp
@@ -1581,7 +1581,7 @@ ProjectStore::Project::GatherReferences(GcContext& GcCtx)
}
IterateOplogs([&](Oplog& Ops) {
- if (!IsExpired(GcCtx.ExpireTime(), Ops))
+ if (!IsExpired(GcCtx.ProjectStoreExpireTime(), Ops))
{
Ops.GatherReferences(GcCtx);
}
@@ -1804,7 +1804,7 @@ ProjectStore::GatherReferences(GcContext& GcCtx)
for (auto& Kv : m_Projects)
{
- if (Kv.second->IsExpired(GcCtx.ExpireTime()))
+ if (Kv.second->IsExpired(GcCtx.ProjectStoreExpireTime()))
{
ExpiredProjectCount++;
continue;
@@ -1842,7 +1842,7 @@ ProjectStore::CollectGarbage(GcContext& GcCtx)
RwLock::SharedLockScope _(m_ProjectsLock);
for (auto& Kv : m_Projects)
{
- if (Kv.second->IsExpired(GcCtx.ExpireTime()))
+ if (Kv.second->IsExpired(GcCtx.ProjectStoreExpireTime()))
{
ExpiredProjects.push_back(Kv.second);
ExpiredProjectCount++;
@@ -1865,7 +1865,7 @@ ProjectStore::CollectGarbage(GcContext& GcCtx)
{
RwLock::ExclusiveLockScope _(m_ProjectsLock);
Project->IterateOplogs([&GcCtx, &Project, &ExpiredOplogs](ProjectStore::Oplog& Oplog) {
- if (Project->IsExpired(GcCtx.ExpireTime(), Oplog))
+ if (Project->IsExpired(GcCtx.ProjectStoreExpireTime(), Oplog))
{
ExpiredOplogs.push_back(Oplog.OplogId());
}
@@ -1893,7 +1893,7 @@ ProjectStore::CollectGarbage(GcContext& GcCtx)
std::string ProjectId;
{
RwLock::ExclusiveLockScope _(m_ProjectsLock);
- if (!Project->IsExpired(GcCtx.ExpireTime()))
+ if (!Project->IsExpired(GcCtx.ProjectStoreExpireTime()))
{
ZEN_DEBUG("ProjectStore::CollectGarbage skipped garbage collect of project '{}'. Project no longer expired.", ProjectId);
continue;
@@ -4173,7 +4173,7 @@ TEST_CASE("project.store.gc")
}
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
ProjectStore.GatherReferences(GcCtx);
size_t RefCount = 0;
GcCtx.IterateCids([&RefCount](const IoHash&) { RefCount++; });
@@ -4184,7 +4184,7 @@ TEST_CASE("project.store.gc")
}
{
- GcContext GcCtx(GcClock::Now() + std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() + std::chrono::hours(24), GcClock::Now() + std::chrono::hours(24));
ProjectStore.GatherReferences(GcCtx);
size_t RefCount = 0;
GcCtx.IterateCids([&RefCount](const IoHash&) { RefCount++; });
@@ -4197,7 +4197,7 @@ TEST_CASE("project.store.gc")
std::filesystem::remove(Project1FilePath);
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
ProjectStore.GatherReferences(GcCtx);
size_t RefCount = 0;
GcCtx.IterateCids([&RefCount](const IoHash&) { RefCount++; });
@@ -4208,7 +4208,7 @@ TEST_CASE("project.store.gc")
}
{
- GcContext GcCtx(GcClock::Now() + std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() + std::chrono::hours(24), GcClock::Now() + std::chrono::hours(24));
ProjectStore.GatherReferences(GcCtx);
size_t RefCount = 0;
GcCtx.IterateCids([&RefCount](const IoHash&) { RefCount++; });
@@ -4220,7 +4220,7 @@ TEST_CASE("project.store.gc")
std::filesystem::remove(Project2OplogPath);
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
ProjectStore.GatherReferences(GcCtx);
size_t RefCount = 0;
GcCtx.IterateCids([&RefCount](const IoHash&) { RefCount++; });
@@ -4231,7 +4231,7 @@ TEST_CASE("project.store.gc")
}
{
- GcContext GcCtx(GcClock::Now() + std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() + std::chrono::hours(24), GcClock::Now() + std::chrono::hours(24));
ProjectStore.GatherReferences(GcCtx);
size_t RefCount = 0;
GcCtx.IterateCids([&RefCount](const IoHash&) { RefCount++; });
@@ -4243,7 +4243,7 @@ TEST_CASE("project.store.gc")
std::filesystem::remove(Project2FilePath);
{
- GcContext GcCtx(GcClock::Now() + std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() + std::chrono::hours(24), GcClock::Now() + std::chrono::hours(24));
ProjectStore.GatherReferences(GcCtx);
size_t RefCount = 0;
GcCtx.IterateCids([&RefCount](const IoHash&) { RefCount++; });
diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp
index b97cbbc26..789b6f4a6 100644
--- a/src/zenserver/zenserver.cpp
+++ b/src/zenserver/zenserver.cpp
@@ -409,11 +409,12 @@ public:
.MonitorInterval = std::chrono::seconds(ServerOptions.GcConfig.MonitorIntervalSeconds),
.Interval = std::chrono::seconds(ServerOptions.GcConfig.IntervalSeconds),
.MaxCacheDuration = std::chrono::seconds(ServerOptions.GcConfig.Cache.MaxDurationSeconds),
+ .MaxProjectStoreDuration = std::chrono::seconds(ServerOptions.GcConfig.ProjectStore.MaxDurationSeconds),
.CollectSmallObjects = ServerOptions.GcConfig.CollectSmallObjects,
.Enabled = ServerOptions.GcConfig.Enabled,
.DiskReserveSize = ServerOptions.GcConfig.DiskReserveSize,
- .DiskSizeSoftLimit = ServerOptions.GcConfig.Cache.DiskSizeSoftLimit,
- .MinimumFreeDiskSpaceToAllowWrites = ServerOptions.GcConfig.Cache.MinimumFreeDiskSpaceToAllowWrites};
+ .DiskSizeSoftLimit = ServerOptions.GcConfig.DiskSizeSoftLimit,
+ .MinimumFreeDiskSpaceToAllowWrites = ServerOptions.GcConfig.MinimumFreeDiskSpaceToAllowWrites};
m_GcScheduler.Initialize(GcConfig);
return EffectiveBasePort;
diff --git a/src/zenstore/compactcas.cpp b/src/zenstore/compactcas.cpp
index e4c2c2ecf..0f6f011e1 100644
--- a/src/zenstore/compactcas.cpp
+++ b/src/zenstore/compactcas.cpp
@@ -645,6 +645,13 @@ CasContainerStrategy::ReadIndexFile(const std::filesystem::path& IndexPath, uint
uint64_t
CasContainerStrategy::ReadLog(const std::filesystem::path& LogPath, uint64_t SkipEntryCount)
{
+ if (!TCasLogFile<CasDiskIndexEntry>::IsValid(LogPath))
+ {
+ ZEN_WARN("removing invalid cas log at '{}'", LogPath);
+ std::filesystem::remove(LogPath);
+ return 0;
+ }
+
size_t LogEntryCount = 0;
Stopwatch Timer;
const auto _ = MakeGuard([&] {
@@ -972,7 +979,7 @@ TEST_CASE("compactcas.gc.basic")
CHECK(InsertResult.New);
Cas.Flush();
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
Cas.CollectGarbage(GcCtx);
@@ -1002,7 +1009,7 @@ TEST_CASE("compactcas.gc.removefile")
CasContainerStrategy Cas(Gc);
Cas.Initialize(TempDir.Path(), "cb", 65536, 1 << 4, false);
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
Cas.CollectGarbage(GcCtx);
@@ -1057,7 +1064,7 @@ TEST_CASE("compactcas.gc.compact")
// Keep first and last
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
@@ -1092,7 +1099,7 @@ TEST_CASE("compactcas.gc.compact")
// Keep last
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
KeepChunks.push_back(ChunkHashes[8]);
@@ -1124,7 +1131,7 @@ TEST_CASE("compactcas.gc.compact")
// Keep mixed
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
KeepChunks.push_back(ChunkHashes[1]);
@@ -1159,7 +1166,7 @@ TEST_CASE("compactcas.gc.compact")
// Keep multiple at end
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
KeepChunks.push_back(ChunkHashes[6]);
@@ -1194,7 +1201,7 @@ TEST_CASE("compactcas.gc.compact")
// Keep every other
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
KeepChunks.push_back(ChunkHashes[0]);
@@ -1273,7 +1280,7 @@ TEST_CASE("compactcas.gc.deleteblockonopen")
// GC every other block
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
for (size_t i = 0; i < 20; i += 2)
@@ -1340,7 +1347,7 @@ TEST_CASE("compactcas.gc.handleopeniobuffer")
Cas.Flush();
// GC everything
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
Cas.CollectGarbage(GcCtx);
@@ -1496,7 +1503,7 @@ TEST_CASE("compactcas.threadedinsert")
C++;
}
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
GcCtx.AddRetainedCids(KeepHashes);
Cas.CollectGarbage(GcCtx);
@@ -1537,7 +1544,7 @@ TEST_CASE("compactcas.threadedinsert")
C++;
}
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
GcCtx.AddRetainedCids(KeepHashes);
Cas.CollectGarbage(GcCtx);
diff --git a/src/zenstore/filecas.cpp b/src/zenstore/filecas.cpp
index 2b64bd202..88b847c51 100644
--- a/src/zenstore/filecas.cpp
+++ b/src/zenstore/filecas.cpp
@@ -1417,7 +1417,7 @@ TEST_CASE("cas.file.gc")
{
InsertChunks();
- GcContext Ctx(GcClock::Now() - std::chrono::hours(24));
+ GcContext Ctx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
FileCas.CollectGarbage(Ctx);
for (const IoHash& Key : Keys)
@@ -1433,7 +1433,7 @@ TEST_CASE("cas.file.gc")
{
InsertChunks();
- GcContext Ctx(GcClock::Now() - std::chrono::hours(24));
+ GcContext Ctx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
for (const IoHash& Key : Keys)
{
diff --git a/src/zenstore/gc.cpp b/src/zenstore/gc.cpp
index a7c757877..2d7e0e02f 100644
--- a/src/zenstore/gc.cpp
+++ b/src/zenstore/gc.cpp
@@ -189,16 +189,19 @@ struct GcContext::GcState
CacheKeyContexts m_ExpiredCacheKeys;
HashKeySet m_RetainedCids;
HashKeySet m_DeletedCids;
- GcClock::TimePoint m_ExpireTime;
+ GcClock::TimePoint m_CacheExpireTime;
+ GcClock::TimePoint m_ProjectStoreExpireTime;
bool m_DeletionMode = true;
bool m_CollectSmallObjects = false;
std::filesystem::path DiskReservePath;
};
-GcContext::GcContext(const GcClock::TimePoint& ExpireTime) : m_State(std::make_unique<GcState>())
+GcContext::GcContext(const GcClock::TimePoint& CacheExpireTime, const GcClock::TimePoint& ProjectStoreExpireTime)
+: m_State(std::make_unique<GcState>())
{
- m_State->m_ExpireTime = ExpireTime;
+ m_State->m_CacheExpireTime = CacheExpireTime;
+ m_State->m_ProjectStoreExpireTime = ProjectStoreExpireTime;
}
GcContext::~GcContext()
@@ -278,9 +281,15 @@ GcContext::CollectSmallObjects(bool NewState)
}
GcClock::TimePoint
-GcContext::ExpireTime() const
+GcContext::CacheExpireTime() const
{
- return m_State->m_ExpireTime;
+ return m_State->m_CacheExpireTime;
+}
+
+GcClock::TimePoint
+GcContext::ProjectStoreExpireTime() const
+{
+ return m_State->m_ProjectStoreExpireTime;
}
void
@@ -710,11 +719,12 @@ GcScheduler::SchedulerThread()
continue;
}
- bool Delete = true;
- bool CollectSmallObjects = m_Config.CollectSmallObjects;
- std::chrono::seconds MaxCacheDuration = m_Config.MaxCacheDuration;
- uint64_t DiskSizeSoftLimit = m_Config.DiskSizeSoftLimit;
- GcClock::TimePoint Now = GcClock::Now();
+ bool Delete = true;
+ bool CollectSmallObjects = m_Config.CollectSmallObjects;
+ std::chrono::seconds MaxCacheDuration = m_Config.MaxCacheDuration;
+ std::chrono::seconds MaxProjectStoreDuration = m_Config.MaxProjectStoreDuration;
+ uint64_t DiskSizeSoftLimit = m_Config.DiskSizeSoftLimit;
+ GcClock::TimePoint Now = GcClock::Now();
if (m_TriggerGcParams)
{
const auto TriggerParams = m_TriggerGcParams.value();
@@ -725,13 +735,20 @@ GcScheduler::SchedulerThread()
{
MaxCacheDuration = TriggerParams.MaxCacheDuration;
}
+ if (TriggerParams.MaxProjectStoreDuration != std::chrono::seconds::max())
+ {
+ MaxProjectStoreDuration = TriggerParams.MaxProjectStoreDuration;
+ }
if (TriggerParams.DiskSizeSoftLimit != 0)
{
DiskSizeSoftLimit = TriggerParams.DiskSizeSoftLimit;
}
}
- GcClock::TimePoint ExpireTime = MaxCacheDuration == GcClock::Duration::max() ? GcClock::TimePoint::min() : Now - MaxCacheDuration;
+ GcClock::TimePoint CacheExpireTime =
+ MaxCacheDuration == GcClock::Duration::max() ? GcClock::TimePoint::min() : Now - MaxCacheDuration;
+ GcClock::TimePoint ProjectStoreExpireTime =
+ MaxProjectStoreDuration == GcClock::Duration::max() ? GcClock::TimePoint::min() : Now - MaxProjectStoreDuration;
const GcStorageSize TotalSize = m_GcManager.TotalStorageSize();
@@ -786,9 +803,13 @@ GcScheduler::SchedulerThread()
std::unique_lock Lock(m_GcMutex);
GcClock::Tick AgeTick = m_DiskUsageWindow.FindTimepointThatRemoves(GcDiskSpaceGoal, Now.time_since_epoch().count());
GcClock::TimePoint SizeBasedExpireTime = GcClock::TimePointFromTick(AgeTick);
- if (SizeBasedExpireTime > ExpireTime)
+ if (SizeBasedExpireTime > CacheExpireTime)
+ {
+ CacheExpireTime = SizeBasedExpireTime;
+ }
+ if (SizeBasedExpireTime > ProjectStoreExpireTime)
{
- ExpireTime = SizeBasedExpireTime;
+ ProjectStoreExpireTime = SizeBasedExpireTime;
}
}
@@ -832,7 +853,7 @@ GcScheduler::SchedulerThread()
}
}
- CollectGarbage(ExpireTime, Delete, CollectSmallObjects);
+ CollectGarbage(CacheExpireTime, ProjectStoreExpireTime, Delete, CollectSmallObjects);
uint32_t RunningState = static_cast<uint32_t>(GcSchedulerStatus::kRunning);
if (!m_Status.compare_exchange_strong(RunningState, static_cast<uint32_t>(GcSchedulerStatus::kIdle)))
@@ -859,17 +880,20 @@ GcScheduler::NextGcTime(GcClock::TimePoint CurrentTime)
}
void
-GcScheduler::CollectGarbage(const GcClock::TimePoint& ExpireTime, bool Delete, bool CollectSmallObjects)
+GcScheduler::CollectGarbage(const GcClock::TimePoint& CacheExpireTime,
+ const GcClock::TimePoint& ProjectStoreExpireTime,
+ bool Delete,
+ bool CollectSmallObjects)
{
- GcContext GcCtx(ExpireTime);
+ GcContext GcCtx(CacheExpireTime, ProjectStoreExpireTime);
GcCtx.SetDeletionMode(Delete);
GcCtx.CollectSmallObjects(CollectSmallObjects);
- // GcCtx.MaxCacheDuration(MaxCacheDuration);
GcCtx.DiskReservePath(m_Config.RootDirectory / "reserve.gc");
- ZEN_INFO("garbage collection STARTING, small objects gc {}, cutoff time {}",
+ ZEN_INFO("garbage collection STARTING, small objects gc {}, cache cutoff time {}, project store cutoff time {}",
GcCtx.CollectSmallObjects() ? "ENABLED"sv : "DISABLED"sv,
- ExpireTime);
+ CacheExpireTime,
+ ProjectStoreExpireTime);
{
Stopwatch Timer;
const auto __ = MakeGuard([&] { ZEN_INFO("garbage collection DONE in {}", NiceTimeSpanMs(Timer.GetElapsedTimeMs())); });
@@ -878,9 +902,10 @@ GcScheduler::CollectGarbage(const GcClock::TimePoint& ExpireTime, bool Delete, b
if (Delete)
{
- m_LastGcExpireTime = ExpireTime;
+ GcClock::TimePoint KeepRangeStart = Min(CacheExpireTime, ProjectStoreExpireTime);
+ m_LastGcExpireTime = KeepRangeStart;
std::unique_lock Lock(m_GcMutex);
- m_DiskUsageWindow.KeepRange(ExpireTime.time_since_epoch().count(), GcClock::Duration::max().count());
+ m_DiskUsageWindow.KeepRange(KeepRangeStart.time_since_epoch().count(), GcClock::Duration::max().count());
}
m_LastGcTime = GcClock::Now();
@@ -953,7 +978,7 @@ TEST_CASE("gc.basic")
const auto InsertResult = CidStore.AddChunk(CompressedChunk.GetCompressed().Flatten().AsIoBuffer(), CompressedChunk.DecodeRawHash());
CHECK(InsertResult.New);
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
CidStore.Flush();
@@ -1012,7 +1037,7 @@ TEST_CASE("gc.full")
// Keep first and last
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
@@ -1047,7 +1072,7 @@ TEST_CASE("gc.full")
// Keep last
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
KeepChunks.push_back(ChunkHashes[8]);
@@ -1079,7 +1104,7 @@ TEST_CASE("gc.full")
// Keep mixed
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
KeepChunks.push_back(ChunkHashes[1]);
@@ -1114,7 +1139,7 @@ TEST_CASE("gc.full")
// Keep multiple at end
{
- GcContext GcCtx(GcClock::Now() - std::chrono::hours(24));
+ GcContext GcCtx(GcClock::Now() - std::chrono::hours(24), GcClock::Now() - std::chrono::hours(24));
GcCtx.CollectSmallObjects(true);
std::vector<IoHash> KeepChunks;
KeepChunks.push_back(ChunkHashes[6]);
diff --git a/src/zenstore/include/zenstore/gc.h b/src/zenstore/include/zenstore/gc.h
index 4c709b8a2..881936d0f 100644
--- a/src/zenstore/include/zenstore/gc.h
+++ b/src/zenstore/include/zenstore/gc.h
@@ -48,7 +48,7 @@ public:
class GcContext
{
public:
- GcContext(const GcClock::TimePoint& ExpireTime);
+ GcContext(const GcClock::TimePoint& CacheExpireTime, const GcClock::TimePoint& ProjectStoreExpireTime);
~GcContext();
void AddRetainedCids(std::span<const IoHash> Cid);
@@ -70,7 +70,8 @@ public:
bool CollectSmallObjects() const;
void CollectSmallObjects(bool NewState);
- GcClock::TimePoint ExpireTime() const;
+ GcClock::TimePoint CacheExpireTime() const;
+ GcClock::TimePoint ProjectStoreExpireTime() const;
void DiskReservePath(const std::filesystem::path& Path);
uint64_t ClaimGCReserve();
@@ -174,6 +175,7 @@ struct GcSchedulerConfig
std::chrono::seconds MonitorInterval{30};
std::chrono::seconds Interval{};
std::chrono::seconds MaxCacheDuration{86400};
+ std::chrono::seconds MaxProjectStoreDuration{604800};
bool CollectSmallObjects = true;
bool Enabled = true;
uint64_t DiskReserveSize = 1ul << 28;
@@ -216,16 +218,20 @@ public:
struct TriggerGcParams
{
- bool CollectSmallObjects = false;
- std::chrono::seconds MaxCacheDuration = std::chrono::seconds::max();
- uint64_t DiskSizeSoftLimit = 0;
+ bool CollectSmallObjects = false;
+ std::chrono::seconds MaxCacheDuration = std::chrono::seconds::max();
+ std::chrono::seconds MaxProjectStoreDuration = std::chrono::seconds::max();
+ uint64_t DiskSizeSoftLimit = 0;
};
bool TriggerGc(const TriggerGcParams& Params);
private:
void SchedulerThread();
- void CollectGarbage(const GcClock::TimePoint& ExpireTime, bool Delete, bool CollectSmallObjects);
+ void CollectGarbage(const GcClock::TimePoint& CacheExpireTime,
+ const GcClock::TimePoint& ProjectStoreExpireTime,
+ bool Delete,
+ bool CollectSmallObjects);
GcClock::TimePoint NextGcTime(GcClock::TimePoint CurrentTime);
spdlog::logger& Log() { return m_Log; }
virtual bool AreDiskWritesAllowed() const override { return !m_AreDiskWritesBlocked.load(); }