aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2022-03-21 09:33:59 +0100
committerDan Engelbrecht <[email protected]>2022-03-31 11:28:32 +0200
commit9a85201337a554a36ffdf55c2e084462ec031d7d (patch)
tree1c8bf6fdd05678a7a53370485fa99685ad631710
parentChunkBlock takes prepared path (diff)
downloadzen-9a85201337a554a36ffdf55c2e084462ec031d7d.tar.xz
zen-9a85201337a554a36ffdf55c2e084462ec031d7d.zip
Add GC reserve block logic
-rw-r--r--zenstore/compactcas.cpp81
1 files changed, 71 insertions, 10 deletions
diff --git a/zenstore/compactcas.cpp b/zenstore/compactcas.cpp
index 8cf6fe229..99f00f5af 100644
--- a/zenstore/compactcas.cpp
+++ b/zenstore/compactcas.cpp
@@ -309,7 +309,7 @@ CasContainerStrategy::InsertChunk(const void* ChunkData, size_t ChunkSize, const
WriteBlockIndex += WriteBlock ? 1 : 0;
while (m_ChunkBlocks.contains(WriteBlockIndex))
{
- WriteBlockIndex++;
+ WriteBlockIndex = (WriteBlockIndex + 1) & CasDiskLocation::MaxBlockIndex;
}
auto BlockPath = BuildUcasPath(m_BlocksBasePath, WriteBlockIndex);
WriteBlock = std::make_shared<ChunkBlock>(BlockPath);
@@ -678,6 +678,7 @@ CasContainerStrategy::CollectGarbage(GcContext& GcCtx)
if (!NewBlockFile || (WriteOffset + Chunk.size() > m_MaxBlockSize))
{
NewBlockIndex = m_WriteBlockIndex.load();
+
{
RwLock::ExclusiveLockScope _l(m_LocationMapLock);
if (NewBlockFile)
@@ -695,12 +696,16 @@ CasContainerStrategy::CollectGarbage(GcContext& GcCtx)
return;
}
}
+ if (m_ChunkBlocks.size() == CasDiskLocation::MaxBlockIndex)
+ {
+ throw std::runtime_error(fmt::format("unable to allocate a new block in {}", m_ContainerBaseName));
+ }
while (m_ChunkBlocks.contains(NewBlockIndex))
{
- NewBlockIndex++;
+ NewBlockIndex = (NewBlockIndex + 1) & CasDiskLocation::MaxBlockIndex;
}
- auto BlockPath = BuildUcasPath(m_BlocksBasePath, NewBlockIndex);
- NewBlockFile = std::make_shared<ChunkBlock>(BlockPath);
+ auto NewBlockPath = BuildUcasPath(m_BlocksBasePath, NewBlockIndex);
+ NewBlockFile = std::make_shared<ChunkBlock>(NewBlockPath);
m_ChunkBlocks[NewBlockIndex] = NewBlockFile;
}
@@ -714,16 +719,30 @@ CasContainerStrategy::CollectGarbage(GcContext& GcCtx)
if (Space.Free < m_MaxBlockSize)
{
- ZEN_INFO("garbage collect from '{}' FAILED, required disk space {}, free {}",
+ std::filesystem::path GCReservePath = m_Config.RootDirectory / (m_ContainerBaseName + ".gc.reserve.ucas");
+ if (!std::filesystem::is_regular_file(GCReservePath))
+ {
+ ZEN_INFO("garbage collect from '{}' FAILED, required disk space {}, free {}",
+ m_Config.RootDirectory / m_ContainerBaseName,
+ m_MaxBlockSize,
+ NiceBytes(Space.Free));
+ RwLock::ExclusiveLockScope _l(m_LocationMapLock);
+ m_ChunkBlocks.erase(NewBlockIndex);
+ return;
+ }
+
+ ZEN_INFO("using gc reserve for '{}', disk free {}",
m_Config.RootDirectory / m_ContainerBaseName,
- m_MaxBlockSize * m_MaxBlockSize,
NiceBytes(Space.Free));
- RwLock::ExclusiveLockScope _l(m_LocationMapLock);
- m_ChunkBlocks.erase(NewBlockIndex);
- return;
+ auto NewBlockPath = BuildUcasPath(m_BlocksBasePath, NewBlockIndex);
+ std::filesystem::rename(GCReservePath, NewBlockPath);
+ NewBlockFile->Open();
+ }
+ else
+ {
+ NewBlockFile->Create(m_MaxBlockSize);
}
- NewBlockFile->Create(m_MaxBlockSize);
MovedBlocks.clear();
WriteOffset = 0;
}
@@ -930,6 +949,7 @@ CasContainerStrategy::OpenContainer(bool IsNewStore)
std::filesystem::path SidxPath = m_Config.RootDirectory / (m_ContainerBaseName + ".uidx");
std::filesystem::path SlogPath = m_Config.RootDirectory / (m_ContainerBaseName + ".ulog");
std::filesystem::path LegacySobsPath = m_Config.RootDirectory / (m_ContainerBaseName + ".ucas");
+
if (IsNewStore)
{
if (std::filesystem::is_regular_file(LegacySobsPath))
@@ -1177,6 +1197,47 @@ CasContainerStrategy::OpenContainer(bool IsNewStore)
m_CurrentInsertOffset = AlignPositon(SmallestBlockSize, m_PayloadAlignment);
}
+ // Create GC reserve file if possible
+ std::filesystem::path GCReservePath = m_Config.RootDirectory / (m_ContainerBaseName + ".gc.reserve.ucas");
+
+ std::error_code Error;
+ DiskSpace Space = DiskSpaceInfo(m_Config.RootDirectory, Error);
+ if (Error)
+ {
+ ZEN_ERROR("get disk space in {} FAILED, reason '{}'", m_ContainerBaseName, Error.message());
+ return;
+ }
+
+ BasicFile GCReserveFile;
+ if (std::filesystem::is_regular_file(GCReservePath))
+ {
+ GCReserveFile.Open(GCReservePath, false);
+ std::uint64_t CurrentSize = GCReserveFile.FileSize();
+ if (CurrentSize != m_MaxBlockSize)
+ {
+ if (CurrentSize > m_MaxBlockSize)
+ {
+ GCReserveFile.SetFileSize(m_MaxBlockSize);
+ }
+ else
+ {
+ std::uint64_t ExtraSpace = m_MaxBlockSize - CurrentSize;
+ if (Space.Free >= ExtraSpace)
+ {
+ GCReserveFile.SetFileSize(m_MaxBlockSize);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (Space.Free > m_MaxBlockSize)
+ {
+ GCReserveFile.Open(GCReservePath, true);
+ GCReserveFile.SetFileSize(m_MaxBlockSize);
+ }
+ }
+
// TODO: should validate integrity of container files here
}