aboutsummaryrefslogtreecommitdiff
path: root/zenstore/compactcas.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2022-03-14 10:32:22 +0100
committerDan Engelbrecht <[email protected]>2022-03-31 11:28:31 +0200
commit53afe82f8433bf8506fef3dd4450b6d38352018f (patch)
tree63b97516aa8dcb086107dc773c76e0ea32df14b0 /zenstore/compactcas.cpp
parentAdd AlignPositon helper (diff)
downloadzen-53afe82f8433bf8506fef3dd4450b6d38352018f.tar.xz
zen-53afe82f8433bf8506fef3dd4450b6d38352018f.zip
WIP
Diffstat (limited to 'zenstore/compactcas.cpp')
-rw-r--r--zenstore/compactcas.cpp497
1 files changed, 289 insertions, 208 deletions
diff --git a/zenstore/compactcas.cpp b/zenstore/compactcas.cpp
index 5cf0d3ae1..5712734c7 100644
--- a/zenstore/compactcas.cpp
+++ b/zenstore/compactcas.cpp
@@ -31,7 +31,8 @@
namespace zen {
-static uint64_t AlignPositon(uint64_t Offset, uint64_t Alignment)
+static uint64_t
+AlignPositon(uint64_t Offset, uint64_t Alignment)
{
return (Offset + Alignment - 1) & ~(Alignment - 1);
}
@@ -85,9 +86,6 @@ CasContainerStrategy::InsertChunk(const void* ChunkData, size_t ChunkSize, const
const CasDiskLocation Location{InsertOffset, ChunkSize};
CasDiskIndexEntry IndexEntry{.Key = ChunkHash, .Location = Location};
- // m_SmallObjectIndex.Write(&IndexEntry, sizeof(CasDiskIndexEntry), m_CurrentIndexOffset);
- // m_CurrentIndexOffset += sizeof(CasDiskIndexEntry);
-
RwLock::ExclusiveLockScope __(m_LocationMapLock);
m_LocationMap[ChunkHash] = Location;
m_TotalSize.fetch_add(static_cast<uint64_t>(ChunkSize));
@@ -148,8 +146,8 @@ CasContainerStrategy::FilterChunks(CasChunkSet& InOutChunks)
void
CasContainerStrategy::Flush()
{
+ RwLock::SharedLockScope _(m_LocationMapLock);
m_CasLog.Flush();
- // m_SmallObjectIndex.Flush();
m_SmallObjectFile.Flush();
}
@@ -211,21 +209,21 @@ CasContainerStrategy::Scrub(ScrubContext& Ctx)
WindowStart += WindowSize;
WindowEnd += WindowSize;
} while (WindowStart < FileSize);
- }
-
- // Deal with large chunks
- for (const CasDiskIndexEntry& Entry : BigChunks)
- {
- IoHashStream Hasher;
- m_SmallObjectFile.StreamByteRange(Entry.Location.GetOffset(), Entry.Location.GetSize(), [&](const void* Data, uint64_t Size) {
- Hasher.Append(Data, Size);
- });
- IoHash ComputedHash = Hasher.GetHash();
+ // Deal with large chunks
- if (Entry.Key != ComputedHash)
+ for (const CasDiskIndexEntry& Entry : BigChunks)
{
- BadChunks.push_back(Entry);
+ IoHashStream Hasher;
+ m_SmallObjectFile.StreamByteRange(Entry.Location.GetOffset(), Entry.Location.GetSize(), [&](const void* Data, uint64_t Size) {
+ Hasher.Append(Data, Size);
+ });
+ IoHash ComputedHash = Hasher.GetHash();
+
+ if (Entry.Key != ComputedHash)
+ {
+ BadChunks.push_back(Entry);
+ }
}
}
@@ -240,6 +238,7 @@ CasContainerStrategy::Scrub(ScrubContext& Ctx)
std::vector<IoHash> BadChunkHashes;
+ RwLock::ExclusiveLockScope _(m_LocationMapLock);
for (const CasDiskIndexEntry& Entry : BadChunks)
{
BadChunkHashes.push_back(Entry.Key);
@@ -281,263 +280,346 @@ CasContainerStrategy::CollectGarbage(GcContext& GcCtx)
// added betwen each move of a block.
ZEN_INFO("collecting garbage from '{}'", m_Config.RootDirectory / m_ContainerBaseName);
- const uint64_t TotalChunkCount = m_LocationMap.size();
- uint64_t TotalSize = m_TotalSize.load();
-
- RwLock::ExclusiveLockScope _i(m_InsertLock);
- RwLock::ExclusiveLockScope _l(m_LocationMapLock);
-
- Flush();
-
- if (m_LocationMap.empty())
{
- ZEN_INFO("garbage collect SKIPPED, for '{}', container is empty", m_Config.RootDirectory / m_ContainerBaseName);
- return;
- }
+ RwLock::ExclusiveLockScope _i(m_InsertLock);
+ RwLock::ExclusiveLockScope _l(m_LocationMapLock);
- std::vector<IoHash> TotalChunkHashes;
- TotalChunkHashes.reserve(m_LocationMap.size());
- for (auto& Entry : m_LocationMap)
- {
- TotalChunkHashes.push_back(Entry.first);
- }
+ Flush();
- std::vector<IoHash> DeletedChunks;
- std::vector<IoHash> ChunkHashes; // Same sort order as ChunkLocations
- ChunkHashes.reserve(m_LocationMap.size());
+ if (m_LocationMap.empty())
+ {
+ ZEN_INFO("garbage collect SKIPPED, for '{}', container is empty", m_Config.RootDirectory / m_ContainerBaseName);
+ return;
+ }
- const bool CollectSmallObjects = GcCtx.IsDeletionMode() && GcCtx.CollectSmallObjects();
+ const uint64_t TotalChunkCount = m_LocationMap.size();
+ uint64_t TotalSize = m_TotalSize.load();
- GcCtx.FilterCas(TotalChunkHashes, [&](const IoHash& ChunkHash, bool Keep) {
- if (Keep)
+ std::vector<IoHash> TotalChunkHashes;
+ TotalChunkHashes.reserve(m_LocationMap.size());
+ for (auto& Entry : m_LocationMap)
{
- ChunkHashes.push_back(ChunkHash);
+ TotalChunkHashes.push_back(Entry.first);
}
- else
+
+ std::vector<IoHash> DeletedChunks;
+ std::vector<IoHash> ChunkHashes; // Same sort order as ChunkLocations
+ ChunkHashes.reserve(m_LocationMap.size());
+
+ const bool CollectSmallObjects = GcCtx.IsDeletionMode() && GcCtx.CollectSmallObjects();
+
+ GcCtx.FilterCas(TotalChunkHashes, [&](const IoHash& ChunkHash, bool Keep) {
+ if (Keep)
+ {
+ ChunkHashes.push_back(ChunkHash);
+ }
+ else
+ {
+ DeletedChunks.push_back(ChunkHash);
+ }
+ });
+
+ if (ChunkHashes.size() == TotalChunkCount)
{
- DeletedChunks.push_back(ChunkHash);
+ ZEN_INFO("garbage collect DONE, scanned #{} {} chunks from '{}', nothing to delete",
+ TotalChunkCount,
+ NiceBytes(TotalSize),
+ m_Config.RootDirectory / m_ContainerBaseName);
+ return;
}
- });
- if (ChunkHashes.size() == TotalChunkCount)
- {
- ZEN_INFO("garbage collect DONE, scanned #{} {} chunks from '{}', nothing to delete",
- TotalChunkCount,
- NiceBytes(TotalSize),
- m_Config.RootDirectory / m_ContainerBaseName);
- return;
- }
+ const uint64_t ChunkCount = ChunkHashes.size();
- const uint64_t ChunkCount = ChunkHashes.size();
-
- std::sort(begin(ChunkHashes), end(ChunkHashes), [&](IoHash Lhs, IoHash Rhs) {
- auto LhsKeyIt = m_LocationMap.find(Lhs);
- auto RhsKeyIt = m_LocationMap.find(Rhs);
- return LhsKeyIt->second.GetOffset() < RhsKeyIt->second.GetOffset();
- });
+ std::sort(begin(ChunkHashes), end(ChunkHashes), [&](IoHash Lhs, IoHash Rhs) {
+ auto LhsKeyIt = m_LocationMap.find(Lhs);
+ auto RhsKeyIt = m_LocationMap.find(Rhs);
+ return LhsKeyIt->second.GetOffset() < RhsKeyIt->second.GetOffset();
+ });
- uint64_t NewTotalSize = 0;
- std::vector<CasDiskLocation> ChunkLocations;
- ChunkLocations.reserve(ChunkHashes.size());
- for (auto Entry : ChunkHashes)
- {
- auto KeyIt = m_LocationMap.find(Entry);
- const auto& ChunkLocation = KeyIt->second;
- ChunkLocations.push_back(ChunkLocation);
- NewTotalSize += ChunkLocation.GetSize();
- }
+ uint64_t NewTotalSize = 0;
+ std::vector<CasDiskLocation> ChunkLocations;
+ ChunkLocations.reserve(ChunkHashes.size());
+ for (auto Entry : ChunkHashes)
+ {
+ auto KeyIt = m_LocationMap.find(Entry);
+ const auto& ChunkLocation = KeyIt->second;
+ ChunkLocations.push_back(ChunkLocation);
+ NewTotalSize += ChunkLocation.GetSize();
+ }
- if (!CollectSmallObjects)
- {
- ZEN_INFO("garbage collect from '{}' DISABLED, found #{} {} chunks of total #{} {}",
- m_Config.RootDirectory / m_ContainerBaseName,
- TotalChunkCount - ChunkCount,
- NiceBytes(TotalSize - NewTotalSize),
- TotalChunkCount,
- NiceBytes(TotalSize));
- return;
- }
+ if (!CollectSmallObjects)
+ {
+ ZEN_INFO("garbage collect from '{}' DISABLED, found #{} {} chunks of total #{} {}",
+ m_Config.RootDirectory / m_ContainerBaseName,
+ TotalChunkCount - ChunkCount,
+ NiceBytes(TotalSize - NewTotalSize),
+ TotalChunkCount,
+ NiceBytes(TotalSize));
+ return;
+ }
- for (auto ChunkHash : DeletedChunks)
- {
- auto KeyIt = m_LocationMap.find(ChunkHash);
- const auto& ChunkLocation = KeyIt->second;
- uint64_t NextChunkOffset = ChunkLocation.GetOffset() + ChunkLocation.GetSize();
- m_CasLog.Append({.Key = ChunkHash, .Location = ChunkLocation, .Flags = CasDiskIndexEntry::kTombstone});
- m_LocationMap.erase(ChunkHash);
- if (m_CurrentInsertOffset == NextChunkOffset)
+ for (auto ChunkHash : DeletedChunks)
{
- m_CurrentInsertOffset = ChunkLocation.GetOffset();
+ auto KeyIt = m_LocationMap.find(ChunkHash);
+ const auto& ChunkLocation = KeyIt->second;
+ uint64_t NextChunkOffset = ChunkLocation.GetOffset() + ChunkLocation.GetSize();
+ m_CasLog.Append({.Key = ChunkHash, .Location = ChunkLocation, .Flags = CasDiskIndexEntry::kTombstone});
+ m_LocationMap.erase(ChunkHash);
+ if (m_CurrentInsertOffset == NextChunkOffset)
+ {
+ m_CurrentInsertOffset = ChunkLocation.GetOffset();
+ }
+ m_TotalSize.fetch_sub(static_cast<uint64_t>(ChunkLocation.GetSize()));
}
- m_TotalSize.fetch_sub(static_cast<uint64_t>(ChunkLocation.GetSize()));
- }
- // We can break here if we only want to remove items without compacting of space
+ // We can break here if we only want to remove items without compacting of space
- std::vector<IoHash> MovedChunks;
+ std::vector<IoHash> MovedChunks;
- uint64_t WriteOffset{};
- uint64_t ChunkIndex{};
- while (ChunkIndex < ChunkHashes.size())
- {
- IoHash ChunkHash = ChunkHashes[ChunkIndex];
- const auto& ChunkLocation = ChunkLocations[ChunkIndex];
+ uint64_t WriteOffset{};
+ uint64_t ChunkIndex{};
+ while (ChunkIndex < ChunkHashes.size())
+ {
+ IoHash ChunkHash = ChunkHashes[ChunkIndex];
+ const auto& ChunkLocation = ChunkLocations[ChunkIndex];
- uint64_t NextChunkOffset = AlignPositon(ChunkLocation.GetOffset() + ChunkLocation.GetSize(), m_PayloadAlignment);
+ uint64_t NextChunkOffset = AlignPositon(ChunkLocation.GetOffset() + ChunkLocation.GetSize(), m_PayloadAlignment);
- uint64_t FreeChunkSize = ChunkLocation.GetOffset() - WriteOffset;
+ uint64_t FreeChunkSize = ChunkLocation.GetOffset() - WriteOffset;
- // TODO: We could keep some wiggle room here, only try to find the last keep block if there is a reasonable amount of space free
- while (FreeChunkSize >= m_PayloadAlignment)
- {
- // We should move as many keep chunk at the end as we can possibly fit
- uint64_t LastKeepChunkIndex = ChunkHashes.size() - 1;
- if (LastKeepChunkIndex == ChunkIndex)
+ // TODO: We could keep some wiggle room here, only try to find the last keep block if there is a reasonable amount of space free
+ while (FreeChunkSize >= m_PayloadAlignment)
{
- break;
+ // We should move as many keep chunk at the end as we can possibly fit
+ uint64_t LastKeepChunkIndex = ChunkHashes.size() - 1;
+ if (LastKeepChunkIndex == ChunkIndex)
+ {
+ break;
+ }
+
+ IoHash LastChunkHash = ChunkHashes[LastKeepChunkIndex];
+ const auto& LastChunkLocation = ChunkLocations[LastKeepChunkIndex];
+ if (LastChunkLocation.GetSize() > FreeChunkSize)
+ {
+ break;
+ }
+
+ // Move the last chunk to our write location
+ std::vector<uint8_t> Chunk;
+ Chunk.resize(LastChunkLocation.GetSize());
+ m_SmallObjectFile.Read(Chunk.data(), Chunk.size(), LastChunkLocation.GetOffset());
+ CasDiskLocation NewChunkLocation(WriteOffset, Chunk.size());
+ m_SmallObjectFile.Write(Chunk.data(), Chunk.size(), NewChunkLocation.GetOffset());
+
+ CasDiskIndexEntry IndexEntry{.Key = ChunkHash, .Location = NewChunkLocation};
+ m_CasLog.Append(IndexEntry);
+ m_LocationMap[LastChunkHash] = NewChunkLocation;
+ ChunkHashes.pop_back();
+
+ WriteOffset = AlignPositon(WriteOffset + Chunk.size(), m_PayloadAlignment);
+ FreeChunkSize = ChunkLocation.GetOffset() - WriteOffset;
+ MovedChunks.push_back(LastChunkHash);
+
+ uint64_t LastChunkNextChunkOffset = AlignPositon(LastChunkLocation.GetOffset() + Chunk.size(), m_PayloadAlignment);
+ if (m_CurrentInsertOffset == LastChunkNextChunkOffset)
+ {
+ m_CurrentInsertOffset = LastChunkLocation.GetOffset();
+ }
}
- IoHash LastChunkHash = ChunkHashes[LastKeepChunkIndex];
- const auto& LastChunkLocation = ChunkLocations[LastKeepChunkIndex];
- if (LastChunkLocation.GetSize() > FreeChunkSize)
+ // TODO: We could keep some wiggle room here, don't move chunk if we only move it a very small amount
+ if (FreeChunkSize > m_PayloadAlignment)
+ {
+ std::vector<uint8_t> Chunk;
+ Chunk.resize(ChunkLocation.GetSize());
+ m_SmallObjectFile.Read(Chunk.data(), Chunk.size(), ChunkLocation.GetOffset());
+ CasDiskLocation NewChunkLocation(WriteOffset, Chunk.size());
+ m_SmallObjectFile.Write(Chunk.data(), Chunk.size(), NewChunkLocation.GetOffset());
+
+ CasDiskIndexEntry IndexEntry{.Key = ChunkHash, .Location = NewChunkLocation};
+ m_CasLog.Append(IndexEntry);
+ m_LocationMap[ChunkHash] = NewChunkLocation;
+
+ MovedChunks.push_back(ChunkHash);
+ WriteOffset = AlignPositon(NewChunkLocation.GetOffset() + Chunk.size(), m_PayloadAlignment);
+ }
+ else
{
- break;
+ WriteOffset = NextChunkOffset;
}
- // Move the last chunk to our write location
- std::vector<uint8_t> Chunk;
- Chunk.resize(LastChunkLocation.GetSize());
- m_SmallObjectFile.Read(Chunk.data(), Chunk.size(), LastChunkLocation.GetOffset());
- CasDiskLocation NewChunkLocation(WriteOffset, Chunk.size());
- m_SmallObjectFile.Write(Chunk.data(), Chunk.size(), NewChunkLocation.GetOffset());
+ // Update insert location if this is the last chunk in the file
+ if (m_CurrentInsertOffset == NextChunkOffset)
+ {
+ m_CurrentInsertOffset = WriteOffset;
+ }
- CasDiskIndexEntry IndexEntry{.Key = ChunkHash, .Location = NewChunkLocation};
- m_CasLog.Append(IndexEntry);
- m_LocationMap[LastChunkHash] = NewChunkLocation;
- ChunkHashes.pop_back();
+ // We can break here if we want to do incremental GC
- WriteOffset = AlignPositon(WriteOffset + Chunk.size(), m_PayloadAlignment);
- FreeChunkSize = ChunkLocation.GetOffset() - WriteOffset;
- MovedChunks.push_back(LastChunkHash);
+ ChunkIndex++;
+ }
- uint64_t LastChunkNextChunkOffset = AlignPositon(LastChunkLocation.GetOffset() + Chunk.size(), m_PayloadAlignment);
- if (m_CurrentInsertOffset == LastChunkNextChunkOffset)
- {
- m_CurrentInsertOffset = LastChunkLocation.GetOffset();
- }
+ if (ChunkCount == 0)
+ {
+ m_CurrentInsertOffset = 0;
}
- // TODO: We could keep some wiggle room here, don't move chunk if we only move it a very small amount
- if (FreeChunkSize > m_PayloadAlignment)
+ GcCtx.DeletedCas(DeletedChunks);
+
+ uint64_t CurrentSize = m_SmallObjectFile.FileSize();
+ ZEN_INFO("garbage collection complete '{}', space {} to {}, moved {} and delete {} chunks",
+ m_Config.RootDirectory / m_ContainerBaseName,
+ NiceBytes(CurrentSize),
+ NiceBytes(m_CurrentInsertOffset),
+ MovedChunks.size(),
+ DeletedChunks.size());
+ // TODO: Should we truncate the file or just keep the size of the file and reuse the space?
+ }
+
+ MakeIndexSnapshot();
+}
+
+void
+CasContainerStrategy::MakeIndexSnapshot()
+{
+ ZEN_INFO("writing index snapshot for '{}'", m_Config.RootDirectory / m_ContainerBaseName);
+
+ namespace fs = std::filesystem;
+
+ fs::path SlogPath = m_Config.RootDirectory / (m_ContainerBaseName + ".ulog");
+ fs::path SidxPath = m_Config.RootDirectory / (m_ContainerBaseName + ".uidx");
+ fs::path STmplogPath = m_Config.RootDirectory / (m_ContainerBaseName + ".tmp.ulog");
+ fs::path STmpSidxPath = m_Config.RootDirectory / (m_ContainerBaseName + ".tmp.uidx");
+ fs::path SRecoveredlogPath = m_Config.RootDirectory / (m_ContainerBaseName + ".recover.ulog");
+
+ // Move cas and index away, we keep them if something goes wrong, any new chunks will be added to the new log
+ {
+ RwLock::ExclusiveLockScope _(m_LocationMapLock);
+ m_CasLog.Close();
+
+ if (fs::exists(STmplogPath))
{
- std::vector<uint8_t> Chunk;
- Chunk.resize(ChunkLocation.GetSize());
- m_SmallObjectFile.Read(Chunk.data(), Chunk.size(), ChunkLocation.GetOffset());
- CasDiskLocation NewChunkLocation(WriteOffset, Chunk.size());
- m_SmallObjectFile.Write(Chunk.data(), Chunk.size(), NewChunkLocation.GetOffset());
-
- CasDiskIndexEntry IndexEntry{.Key = ChunkHash, .Location = NewChunkLocation};
- m_CasLog.Append(IndexEntry);
- m_LocationMap[ChunkHash] = NewChunkLocation;
-
- MovedChunks.push_back(ChunkHash);
- WriteOffset = AlignPositon(NewChunkLocation.GetOffset() + Chunk.size(), m_PayloadAlignment);
+ fs::remove(STmplogPath);
}
- else
+ if (fs::exists(STmpSidxPath))
{
- WriteOffset = NextChunkOffset;
+ fs::remove(STmpSidxPath);
}
- // Update insert location if this is the last chunk in the file
- if (m_CurrentInsertOffset == NextChunkOffset)
+ fs::rename(SlogPath, STmplogPath);
+ if (fs::exists(SidxPath))
{
- m_CurrentInsertOffset = WriteOffset;
+ fs::rename(SidxPath, STmpSidxPath);
}
- // We can break here if we want to do incremental GC
-
- ChunkIndex++;
+ // Open an new log
+ m_CasLog.Open(SlogPath, true);
}
- if (ChunkCount == 0)
+ try
{
- m_CurrentInsertOffset = 0;
- }
+ // Write the current state of the location map to a new index state
+ std::vector<CasDiskIndexEntry> Entries;
+
+ {
+ RwLock::SharedLockScope _l(m_LocationMapLock);
+ Entries.resize(m_LocationMap.size());
+
+ uint64_t EntryIndex = 0;
+ for (auto& Entry : m_LocationMap)
+ {
+ CasDiskIndexEntry& IndexEntry = Entries[EntryIndex++];
+ IndexEntry.Key = Entry.first;
+ IndexEntry.Location = Entry.second;
+ }
+ }
- if (!MovedChunks.empty() || DeletedChunks.empty())
+ BasicFile SmallObjectIndex;
+ SmallObjectIndex.Open(SidxPath, true);
+ SmallObjectIndex.Write(Entries.data(), Entries.size() * sizeof(CasDiskIndexEntry), 0);
+ SmallObjectIndex.Close();
+ }
+ catch (std::exception& Err)
{
- // // Rewrite object index
- // std::filesystem::path SidxPath = m_Config.RootDirectory / (m_ContainerBaseName + ".uidx");
- // std::filesystem::path TmpSidxPath = m_Config.RootDirectory / (m_ContainerBaseName + ".gc.uidx");
- // BasicFile TmpSmallObjectIndex;
- // TmpSmallObjectIndex.Open(TmpSidxPath, true);
- //
- // std::vector<CasDiskIndexEntry> Entries{m_LocationMap.size()};
- // uint64_t EntryIndex = 0;
- // for (auto& Entry : m_LocationMap)
- // {
- // CasDiskIndexEntry& IndexEntry = Entries[EntryIndex++];
- // IndexEntry.Key = Entry.first;
- // IndexEntry.Location = Entry.second;
- // }
- //
- // TmpSmallObjectIndex.Write(Entries.data(), Entries.size() * sizeof(CasDiskIndexEntry), 0);
- // TmpSmallObjectIndex.Close();
- //
- // m_SmallObjectIndex.Close();
- // fs::remove(SidxPath);
- // fs::rename(TmpSidxPath, SidxPath);
- // m_SmallObjectIndex.Open(SidxPath, false);
-
- // Rewrite cas log
- std::filesystem::path SlogPath = m_Config.RootDirectory / (m_ContainerBaseName + ".ulog");
- std::filesystem::path TmpSlogPath = m_Config.RootDirectory / (m_ContainerBaseName + ".gc.ulog");
- TCasLogFile<CasDiskIndexEntry> TmpCasLog;
- TmpCasLog.Open(TmpSlogPath, true);
+ ZEN_ERROR("snapshot FAILED, reason '{}'", Err.what());
- for (auto& Entry : m_LocationMap)
+ // Reconstruct the log from old log and any added log entries
+ RwLock::ExclusiveLockScope _(m_LocationMapLock);
+ if (fs::exists(STmplogPath))
{
- CasDiskIndexEntry IndexEntry{.Key = Entry.first, .Location = Entry.second};
- TmpCasLog.Append(IndexEntry);
+ std::vector<CasDiskIndexEntry> Records;
+ Records.reserve(m_LocationMap.size());
+ {
+ TCasLogFile<CasDiskIndexEntry> OldCasLog;
+ OldCasLog.Open(STmplogPath, false);
+ OldCasLog.Replay([&](const CasDiskIndexEntry& Record) { Records.push_back(Record); });
+ }
+ {
+ m_CasLog.Replay([&](const CasDiskIndexEntry& Record) { Records.push_back(Record); });
+ }
+
+ TCasLogFile<CasDiskIndexEntry> RecoveredCasLog;
+ RecoveredCasLog.Open(SRecoveredlogPath, true);
+ for (const auto& Record : Records)
+ {
+ RecoveredCasLog.Append(Record);
+ }
+ RecoveredCasLog.Close();
+
+ fs::remove(SlogPath);
+ fs::rename(SRecoveredlogPath, SlogPath);
+ fs::remove(STmplogPath);
}
- TmpCasLog.Close();
- m_CasLog.Close();
- fs::remove(SlogPath);
- fs::rename(TmpSlogPath, SlogPath);
- m_CasLog.Open(SlogPath, false);
- }
- uint64_t CurrentSize = m_SmallObjectFile.FileSize();
- ZEN_INFO("garbage collection complete '{}', space {} to {}, moved {} and delete {} chunks",
- m_Config.RootDirectory / m_ContainerBaseName,
- NiceBytes(CurrentSize),
- NiceBytes(m_CurrentInsertOffset),
- MovedChunks.size(),
- DeletedChunks.size());
+ if (fs::exists(SidxPath))
+ {
+ fs::remove(SidxPath);
+ }
- // TODO: Should we truncate the file or just keep the size of the file and reuse the space?
+ // Restore any previous snapshot
+ if (fs::exists(STmpSidxPath))
+ {
+ fs::remove(SidxPath);
+ fs::rename(STmpSidxPath, SidxPath);
+ }
+ }
+ if (fs::exists(STmpSidxPath))
+ {
+ fs::remove(STmpSidxPath);
+ }
}
void
CasContainerStrategy::OpenContainer(bool IsNewStore)
{
std::filesystem::path SobsPath = m_Config.RootDirectory / (m_ContainerBaseName + ".ucas");
- std::filesystem::path SidxPath = m_Config.RootDirectory / (m_ContainerBaseName + ".uidx");
std::filesystem::path SlogPath = m_Config.RootDirectory / (m_ContainerBaseName + ".ulog");
m_SmallObjectFile.Open(SobsPath, IsNewStore);
- // m_SmallObjectIndex.Open(SidxPath, IsNewStore);
m_CasLog.Open(SlogPath, IsNewStore);
// TODO: should validate integrity of container files here
m_CurrentInsertOffset = 0;
- // m_CurrentIndexOffset = 0;
- m_TotalSize = 0;
+ m_TotalSize = 0;
m_LocationMap.clear();
- uint64_t MaxFileOffset = 0;
+ std::filesystem::path SidxPath = m_Config.RootDirectory / (m_ContainerBaseName + ".uidx");
+ if (std::filesystem::exists(SidxPath))
+ {
+ BasicFile SmallObjectIndex;
+ SmallObjectIndex.Open(SidxPath, false);
+ uint64_t Size = SmallObjectIndex.FileSize();
+ uint64_t EntryCount = Size / sizeof(CasDiskIndexEntry);
+ std::vector<CasDiskIndexEntry> Entries{EntryCount};
+ SmallObjectIndex.Read(Entries.data(), Size, 0);
+ for (const auto& Entry : Entries)
+ {
+ m_LocationMap[Entry.Key] = Entry.Location;
+ }
+ SmallObjectIndex.Close();
+ }
m_CasLog.Replay([&](const CasDiskIndexEntry& Record) {
if (Record.Flags & CasDiskIndexEntry::kTombstone)
@@ -550,7 +632,7 @@ CasContainerStrategy::OpenContainer(bool IsNewStore)
}
});
- std::vector<CasDiskIndexEntry> Entries{m_LocationMap.size()};
+ uint64_t MaxFileOffset = 0;
for (const auto& Entry : m_LocationMap)
{
const auto& Location = Entry.second;
@@ -559,7 +641,6 @@ CasContainerStrategy::OpenContainer(bool IsNewStore)
}
m_CurrentInsertOffset = AlignPositon(MaxFileOffset, m_PayloadAlignment);
- // m_CurrentIndexOffset = m_SmallObjectIndex.FileSize();
}
//////////////////////////////////////////////////////////////////////////