diff options
| author | Dan Engelbrecht <[email protected]> | 2022-03-14 10:32:22 +0100 |
|---|---|---|
| committer | Dan Engelbrecht <[email protected]> | 2022-03-31 11:28:31 +0200 |
| commit | 53afe82f8433bf8506fef3dd4450b6d38352018f (patch) | |
| tree | 63b97516aa8dcb086107dc773c76e0ea32df14b0 /zenstore/compactcas.cpp | |
| parent | Add AlignPositon helper (diff) | |
| download | zen-53afe82f8433bf8506fef3dd4450b6d38352018f.tar.xz zen-53afe82f8433bf8506fef3dd4450b6d38352018f.zip | |
WIP
Diffstat (limited to 'zenstore/compactcas.cpp')
| -rw-r--r-- | zenstore/compactcas.cpp | 497 |
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(); } ////////////////////////////////////////////////////////////////////////// |