aboutsummaryrefslogtreecommitdiff
path: root/zenstore/compactcas.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2022-03-25 12:04:59 +0100
committerDan Engelbrecht <[email protected]>2022-03-31 11:29:27 +0200
commit6a166635b5c1d12aae5e58a04fbe423cf9995f6f (patch)
treed8ae7df19316397dd2e22a939c003a0b1da589d9 /zenstore/compactcas.cpp
parentMigration now works in larger disk IO chunks (diff)
downloadzen-6a166635b5c1d12aae5e58a04fbe423cf9995f6f.tar.xz
zen-6a166635b5c1d12aae5e58a04fbe423cf9995f6f.zip
incremental migration with optional clean of source
add more fine-grained access modes for BasicFile
Diffstat (limited to 'zenstore/compactcas.cpp')
-rw-r--r--zenstore/compactcas.cpp349
1 files changed, 182 insertions, 167 deletions
diff --git a/zenstore/compactcas.cpp b/zenstore/compactcas.cpp
index 9d0f72442..e389adb84 100644
--- a/zenstore/compactcas.cpp
+++ b/zenstore/compactcas.cpp
@@ -61,34 +61,39 @@ namespace {
const char* LogExtension = ".ulog";
const char* DataExtension = ".ucas";
+ std::filesystem::path GetBasePath(const std::filesystem::path& RootPath, const std::string& ContainerBaseName)
+ {
+ return RootPath / ContainerBaseName;
+ }
+
std::filesystem::path GetIndexPath(const std::filesystem::path& RootPath, const std::string& ContainerBaseName)
{
- return RootPath / ContainerBaseName / (ContainerBaseName + IndexExtension);
+ return GetBasePath(RootPath, ContainerBaseName) / (ContainerBaseName + IndexExtension);
}
std::filesystem::path GetTempIndexPath(const std::filesystem::path& RootPath, const std::string& ContainerBaseName)
{
- return RootPath / ContainerBaseName / (ContainerBaseName + ".tmp" + LogExtension);
+ return GetBasePath(RootPath, ContainerBaseName) / (ContainerBaseName + ".tmp" + LogExtension);
}
std::filesystem::path GetLogPath(const std::filesystem::path& RootPath, const std::string& ContainerBaseName)
{
- return RootPath / ContainerBaseName / (ContainerBaseName + LogExtension);
+ return GetBasePath(RootPath, ContainerBaseName) / (ContainerBaseName + LogExtension);
}
std::filesystem::path GetTempLogPath(const std::filesystem::path& RootPath, const std::string& ContainerBaseName)
{
- return RootPath / ContainerBaseName / (ContainerBaseName + ".tmp" + LogExtension);
+ return GetBasePath(RootPath, ContainerBaseName) / (ContainerBaseName + ".tmp" + LogExtension);
}
std::filesystem::path GetRecoverLogPath(const std::filesystem::path& RootPath, const std::string& ContainerBaseName)
{
- return RootPath / ContainerBaseName / (ContainerBaseName + ".recover" + LogExtension);
+ return GetBasePath(RootPath, ContainerBaseName) / (ContainerBaseName + ".recover" + LogExtension);
}
std::filesystem::path GetBlocksBasePath(const std::filesystem::path& RootPath, const std::string& ContainerBaseName)
{
- return RootPath / ContainerBaseName / "blocks";
+ return GetBasePath(RootPath, ContainerBaseName) / "blocks";
}
std::filesystem::path GetBlockPath(const std::filesystem::path& BlocksBasePath, const uint32_t BlockIndex)
@@ -109,7 +114,7 @@ namespace {
std::filesystem::path GetGCReservePath(const std::filesystem::path& RootPath, const std::string& ContainerBaseName)
{
- return RootPath / ContainerBaseName / (ContainerBaseName + ".gc.reserve" + DataExtension);
+ return GetBasePath(RootPath, ContainerBaseName) / (ContainerBaseName + ".gc.reserve" + DataExtension);
}
std::filesystem::path GetLegacyLogPath(const std::filesystem::path& RootPath, const std::string& ContainerBaseName)
@@ -164,12 +169,63 @@ namespace {
uint8_t Flags = 0;
};
- void Migrate(const std::filesystem::path& RootPath,
- const std::string& ContainerBaseName,
- uint64_t MaxBlockSize,
- uint64_t PayloadAlignment,
- bool Destructive,
- bool Overwrite)
+ bool ReadIndex(const std::filesystem::path& RootDirectory,
+ const std::string& ContainerBaseName,
+ uint64_t& InOutPayloadAlignment,
+ std::unordered_map<IoHash, BlockStoreDiskLocation, IoHash::Hasher>& OutLocationMap)
+ {
+ std::filesystem::path SidxPath = GetIndexPath(RootDirectory, ContainerBaseName);
+ if (std::filesystem::is_regular_file(SidxPath))
+ {
+ BasicFile ObjectIndexFile;
+ ObjectIndexFile.Open(SidxPath, BasicFile::EMode::kRead);
+ uint64_t Size = ObjectIndexFile.FileSize();
+ if (Size >= sizeof(CasDiskIndexHeader))
+ {
+ uint64_t ExpectedEntryCount = (Size - sizeof(sizeof(CasDiskIndexHeader))) / sizeof(CasDiskIndexEntry);
+ CasDiskIndexHeader Header;
+ ObjectIndexFile.Read(&Header, sizeof(Header), 0);
+ if (Header.Magic == CasDiskIndexHeader::ExpectedMagic && Header.Version == CasDiskIndexHeader::CurrentVersion &&
+ Header.PayloadAlignment > 0 && Header.EntryCount == ExpectedEntryCount)
+ {
+ std::vector<CasDiskIndexEntry> Entries{Header.EntryCount};
+ ObjectIndexFile.Read(Entries.data(), Header.EntryCount * sizeof(CasDiskIndexEntry), sizeof(CasDiskIndexHeader));
+ for (const auto& Entry : Entries)
+ {
+ OutLocationMap[Entry.Key] = Entry.Location;
+ }
+ InOutPayloadAlignment = Header.PayloadAlignment;
+ }
+ }
+ }
+
+ bool AddedFromCasLog = false;
+ TCasLogFile<CasDiskIndexEntry> CasLog;
+ std::filesystem::path SlogPath = GetLogPath(RootDirectory, ContainerBaseName);
+ if (std::filesystem::is_regular_file(SlogPath))
+ {
+ CasLog.Open(SlogPath, CasLogFile::EMode::kRead);
+ CasLog.Replay([&](const CasDiskIndexEntry& Record) {
+ if (Record.Flags & CasDiskIndexEntry::kTombstone)
+ {
+ OutLocationMap.erase(Record.Key);
+ }
+ else
+ {
+ OutLocationMap[Record.Key] = Record.Location;
+ }
+ AddedFromCasLog = true;
+ });
+ }
+ return AddedFromCasLog;
+ }
+
+ uint64_t MigrateLegacyData(const std::filesystem::path& RootPath,
+ const std::string& ContainerBaseName,
+ uint64_t MaxBlockSize,
+ uint64_t PayloadAlignment,
+ bool CleanSource,
+ std::unordered_map<IoHash, BlockStoreDiskLocation, IoHash::Hasher>& InOutLocationMap)
{
std::filesystem::path BlocksBasePath = GetBlocksBasePath(RootPath, ContainerBaseName);
std::filesystem::path LegacyLogPath = GetLegacyLogPath(RootPath, ContainerBaseName);
@@ -177,17 +233,7 @@ namespace {
if (!std::filesystem::is_regular_file(LegacyLogPath) || !std::filesystem::is_regular_file(LegacySobsPath))
{
ZEN_DEBUG("migrate of {} SKIPPED, no legacy data found", RootPath / ContainerBaseName);
- return;
- }
-
- std::filesystem::path SlogPath = GetLogPath(RootPath, ContainerBaseName);
- if (std::filesystem::is_directory(SlogPath.parent_path()))
- {
- if (!Overwrite)
- {
- ZEN_WARN("migrate of {} SKIPPED, new content already exists", RootPath / ContainerBaseName);
- return;
- }
+ return 0;
}
uint32_t NewBlockIndex = 0;
@@ -201,12 +247,18 @@ namespace {
NiceBytes(TotalSize));
});
+ uint32_t WriteBlockIndex = 0;
+ while (std::filesystem::exists(GetBlockPath(BlocksBasePath, WriteBlockIndex)))
+ {
+ ++WriteBlockIndex;
+ }
+
std::error_code Error;
DiskSpace Space = DiskSpaceInfo(RootPath, Error);
if (Error)
{
ZEN_ERROR("get disk space in {} FAILED, reason '{}'", ContainerBaseName, Error.message());
- return;
+ return 0;
}
if (Space.Free < MaxBlockSize)
@@ -215,7 +267,7 @@ namespace {
RootPath / ContainerBaseName,
MaxBlockSize,
NiceBytes(Space.Free));
- return;
+ return 0;
}
BasicFile BlockFile;
@@ -225,7 +277,7 @@ namespace {
std::unordered_map<IoHash, LegacyCasDiskIndexEntry, IoHash::Hasher> LegacyDiskIndex;
TCasLogFile<LegacyCasDiskIndexEntry> LegacyCasLog;
- LegacyCasLog.Open(LegacyLogPath, CasLogFile::EMode::kRead);
+ LegacyCasLog.Open(LegacyLogPath, CleanSource ? CasLogFile::EMode::kWrite : CasLogFile::EMode::kRead);
LegacyCasLog.Replay([&](const LegacyCasDiskIndexEntry& Record) {
if (Record.Flags & LegacyCasDiskIndexEntry::kTombstone)
{
@@ -237,9 +289,18 @@ namespace {
{
return;
}
+ if (InOutLocationMap.contains(Record.Key))
+ {
+ return;
+ }
LegacyDiskIndex[Record.Key] = Record;
});
+ if (LegacyDiskIndex.empty())
+ {
+ return 0;
+ }
+
uint64_t MaxUsedSize = 0;
for (const auto& Entry : LegacyDiskIndex)
{
@@ -260,9 +321,10 @@ namespace {
RootPath / ContainerBaseName,
MaxRequiredBlockCount,
BlockStoreDiskLocation::MaxBlockIndex);
- return;
+ return 0;
}
- if (Destructive)
+
+ if (CleanSource)
{
if (Space.Free < (MaxBlockSize + (1 << 28)))
{
@@ -271,7 +333,7 @@ namespace {
NewBlockIndex + 1,
NiceBytes(MaxBlockSize + (1 << 28)),
NiceBytes(Space.Free));
- return;
+ return 0;
}
}
else
@@ -283,15 +345,18 @@ namespace {
NewBlockIndex + 1,
NiceBytes(RequiredDiskSpace + (1 << 28)),
NiceBytes(Space.Free));
- return;
+ return 0;
}
}
+ std::filesystem::path SlogPath = GetLogPath(RootPath, ContainerBaseName);
CreateDirectories(SlogPath.parent_path());
TCasLogFile<CasDiskIndexEntry> CasLog;
- CasLog.Open(SlogPath, CasLogFile::EMode::kTruncate);
+ CasLog.Open(SlogPath, CasLogFile::EMode::kWrite);
- if (Destructive && (MaxRequiredBlockCount < 2))
+ uint64_t MovedCount = 0;
+
+ if (CleanSource && (MaxRequiredBlockCount < 2))
{
std::vector<CasDiskIndexEntry> LogEntries;
LogEntries.reserve(LegacyDiskIndex.size());
@@ -301,16 +366,18 @@ namespace {
{
const LegacyCasDiskIndexEntry& Record(Entry.second);
- BlockStoreLocation NewChunkLocation(0, Record.Location.GetOffset(), Record.Location.GetSize());
- LogEntries.push_back({.Key = Entry.second.Key,
- .Location = BlockStoreDiskLocation(NewChunkLocation, PayloadAlignment),
- .ContentType = Record.ContentType,
- .Flags = Record.Flags});
+ BlockStoreLocation NewChunkLocation(WriteBlockIndex, Record.Location.GetOffset(), Record.Location.GetSize());
+ BlockStoreDiskLocation NewLocation(NewChunkLocation, PayloadAlignment);
+ LogEntries.push_back(
+ {.Key = Entry.second.Key, .Location = NewLocation, .ContentType = Record.ContentType, .Flags = Record.Flags});
+ InOutLocationMap[Entry.second.Key] = NewLocation;
}
- auto BlockPath = GetBlockPath(BlocksBasePath, 0);
+ auto BlockPath = GetBlockPath(BlocksBasePath, WriteBlockIndex);
CreateDirectories(BlockPath.parent_path());
BlockFile.Close();
std::filesystem::rename(LegacySobsPath, BlockPath);
+ CasLog.Append(LogEntries);
+ MovedCount = LogEntries.size();
}
else
{
@@ -329,7 +396,6 @@ namespace {
uint64_t BlockSize = 0;
uint64_t BlockOffset = 0;
- uint32_t BlockIndex = 0;
std::vector<BlockStoreLocation> NewLocations;
struct BlockData
{
@@ -350,44 +416,33 @@ namespace {
uint64_t ChunkOffset = LegacyChunkLocation.GetOffset();
uint64_t ChunkSize = LegacyChunkLocation.GetSize();
- #if 0
- {
- std::vector<uint8_t> Data(ChunkSize);
- BlockFile.Read(Data.data(), ChunkSize, ChunkOffset);
- const IoHash ComputedHash = IoHash::HashBuffer(Data.data(), ChunkSize);
- if (ComputedHash != ChunkHash)
- {
- ZEN_ERROR("migrating store {}, invalid hash for chunk {}. Got {}",
- RootPath / ContainerBaseName,
- ChunkHash,
- ComputedHash);
- }
- }
- #endif // 0
-
if (BlockSize == 0)
{
BlockOffset = ChunkOffset;
}
if ((BlockSize + ChunkSize) > MaxBlockSize)
{
- BlockData BlockRange{.BlockOffset = BlockOffset, .BlockSize = BlockSize, .BlockIndex = BlockIndex};
+ BlockData BlockRange{.BlockOffset = BlockOffset, .BlockSize = BlockSize, .BlockIndex = WriteBlockIndex};
BlockRange.Chunks.swap(Chunks);
BlockRanges.push_back(BlockRange);
- BlockIndex++;
+ WriteBlockIndex++;
+ while (std::filesystem::exists(GetBlockPath(BlocksBasePath, WriteBlockIndex)))
+ {
+ ++WriteBlockIndex;
+ }
BlockOffset = ChunkOffset;
BlockSize = 0;
}
BlockSize = RoundUp(BlockSize, PayloadAlignment);
- BlockStoreLocation ChunkLocation = {.BlockIndex = BlockIndex, .Offset = BlockSize, .Size = ChunkSize};
+ BlockStoreLocation ChunkLocation = {.BlockIndex = WriteBlockIndex, .Offset = BlockSize, .Size = ChunkSize};
Chunks.push_back({ChunkHash, ChunkLocation});
BlockSize += ChunkSize;
}
if (BlockSize > 0)
{
BlockRanges.push_back(
- {.Chunks = std::move(Chunks), .BlockOffset = BlockOffset, .BlockSize = BlockSize, .BlockIndex = BlockIndex});
+ {.Chunks = std::move(Chunks), .BlockOffset = BlockOffset, .BlockSize = BlockSize, .BlockIndex = WriteBlockIndex});
}
std::reverse(BlockRanges.begin(), BlockRanges.end());
@@ -428,25 +483,12 @@ namespace {
BlockStoreDiskLocation Location(Entry.second, PayloadAlignment);
LogEntries.push_back(
{.Key = Entry.first, .Location = Location, .ContentType = LegacyEntry.ContentType, .Flags = LegacyEntry.Flags});
+ InOutLocationMap[Entry.first] = Location;
}
CasLog.Append(LogEntries);
- #if 0
- for (const CasDiskIndexEntry& Entry : LogEntries)
- {
- std::vector<uint8_t> Data(Entry.Location.GetSize());
- ChunkBlock.Read(Data.data(), Entry.Location.GetSize(), Entry.Location.GetOffset(PayloadAlignment));
- const IoHash ComputedHash = IoHash::HashBuffer(Data.data(), Entry.Location.GetSize());
- if (ComputedHash != Entry.Key)
- {
- ZEN_ERROR("migrating store {}, invalid hash for chunk {}. Got {}",
- RootPath / ContainerBaseName,
- Entry.Key,
- ComputedHash);
- }
- }
- #endif // 0
+ MovedCount += LogEntries.size();
- if (Destructive)
+ if (CleanSource)
{
std::vector<LegacyCasDiskIndexEntry> LegacyLogEntries;
LegacyLogEntries.reserve(BlockRange.Chunks.size());
@@ -462,10 +504,13 @@ namespace {
LegacyCasLog.Close();
CasLog.Close();
- if (Destructive)
+ if (CleanSource)
{
std::filesystem::remove(LegacyLogPath);
+ BlockFile.Close();
+ std::filesystem::remove(LegacySobsPath);
}
+ return MovedCount;
}
} // namespace
@@ -1244,84 +1289,32 @@ CasContainerStrategy::OpenContainer(bool IsNewStore)
m_LocationMap.clear();
- std::filesystem::path SidxPath = GetIndexPath(m_Config.RootDirectory, m_ContainerBaseName);
- std::filesystem::path SlogPath = GetLogPath(m_Config.RootDirectory, m_ContainerBaseName);
- std::filesystem::path LegacyLogPath = GetLegacyLogPath(m_Config.RootDirectory, m_ContainerBaseName);
- std::filesystem::path LegacySobsPath = GetLegacyUcasPath(m_Config.RootDirectory, m_ContainerBaseName);
-
- bool CasLogEmpty = true;
+ std::filesystem::path BasePath = GetBasePath(m_Config.RootDirectory, m_ContainerBaseName);
if (IsNewStore)
{
- if (std::filesystem::is_regular_file(LegacyLogPath))
- {
- std::filesystem::remove(LegacyLogPath);
- }
- if (std::filesystem::is_regular_file(LegacySobsPath))
- {
- std::filesystem::remove(LegacySobsPath);
- }
- if (std::filesystem::is_regular_file(SlogPath))
- {
- std::filesystem::remove(SlogPath);
- }
- if (std::filesystem::is_regular_file(SidxPath))
- {
- std::filesystem::remove(SidxPath);
- }
- CreateDirectories(SlogPath.parent_path());
- m_CasLog.Open(SlogPath, CasLogFile::EMode::kTruncate);
+ std::filesystem::path LegacyLogPath = GetLegacyLogPath(m_Config.RootDirectory, m_ContainerBaseName);
+ std::filesystem::path LegacySobsPath = GetLegacyUcasPath(m_Config.RootDirectory, m_ContainerBaseName);
+ std::filesystem::remove(LegacyLogPath);
+ std::filesystem::remove(LegacySobsPath);
+ std::filesystem::remove_all(BasePath);
}
- else
- {
- // Keep the old cache intact for now
- Migrate(m_Config.RootDirectory, m_ContainerBaseName, m_MaxBlockSize, m_PayloadAlignment, false, true);
- if (std::filesystem::is_regular_file(SidxPath))
- {
- BasicFile ObjectIndexFile;
- ObjectIndexFile.Open(SidxPath, BasicFile::EMode::kRead);
- uint64_t Size = ObjectIndexFile.FileSize();
- if (Size >= sizeof(CasDiskIndexHeader))
- {
- uint64_t ExpectedEntryCount = (Size - sizeof(sizeof(CasDiskIndexHeader))) / sizeof(CasDiskIndexEntry);
- CasDiskIndexHeader Header;
- ObjectIndexFile.Read(&Header, sizeof(Header), 0);
- if (Header.Magic == CasDiskIndexHeader::ExpectedMagic && Header.Version == CasDiskIndexHeader::CurrentVersion &&
- Header.PayloadAlignment > 0 && Header.EntryCount == ExpectedEntryCount)
- {
- std::vector<CasDiskIndexEntry> Entries{Header.EntryCount};
- ObjectIndexFile.Read(Entries.data(), Header.EntryCount * sizeof(CasDiskIndexEntry), sizeof(CasDiskIndexHeader));
- ObjectIndexFile.Close();
- for (const auto& Entry : Entries)
- {
- m_LocationMap[Entry.Key] = Entry.Location;
- }
- m_PayloadAlignment = Header.PayloadAlignment;
- }
- }
- }
+ bool AddedFromCasLog = ReadIndex(m_Config.RootDirectory, m_ContainerBaseName, m_PayloadAlignment, m_LocationMap);
- m_CasLog.Open(SlogPath, CasLogFile::EMode::kWrite);
- m_CasLog.Replay([&](const CasDiskIndexEntry& Record) {
- if (Record.Flags & CasDiskIndexEntry::kTombstone)
- {
- m_LocationMap.erase(Record.Key);
- }
- else
- {
- m_LocationMap[Record.Key] = Record.Location;
- }
- CasLogEmpty = false;
- });
- }
+ MigrateLegacyData(m_Config.RootDirectory, m_ContainerBaseName, m_MaxBlockSize, m_PayloadAlignment, false, m_LocationMap);
+
+ CreateDirectories(BasePath);
+
+ std::filesystem::path SlogPath = GetLogPath(m_Config.RootDirectory, m_ContainerBaseName);
+ m_CasLog.Open(SlogPath, CasLogFile::EMode::kWrite);
- std::unordered_set<uint32_t> BlockUsage;
+ std::unordered_set<uint32_t> KnownBlocks;
for (const auto& Entry : m_LocationMap)
{
const BlockStoreDiskLocation& Location = Entry.second;
m_TotalSize.fetch_add(Location.GetSize(), std::memory_order_release);
- BlockUsage.insert(Location.GetBlockIndex());
+ KnownBlocks.insert(Location.GetBlockIndex());
}
if (std::filesystem::is_directory(m_BlocksBasePath))
@@ -1357,7 +1350,7 @@ CasContainerStrategy::OpenContainer(bool IsNewStore)
{
continue;
}
- if (!BlockUsage.contains(BlockIndex))
+ if (!KnownBlocks.contains(BlockIndex))
{
// Clear out unused blocks
std::filesystem::remove(Path);
@@ -1388,38 +1381,39 @@ CasContainerStrategy::OpenContainer(bool IsNewStore)
{
GCReserveFile.Open(GCReservePath, BasicFile::EMode::kWrite);
std::uint64_t CurrentSize = GCReserveFile.FileSize();
- if (CurrentSize != m_MaxBlockSize)
+ if ((Space.Free - 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
- {
- // We need it to be the proper size if we are to use it
- std::filesystem::remove(GCReservePath);
- }
- }
+ GCReserveFile.SetFileSize(m_MaxBlockSize);
+ }
+ else
+ {
+ // We need it to be the proper size if we are to use it
+ ZEN_WARN("removing gc reserve {}, not enough space free on drive, need {}, have {} ",
+ m_Config.RootDirectory / m_ContainerBaseName,
+ NiceBytes(m_MaxBlockSize),
+ NiceBytes(Space.Free));
+
+ std::filesystem::remove(GCReservePath);
}
}
else
{
- if (Space.Free > m_MaxBlockSize)
+ if (Space.Free >= m_MaxBlockSize)
{
CreateDirectories(GCReservePath.parent_path());
GCReserveFile.Open(GCReservePath, BasicFile::EMode::kTruncate);
GCReserveFile.SetFileSize(m_MaxBlockSize);
}
+ else
+ {
+ ZEN_WARN("can't create gc reserve {}, not enough space free on drive, need {}, have {} ",
+ m_Config.RootDirectory / m_ContainerBaseName,
+ NiceBytes(m_MaxBlockSize),
+ NiceBytes(Space.Free));
+ }
}
- if (!CasLogEmpty)
+ if (AddedFromCasLog)
{
MakeIndexSnapshot();
}
@@ -2319,9 +2313,30 @@ TEST_CASE("compactcas.threadedinsert") // * doctest::skip(true))
TEST_CASE("compactcas.migrate.large.data" * doctest::skip(true))
{
- const char* BigDataPath = "D:\\zen-data\\dc4-zen-cache-t\\cas";
- Migrate(BigDataPath, "tobs", 1u << 28, 16, false, true);
- Migrate(BigDataPath, "sobs", 1u << 30, 4096, false, true);
+ const char* BigDataPath = "D:\\zen-data\\dc4-zen-cache-t\\cas";
+ std::filesystem::path TobsBasePath = GetBasePath(BigDataPath, "tobs");
+ std::filesystem::path SobsBasePath = GetBasePath(BigDataPath, "sobs");
+ std::filesystem::remove_all(TobsBasePath);
+ std::filesystem::remove_all(SobsBasePath);
+ uint64_t TobsPayloadAlignment = 16;
+ uint64_t TobsBlockSize = 1u << 28;
+ std::unordered_map<IoHash, BlockStoreDiskLocation, IoHash::Hasher> TobsLocationMap;
+ uint64_t MigratedTobsCount = MigrateLegacyData(BigDataPath, "tobs", TobsBlockSize, TobsPayloadAlignment, false, TobsLocationMap);
+ CHECK(MigratedTobsCount > 0);
+ TobsLocationMap.clear();
+ ReadIndex(BigDataPath, "tobs", TobsPayloadAlignment, TobsLocationMap);
+ uint64_t MigratedTobsCount2 = MigrateLegacyData(BigDataPath, "tobs", TobsBlockSize, TobsPayloadAlignment, false, TobsLocationMap);
+ CHECK(MigratedTobsCount2 == 0);
+
+ uint64_t SobsPayloadAlignment = 4096;
+ uint64_t SobsBlockSize = 1u << 30;
+ std::unordered_map<IoHash, BlockStoreDiskLocation, IoHash::Hasher> SobsLocationMap;
+ uint64_t MigratedSobsCount = MigrateLegacyData(BigDataPath, "sobs", SobsBlockSize, SobsPayloadAlignment, false, SobsLocationMap);
+ CHECK(MigratedSobsCount > 0);
+ SobsLocationMap.clear();
+ ReadIndex(BigDataPath, "sobs", SobsPayloadAlignment, SobsLocationMap);
+ uint64_t MigratedSobsCount2 = MigrateLegacyData(BigDataPath, "sobs", SobsBlockSize, SobsPayloadAlignment, false, SobsLocationMap);
+ CHECK(MigratedSobsCount2 == 0);
CasStoreConfiguration CasConfig;
CasConfig.RootDirectory = BigDataPath;