aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPer Larsson <[email protected]>2021-12-05 19:04:39 +0100
committerPer Larsson <[email protected]>2021-12-05 19:04:39 +0100
commit69c33063aaa85abf153bea036c58937067a80cd5 (patch)
tree6c13f9c8095e727213cf754d274694af05afb3ce
parentAdded simple GC interval scheduling. (diff)
downloadzen-69c33063aaa85abf153bea036c58937067a80cd5.tar.xz
zen-69c33063aaa85abf153bea036c58937067a80cd5.zip
Check available disk space before GC.
-rw-r--r--zencore/filesystem.cpp21
-rw-r--r--zencore/include/zencore/filesystem.h16
-rw-r--r--zenstore/compactcas.cpp21
-rw-r--r--zenstore/gc.cpp12
4 files changed, 68 insertions, 2 deletions
diff --git a/zencore/filesystem.cpp b/zencore/filesystem.cpp
index bcbb36c73..53e6f1f38 100644
--- a/zencore/filesystem.cpp
+++ b/zencore/filesystem.cpp
@@ -634,6 +634,27 @@ ToUtf8(const std::filesystem::path& Path)
#endif
}
+DiskSpace
+DiskSpaceInfo(std::filesystem::path Directory, std::error_code& Error)
+{
+#if ZEN_PLATFORM_WINDOWS
+ ULARGE_INTEGER Free, Total;
+ if (GetDiskFreeSpaceExA(Directory.string().c_str(), &Free, &Total, nullptr))
+ {
+ return {.Free = static_cast<uint64_t>(Free.QuadPart), .Total = static_cast<uint64_t>(Total.QuadPart)};
+ }
+ else
+ {
+ Error = std::error_code(::GetLastError(), std::system_category());
+ return {};
+ }
+#else
+ ZEN_ERROR("DiskSpaceInfo() is not implemented on this platform");
+ Error = std::error_code(1, std::system_category());
+ return {};
+#endif
+}
+
void
FileSystemTraversal::TraverseFileSystem(const std::filesystem::path& RootDir, TreeVisitor& Visitor)
{
diff --git a/zencore/include/zencore/filesystem.h b/zencore/include/zencore/filesystem.h
index c7ac7140d..155291e67 100644
--- a/zencore/include/zencore/filesystem.h
+++ b/zencore/include/zencore/filesystem.h
@@ -57,6 +57,22 @@ ZENCORE_API bool SupportsBlockRefCounting(std::filesystem::path Path);
ZENCORE_API std::string ToUtf8(const std::filesystem::path& Path);
+struct DiskSpace
+{
+ uint64_t Free{};
+ uint64_t Total{};
+};
+
+ZENCORE_API DiskSpace DiskSpaceInfo(std::filesystem::path Directory, std::error_code& Error);
+
+inline bool
+DiskSpaceInfo(std::filesystem::path Directory, DiskSpace& Space)
+{
+ std::error_code Err;
+ Space = DiskSpaceInfo(Directory, Err);
+ return !!Err;
+}
+
/**
* Efficient file system traversal
*
diff --git a/zenstore/compactcas.cpp b/zenstore/compactcas.cpp
index fd4b9441e..eeaec6f36 100644
--- a/zenstore/compactcas.cpp
+++ b/zenstore/compactcas.cpp
@@ -257,6 +257,10 @@ CasContainerStrategy::CollectGarbage(GcContext& GcCtx)
{
namespace fs = std::filesystem;
+ // A naive garbage collection implementation that just copies evicted chunks
+ // into a new container file. We probably need to partition the container file
+ // into several parts to prevent needing to keep the entire container file during GC.
+
ZEN_INFO("collecting garbage from '{}'", m_Config.RootDirectory / m_ContainerBaseName);
RwLock::ExclusiveLockScope _(m_LocationMapLock);
@@ -297,6 +301,23 @@ CasContainerStrategy::CollectGarbage(GcContext& GcCtx)
NewTotalSize += Loc.GetSize();
}
+ std::error_code Error;
+ DiskSpace Space = DiskSpaceInfo(m_Config.RootDirectory, Error);
+ if (Error)
+ {
+ ZEN_ERROR("get disk space FAILED, reason '{}'", Error.message());
+ return;
+ }
+
+ if (Space.Free < NewTotalSize + (64 << 20))
+ {
+ ZEN_INFO("garbage collect from '{}' FAILED, required disk space {}, free {}",
+ m_Config.RootDirectory / m_ContainerBaseName,
+ NiceBytes(NewTotalSize),
+ NiceBytes(Space.Free));
+ return;
+ }
+
const bool GcEnabled = GcCtx.IsDeletionMode() && GcCtx.IsContainerGcEnabled();
if (GcEnabled)
diff --git a/zenstore/gc.cpp b/zenstore/gc.cpp
index 7ab2045b5..b18a577bf 100644
--- a/zenstore/gc.cpp
+++ b/zenstore/gc.cpp
@@ -318,7 +318,10 @@ GcScheduler::SchedulerThread()
if (m_Config.Enabled)
{
Stopwatch Timer;
- ZEN_INFO("garbage collection STARTING");
+
+ DiskSpace Space;
+ DiskSpaceInfo(m_Config.RootDirectory, Space);
+ ZEN_INFO("garbage collection STARTING, disk space {}/{} (free/total)", NiceBytes(Space.Free), NiceBytes(Space.Total));
GcContext GcCtx;
GcCtx.SetDeletionMode(true);
@@ -335,7 +338,12 @@ GcScheduler::SchedulerThread()
SaveCompactBinaryObject(m_Config.RootDirectory / "gc_state", SchedulderState.Save());
}
- ZEN_INFO("garbage collection DONE after {}", NiceTimeSpanMs(Timer.GetElapsedTimeMs()));
+ DiskSpaceInfo(m_Config.RootDirectory, Space);
+
+ ZEN_INFO("garbage collection DONE after {}, disk space {}/{} (free/total)",
+ NiceTimeSpanMs(Timer.GetElapsedTimeMs()),
+ NiceBytes(Space.Free),
+ NiceBytes(Space.Total));
}
}
}