aboutsummaryrefslogtreecommitdiff
path: root/src/zenstore/gc.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-05-09 15:11:10 +0200
committerGitHub <[email protected]>2023-05-09 15:11:10 +0200
commit2542797c56b84473395a877376b68fcc77687ea9 (patch)
tree698ebb1e4e6fb33ba9b8be973f8a851b2ee46c83 /src/zenstore/gc.cpp
parentValidate that entries points inside valid blocks at startup (#280) (diff)
downloadzen-2542797c56b84473395a877376b68fcc77687ea9.tar.xz
zen-2542797c56b84473395a877376b68fcc77687ea9.zip
Low disk space detector (#277)
* - Feature: Disk writes are now blocked early and return an insufficient storage error if free disk space falls below the `--low-diskspace-threshold` value * Never keep an entry in m_ChunkBlocks that points to a nullptr
Diffstat (limited to 'src/zenstore/gc.cpp')
-rw-r--r--src/zenstore/gc.cpp48
1 files changed, 45 insertions, 3 deletions
diff --git a/src/zenstore/gc.cpp b/src/zenstore/gc.cpp
index 370c3c965..f9888722b 100644
--- a/src/zenstore/gc.cpp
+++ b/src/zenstore/gc.cpp
@@ -559,10 +559,12 @@ DiskUsageWindow::FindTimepointThatRemoves(uint64_t Amount, GcClock::Tick EndTick
GcScheduler::GcScheduler(GcManager& GcManager) : m_Log(logging::Get("gc")), m_GcManager(GcManager)
{
+ m_GcManager.SetDiskWriteBlocker(this);
}
GcScheduler::~GcScheduler()
{
+ m_GcManager.SetDiskWriteBlocker(nullptr);
Shutdown();
}
@@ -573,6 +575,18 @@ GcScheduler::Initialize(const GcSchedulerConfig& Config)
m_Config = Config;
+ std::error_code Ec;
+ DiskSpace Space = DiskSpaceInfo(m_Config.RootDirectory, Ec);
+ if (Ec)
+ {
+ m_AreDiskWritesBlocked.store(true);
+ ZEN_WARN("get disk space info FAILED, blocking disk writes, reason: '{}'", Ec.message());
+ }
+ else
+ {
+ CheckDiskSpace(Space);
+ }
+
if (m_Config.Interval.count() && m_Config.Interval < m_Config.MonitorInterval)
{
m_Config.Interval = m_Config.MonitorInterval;
@@ -580,7 +594,7 @@ GcScheduler::Initialize(const GcSchedulerConfig& Config)
std::filesystem::create_directories(Config.RootDirectory);
- std::error_code Ec = CreateGCReserve(m_Config.RootDirectory / "reserve.gc", m_Config.DiskReserveSize);
+ Ec = CreateGCReserve(m_Config.RootDirectory / "reserve.gc", m_Config.DiskReserveSize);
if (Ec)
{
ZEN_WARN("unable to create GC reserve at '{}' with size {}, reason '{}'",
@@ -664,6 +678,29 @@ GcScheduler::Trigger(const GcScheduler::TriggerParams& Params)
}
void
+GcScheduler::CheckDiskSpace(const DiskSpace& Space)
+{
+ bool AreDiskWritesBlocked = m_AreDiskWritesBlocked;
+ bool IsLowOnDiskSpace = (m_Config.MinimumFreeDiskSpaceToAllowWrites) != 0 && (Space.Free < m_Config.MinimumFreeDiskSpaceToAllowWrites);
+ if (IsLowOnDiskSpace != AreDiskWritesBlocked)
+ {
+ m_AreDiskWritesBlocked.store(IsLowOnDiskSpace);
+ if (IsLowOnDiskSpace)
+ {
+ ZEN_WARN("Writing to disk is blocked, free disk space: {}, minimum required {}",
+ NiceBytes(Space.Free),
+ NiceBytes(m_Config.MinimumFreeDiskSpaceToAllowWrites));
+ }
+ else
+ {
+ ZEN_INFO("Writing to disk is unblocked, free disk space: {}, minimum required {}",
+ NiceBytes(Space.Free),
+ NiceBytes(m_Config.MinimumFreeDiskSpaceToAllowWrites));
+ }
+ }
+}
+
+void
GcScheduler::SchedulerThread()
{
std::chrono::seconds WaitTime{0};
@@ -716,16 +753,21 @@ GcScheduler::SchedulerThread()
GcClock::TimePoint ExpireTime = MaxCacheDuration == GcClock::Duration::max() ? GcClock::TimePoint::min() : Now - MaxCacheDuration;
- std::error_code Ec;
const GcStorageSize TotalSize = m_GcManager.TotalStorageSize();
if (Timeout && Status() == GcSchedulerStatus::kIdle)
{
- DiskSpace Space = DiskSpaceInfo(m_Config.RootDirectory, Ec);
+ std::error_code Ec;
+ DiskSpace Space = DiskSpaceInfo(m_Config.RootDirectory, Ec);
if (Ec)
{
+ m_AreDiskWritesBlocked.store(true);
ZEN_WARN("get disk space info FAILED, reason: '{}'", Ec.message());
}
+ else
+ {
+ CheckDiskSpace(Space);
+ }
const int64_t PressureGraphLength = 30;
const std::chrono::duration LoadGraphTime = PressureGraphLength * m_Config.MonitorInterval;