diff options
| author | Per Larsson <[email protected]> | 2021-12-05 19:04:39 +0100 |
|---|---|---|
| committer | Per Larsson <[email protected]> | 2021-12-05 19:04:39 +0100 |
| commit | 69c33063aaa85abf153bea036c58937067a80cd5 (patch) | |
| tree | 6c13f9c8095e727213cf754d274694af05afb3ce | |
| parent | Added simple GC interval scheduling. (diff) | |
| download | zen-69c33063aaa85abf153bea036c58937067a80cd5.tar.xz zen-69c33063aaa85abf153bea036c58937067a80cd5.zip | |
Check available disk space before GC.
| -rw-r--r-- | zencore/filesystem.cpp | 21 | ||||
| -rw-r--r-- | zencore/include/zencore/filesystem.h | 16 | ||||
| -rw-r--r-- | zenstore/compactcas.cpp | 21 | ||||
| -rw-r--r-- | zenstore/gc.cpp | 12 |
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)); } } } |