aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2025-09-23 16:23:31 +0200
committerGitHub Enterprise <[email protected]>2025-09-23 16:23:31 +0200
commit2de9f8cdca2929dabbe65e6a51adf27d1a45d830 (patch)
tree9ae4833e1ec94445273b0163c9b755ab6156ee36 /src
parent5.7.2-pre1 (diff)
downloadzen-2de9f8cdca2929dabbe65e6a51adf27d1a45d830.tar.xz
zen-2de9f8cdca2929dabbe65e6a51adf27d1a45d830.zip
limit number of chunks per block (#508)
- Improvement: Chunk block generation for `zen oplog-export` and `zen builds upload` command are now limited to max 4000 chunks per block zen builds list-block testing function to check results for recently used blocks in a context
Diffstat (limited to 'src')
-rw-r--r--src/zen/cmds/builds_cmd.cpp111
-rw-r--r--src/zen/cmds/builds_cmd.h6
-rw-r--r--src/zen/cmds/projectstore_cmd.cpp17
-rw-r--r--src/zen/cmds/projectstore_cmd.h3
-rw-r--r--src/zenserver/projectstore/projectstore.cpp113
-rw-r--r--src/zenserver/projectstore/remoteprojectstore.cpp9
-rw-r--r--src/zenserver/projectstore/remoteprojectstore.h4
7 files changed, 202 insertions, 61 deletions
diff --git a/src/zen/cmds/builds_cmd.cpp b/src/zen/cmds/builds_cmd.cpp
index d9f57959e..fee2adaee 100644
--- a/src/zen/cmds/builds_cmd.cpp
+++ b/src/zen/cmds/builds_cmd.cpp
@@ -263,16 +263,19 @@ namespace {
}
static const size_t DefaultMaxBlockSize = 64u * 1024u * 1024u;
+ static const size_t DefaultMaxChunksPerBlock = 4u * 1000u;
static const size_t DefaultMaxChunkEmbedSize = 3u * 512u * 1024u;
struct ChunksBlockParameters
{
size_t MaxBlockSize = DefaultMaxBlockSize;
+ size_t MaxChunksPerBlock = DefaultMaxChunksPerBlock;
size_t MaxChunkEmbedSize = DefaultMaxChunkEmbedSize;
};
const ChunksBlockParameters DefaultChunksBlockParams{
.MaxBlockSize = 32u * 1024u * 1024u,
+ .MaxChunksPerBlock = DefaultMaxChunksPerBlock,
.MaxChunkEmbedSize = 2u * 1024u * 1024u // DefaultChunkedParams.MaxSize
};
const uint64_t DefaultPreferredMultipartChunkSize = 32u * 1024u * 1024u;
@@ -2614,6 +2617,7 @@ namespace {
void ArrangeChunksIntoBlocks(const ChunkedFolderContent& Content,
const ChunkedContentLookup& Lookup,
uint64_t MaxBlockSize,
+ uint64_t MaxChunksPerBlock,
std::vector<uint32_t>& ChunkIndexes,
std::vector<std::vector<uint32_t>>& OutBlocks)
{
@@ -2642,7 +2646,7 @@ namespace {
const uint32_t ChunkIndex = ChunkIndexes[ChunkIndexOffset];
const uint64_t ChunkSize = Content.ChunkedContent.ChunkRawSizes[ChunkIndex];
- if ((BlockSize + ChunkSize) > MaxBlockSize)
+ if (((BlockSize + ChunkSize) > MaxBlockSize) || (ChunkIndexOffset - ChunkIndexStart) > MaxChunksPerBlock)
{
// Within the span of MaxBlockSizeLowThreshold and MaxBlockSize, see if there is a break
// between source paths for chunks. Break the block at the last such break if any.
@@ -4091,7 +4095,12 @@ namespace {
}
std::vector<std::vector<uint32_t>> NewBlockChunks;
- ArrangeChunksIntoBlocks(LocalContent, LocalLookup, DefaultChunksBlockParams.MaxBlockSize, NewBlockChunkIndexes, NewBlockChunks);
+ ArrangeChunksIntoBlocks(LocalContent,
+ LocalLookup,
+ DefaultChunksBlockParams.MaxBlockSize,
+ DefaultChunksBlockParams.MaxChunksPerBlock,
+ NewBlockChunkIndexes,
+ NewBlockChunks);
FindBlocksStats.NewBlocksCount = NewBlockChunks.size();
for (uint32_t ChunkIndex : NewBlockChunkIndexes)
@@ -10352,6 +10361,25 @@ BuildsCommand::BuildsCommand()
m_ListOptions.parse_positional({"query-path", "result-path"});
m_ListOptions.positional_help("query-path result-path");
+ // list-blocks
+ AddSystemOptions(m_ListBlocksOptions);
+ AddCloudOptions(m_ListBlocksOptions);
+ AddZenFolderOptions(m_ListBlocksOptions);
+ m_ListBlocksOptions.add_options()("h,help", "Print help");
+ m_ListBlocksOptions.add_option("", "", "build-id", "Build Id", cxxopts::value(m_BuildId), "<id>");
+ m_ListBlocksOptions.add_option("",
+ "",
+ "result-path",
+ "Path to json or compactbinary to write query result to",
+ cxxopts::value(m_ListResultPath),
+ "<result-path>");
+
+ m_ListBlocksOptions
+ .add_option("", "", "max-count", "Maximum number of blocks to list", cxxopts::value(m_ListBlocksMaxCount), "<maxcount>");
+
+ m_ListBlocksOptions.parse_positional({"build-id"});
+ m_ListBlocksOptions.positional_help("build-id");
+
// upload
AddSystemOptions(m_UploadOptions);
AddCloudOptions(m_UploadOptions);
@@ -11304,6 +11332,85 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
return;
}
+ if (SubOption == &m_ListBlocksOptions)
+ {
+ MakeSafeAbsolutePathÍnPlace(m_ListResultPath);
+
+ if (!m_ListResultPath.empty())
+ {
+ if (!IsQuiet)
+ {
+ ZEN_CONSOLE("Running {}: {} (pid {})",
+ GetRunningExecutablePath(),
+ ZEN_CFG_VERSION_BUILD_STRING_FULL,
+ GetCurrentProcessId());
+ }
+ }
+
+ if (m_ListBlocksMaxCount == 0)
+ {
+ throw OptionParseException(fmt::format("'--max-count' ('{}') is invalid", m_ListBlocksMaxCount), SubOption->help());
+ }
+
+ BuildStorage::Statistics StorageStats;
+ BuildStorageCache::Statistics StorageCacheStats;
+
+ if (m_ZenFolderPath.empty())
+ {
+ m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName;
+ }
+ MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath);
+
+ CreateDirectories(m_ZenFolderPath);
+ auto _ = MakeGuard([this]() {
+ if (CleanDirectory(m_ZenFolderPath, {}))
+ {
+ std::error_code DummyEc;
+ RemoveDir(m_ZenFolderPath, DummyEc);
+ }
+ });
+
+ StorageInstance Storage = CreateBuildStorage(StorageStats,
+ StorageCacheStats,
+ ZenTempFolderPath(m_ZenFolderPath),
+ /*RequriesNamespace*/ true,
+ /*RequireBucket*/ true);
+
+ const Oid BuildId = ParseBuildId();
+
+ CbObject Response = Storage.BuildStorage->FindBlocks(BuildId, m_ListBlocksMaxCount);
+ ZEN_ASSERT(ValidateCompactBinary(Response.GetView(), CbValidateMode::Default) == CbValidateError::None);
+
+ std::vector<ChunkBlockDescription> BlockDescriptions = ParseChunkBlockDescriptionList(Response);
+ if (!IsQuiet)
+ {
+ ZEN_CONSOLE("Response contains {} block", BlockDescriptions.size());
+ }
+ if (m_ListResultPath.empty())
+ {
+ ExtendableStringBuilder<1024> SB;
+ CompactBinaryToJson(Response.GetView(), SB);
+ ForEachStrTok(SB.ToView(), '\n', [](std::string_view Row) {
+ ZEN_CONSOLE("{}", Row);
+ return true;
+ });
+ }
+ else
+ {
+ if (ToLower(m_ListResultPath.extension().string()) == ".cbo")
+ {
+ MemoryView ResponseView = Response.GetView();
+ WriteFile(m_ListResultPath, IoBuffer(IoBuffer::Wrap, ResponseView.GetData(), ResponseView.GetSize()));
+ }
+ else
+ {
+ ExtendableStringBuilder<1024> SB;
+ CompactBinaryToJson(Response.GetView(), SB);
+ WriteFile(m_ListResultPath, IoBuffer(IoBuffer::Wrap, SB.Data(), SB.Size()));
+ }
+ }
+ return;
+ }
if (SubOption == &m_UploadOptions)
{
if (!IsQuiet)
diff --git a/src/zen/cmds/builds_cmd.h b/src/zen/cmds/builds_cmd.h
index 27a178c6f..ddec1f791 100644
--- a/src/zen/cmds/builds_cmd.h
+++ b/src/zen/cmds/builds_cmd.h
@@ -79,6 +79,9 @@ private:
std::filesystem::path m_ListQueryPath;
std::filesystem::path m_ListResultPath;
+ cxxopts::Options m_ListBlocksOptions{"list-blocks", "List recent blocks"};
+ uint32_t m_ListBlocksMaxCount = 16;
+
std::filesystem::path m_Path;
cxxopts::Options m_UploadOptions{"upload", "Upload a folder"};
@@ -115,8 +118,9 @@ private:
cxxopts::Options m_MultiTestDownloadOptions{"multi-test-download", "Test multiple sequenced downloads with verify"};
std::vector<std::string> m_BuildIds;
- cxxopts::Options* m_SubCommands[13] = {&m_ListNamespacesOptions,
+ cxxopts::Options* m_SubCommands[14] = {&m_ListNamespacesOptions,
&m_ListOptions,
+ &m_ListBlocksOptions,
&m_UploadOptions,
&m_DownloadOptions,
&m_PauseOptions,
diff --git a/src/zen/cmds/projectstore_cmd.cpp b/src/zen/cmds/projectstore_cmd.cpp
index b738d16aa..c9f787915 100644
--- a/src/zen/cmds/projectstore_cmd.cpp
+++ b/src/zen/cmds/projectstore_cmd.cpp
@@ -823,6 +823,12 @@ ExportOplogCommand::ExportOplogCommand()
m_Options.add_option("", "", "maxblocksize", "Max size for bundled attachments", cxxopts::value(m_MaxBlockSize), "<blocksize>");
m_Options.add_option("",
"",
+ "maxchunksperblock",
+ "Max number of chunks in one block",
+ cxxopts::value(m_MaxChunksPerBlock),
+ "<maxchunksperblock>");
+ m_Options.add_option("",
+ "",
"maxchunkembedsize",
"Max size for attachment to be bundled",
cxxopts::value(m_MaxChunkEmbedSize),
@@ -1119,6 +1125,10 @@ ExportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
{
Writer.AddInteger("maxblocksize"sv, m_MaxBlockSize);
}
+ if (m_MaxChunksPerBlock != 0)
+ {
+ Writer.AddInteger("maxchunksperblock"sv, m_MaxChunksPerBlock);
+ }
if (m_MaxChunkEmbedSize != 0)
{
Writer.AddInteger("maxchunkembedsize"sv, m_MaxChunkEmbedSize);
@@ -1308,13 +1318,6 @@ ImportOplogCommand::ImportOplogCommand()
"Absolute path to oplog lifetime marker file if we create the oplog",
cxxopts::value(m_GcPath),
"<path>");
- m_Options.add_option("", "", "maxblocksize", "Max size for bundled attachments", cxxopts::value(m_MaxBlockSize), "<blocksize>");
- m_Options.add_option("",
- "",
- "maxchunkembedsize",
- "Max size for attachment to be bundled",
- cxxopts::value(m_MaxChunkEmbedSize),
- "<chunksize>");
m_Options.add_option("", "f", "force", "Force import of all attachments", cxxopts::value(m_Force), "<force>");
m_Options.add_option("", "a", "async", "Trigger import but don't wait for completion", cxxopts::value(m_Async), "<async>");
m_Options.add_option("", "", "clean", "Delete existing target oplog", cxxopts::value(m_Clean), "<clean>");
diff --git a/src/zen/cmds/projectstore_cmd.h b/src/zen/cmds/projectstore_cmd.h
index 136319aa3..ae8233f51 100644
--- a/src/zen/cmds/projectstore_cmd.h
+++ b/src/zen/cmds/projectstore_cmd.h
@@ -99,6 +99,7 @@ private:
std::string m_ProjectName;
std::string m_OplogName;
uint64_t m_MaxBlockSize = 0;
+ uint64_t m_MaxChunksPerBlock = 0;
uint64_t m_MaxChunkEmbedSize = 0;
bool m_EmbedLooseFiles = false;
bool m_Force = false;
@@ -154,8 +155,6 @@ private:
std::string m_ProjectName;
std::string m_OplogName;
std::string m_GcPath;
- size_t m_MaxBlockSize = 0;
- size_t m_MaxChunkEmbedSize = 0;
bool m_Force = false;
bool m_Async = false;
bool m_IgnoreMissingAttachments = false;
diff --git a/src/zenserver/projectstore/projectstore.cpp b/src/zenserver/projectstore/projectstore.cpp
index 78e014346..09cbe1aa3 100644
--- a/src/zenserver/projectstore/projectstore.cpp
+++ b/src/zenserver/projectstore/projectstore.cpp
@@ -174,13 +174,14 @@ namespace {
bool ForceDisableBlocks = File["disableblocks"sv].AsBool(false);
bool ForceEnableTempBlocks = File["enabletempblocks"sv].AsBool(false);
- FileRemoteStoreOptions Options = {RemoteStoreOptions{.MaxBlockSize = MaxBlockSize, .MaxChunkEmbedSize = MaxChunkEmbedSize},
- FolderPath,
- std::string(Name),
- std::string(OptionalBaseName),
- ForceDisableBlocks,
- ForceEnableTempBlocks};
- RemoteStore = CreateFileRemoteStore(Options);
+ FileRemoteStoreOptions Options = {
+ RemoteStoreOptions{.MaxBlockSize = MaxBlockSize, .MaxChunksPerBlock = 1000, .MaxChunkEmbedSize = MaxChunkEmbedSize},
+ FolderPath,
+ std::string(Name),
+ std::string(OptionalBaseName),
+ ForceDisableBlocks,
+ ForceEnableTempBlocks};
+ RemoteStore = CreateFileRemoteStore(Options);
}
if (CbObjectView Cloud = Params["cloud"sv].AsObjectView(); Cloud)
@@ -255,20 +256,21 @@ namespace {
bool ForceDisableTempBlocks = Cloud["disabletempblocks"sv].AsBool(false);
bool AssumeHttp2 = Cloud["assumehttp2"sv].AsBool(false);
- JupiterRemoteStoreOptions Options = {RemoteStoreOptions{.MaxBlockSize = MaxBlockSize, .MaxChunkEmbedSize = MaxChunkEmbedSize},
- Url,
- std::string(Namespace),
- std::string(Bucket),
- Key,
- BaseKey,
- std::string(OpenIdProvider),
- AccessToken,
- AuthManager,
- OidcExePath,
- ForceDisableBlocks,
- ForceDisableTempBlocks,
- AssumeHttp2};
- RemoteStore = CreateJupiterRemoteStore(Options, TempFilePath, /*Quiet*/ false, /*Unattended*/ false);
+ JupiterRemoteStoreOptions Options = {
+ RemoteStoreOptions{.MaxBlockSize = MaxBlockSize, .MaxChunksPerBlock = 1000, .MaxChunkEmbedSize = MaxChunkEmbedSize},
+ Url,
+ std::string(Namespace),
+ std::string(Bucket),
+ Key,
+ BaseKey,
+ std::string(OpenIdProvider),
+ AccessToken,
+ AuthManager,
+ OidcExePath,
+ ForceDisableBlocks,
+ ForceDisableTempBlocks,
+ AssumeHttp2};
+ RemoteStore = CreateJupiterRemoteStore(Options, TempFilePath, /*Quiet*/ false, /*Unattended*/ false);
}
if (CbObjectView Zen = Params["zen"sv].AsObjectView(); Zen)
@@ -284,11 +286,12 @@ namespace {
{
return {nullptr, "Missing oplog"};
}
- ZenRemoteStoreOptions Options = {RemoteStoreOptions{.MaxBlockSize = MaxBlockSize, .MaxChunkEmbedSize = MaxChunkEmbedSize},
- std::string(Url),
- std::string(Project),
- std::string(Oplog)};
- RemoteStore = CreateZenRemoteStore(Options, TempFilePath);
+ ZenRemoteStoreOptions Options = {
+ RemoteStoreOptions{.MaxBlockSize = MaxBlockSize, .MaxChunksPerBlock = 1000, .MaxChunkEmbedSize = MaxChunkEmbedSize},
+ std::string(Url),
+ std::string(Project),
+ std::string(Oplog)};
+ RemoteStore = CreateZenRemoteStore(Options, TempFilePath);
}
if (CbObjectView Builds = Params["builds"sv].AsObjectView(); Builds)
@@ -352,20 +355,21 @@ namespace {
MemoryView MetaDataSection = Builds["metadata"sv].AsBinaryView();
IoBuffer MetaData(IoBuffer::Wrap, MetaDataSection.GetData(), MetaDataSection.GetSize());
- BuildsRemoteStoreOptions Options = {RemoteStoreOptions{.MaxBlockSize = MaxBlockSize, .MaxChunkEmbedSize = MaxChunkEmbedSize},
- Url,
- std::string(Namespace),
- std::string(Bucket),
- BuildId,
- std::string(OpenIdProvider),
- AccessToken,
- AuthManager,
- OidcExePath,
- ForceDisableBlocks,
- ForceDisableTempBlocks,
- AssumeHttp2,
- MetaData};
- RemoteStore = CreateJupiterBuildsRemoteStore(Options, TempFilePath, /*Quiet*/ false, /*Unattended*/ false);
+ BuildsRemoteStoreOptions Options = {
+ RemoteStoreOptions{.MaxBlockSize = MaxBlockSize, .MaxChunksPerBlock = 1000, .MaxChunkEmbedSize = MaxChunkEmbedSize},
+ Url,
+ std::string(Namespace),
+ std::string(Bucket),
+ BuildId,
+ std::string(OpenIdProvider),
+ AccessToken,
+ AuthManager,
+ OidcExePath,
+ ForceDisableBlocks,
+ ForceDisableTempBlocks,
+ AssumeHttp2,
+ MetaData};
+ RemoteStore = CreateJupiterBuildsRemoteStore(Options, TempFilePath, /*Quiet*/ false, /*Unattended*/ false);
}
if (!RemoteStore)
@@ -5732,6 +5736,14 @@ ProjectStore::ReadOplog(const std::string_view ProjectId,
MaxChunkEmbedSize = Value.value();
}
}
+ size_t MaxChunksPerBlock = RemoteStoreOptions::DefaultMaxChunksPerBlock;
+ if (auto Param = Params.GetValue("maxchunksperblock"); Param.empty() == false)
+ {
+ if (auto Value = ParseInt<size_t>(Param))
+ {
+ MaxChunksPerBlock = Value.value();
+ }
+ }
size_t ChunkFileSizeLimit = RemoteStoreOptions::DefaultChunkFileSizeLimit;
if (auto Param = Params.GetValue("chunkfilesizelimit"); Param.empty() == false)
@@ -5750,6 +5762,7 @@ ProjectStore::ReadOplog(const std::string_view ProjectId,
*Oplog,
MaxBlockSize,
MaxChunkEmbedSize,
+ MaxChunksPerBlock,
ChunkFileSizeLimit,
/* BuildBlocks */ false,
/* IgnoreMissingAttachments */ false,
@@ -6149,6 +6162,7 @@ ProjectStore::Export(Ref<ProjectStore::Project> Project, ProjectStore::Oplog& Op
size_t MaxBlockSize = Params["maxblocksize"sv].AsUInt64(RemoteStoreOptions::DefaultMaxBlockSize);
size_t MaxChunkEmbedSize = Params["maxchunkembedsize"sv].AsUInt64(RemoteStoreOptions::DefaultMaxChunkEmbedSize);
+ size_t MaxChunksPerBlock = Params["maxchunksperblock"sv].AsUInt64(RemoteStoreOptions::DefaultMaxChunksPerBlock);
size_t ChunkFileSizeLimit = Params["chunkfilesizelimit"sv].AsUInt64(RemoteStoreOptions::DefaultChunkFileSizeLimit);
bool Force = Params["force"sv].AsBool(false);
bool IgnoreMissingAttachments = Params["ignoremissingattachments"sv].AsBool(false);
@@ -6170,6 +6184,7 @@ ProjectStore::Export(Ref<ProjectStore::Project> Project, ProjectStore::Oplog& Op
Project,
OplogPtr = &Oplog,
MaxBlockSize,
+ MaxChunksPerBlock,
MaxChunkEmbedSize,
ChunkFileSizeLimit,
EmbedLooseFile,
@@ -6187,6 +6202,7 @@ ProjectStore::Export(Ref<ProjectStore::Project> Project, ProjectStore::Oplog& Op
*Project.Get(),
*OplogPtr,
MaxBlockSize,
+ MaxChunksPerBlock,
MaxChunkEmbedSize,
ChunkFileSizeLimit,
EmbedLooseFile,
@@ -7529,13 +7545,15 @@ TEST_CASE_TEMPLATE("project.store.export",
Oid::NewOid(),
CreateAttachments(std::initializer_list<size_t>{256u * 1024u, 92u * 1024u}, OodleCompressionLevel::None)));
- FileRemoteStoreOptions Options = {
- RemoteStoreOptions{.MaxBlockSize = 64u * 1024, .MaxChunkEmbedSize = 32 * 1024u, .ChunkFileSizeLimit = 64u * 1024u},
- /*.FolderPath = */ ExportDir.Path(),
- /*.Name = */ std::string("oplog1"),
- /*OptionalBaseName = */ std::string(),
- /*.ForceDisableBlocks = */ Settings::ForceDisableBlocks,
- /*.ForceEnableTempBlocks = */ Settings::ForceEnableTempBlocks};
+ FileRemoteStoreOptions Options = {RemoteStoreOptions{.MaxBlockSize = 64u * 1024,
+ .MaxChunksPerBlock = 1000,
+ .MaxChunkEmbedSize = 32 * 1024u,
+ .ChunkFileSizeLimit = 64u * 1024u},
+ /*.FolderPath = */ ExportDir.Path(),
+ /*.Name = */ std::string("oplog1"),
+ /*OptionalBaseName = */ std::string(),
+ /*.ForceDisableBlocks = */ Settings::ForceDisableBlocks,
+ /*.ForceEnableTempBlocks = */ Settings::ForceEnableTempBlocks};
std::shared_ptr<RemoteProjectStore> RemoteStore = CreateFileRemoteStore(Options);
RemoteProjectStore::RemoteStoreInfo StoreInfo = RemoteStore->GetInfo();
@@ -7544,6 +7562,7 @@ TEST_CASE_TEMPLATE("project.store.export",
*Project.Get(),
*Oplog,
Options.MaxBlockSize,
+ Options.MaxChunksPerBlock,
Options.MaxChunkEmbedSize,
Options.ChunkFileSizeLimit,
true,
diff --git a/src/zenserver/projectstore/remoteprojectstore.cpp b/src/zenserver/projectstore/remoteprojectstore.cpp
index e61ccd917..407a284c1 100644
--- a/src/zenserver/projectstore/remoteprojectstore.cpp
+++ b/src/zenserver/projectstore/remoteprojectstore.cpp
@@ -1167,6 +1167,7 @@ BuildContainer(CidStore& ChunkStore,
ProjectStore::Project& Project,
ProjectStore::Oplog& Oplog,
size_t MaxBlockSize,
+ size_t MaxChunksPerBlock,
size_t MaxChunkEmbedSize,
size_t ChunkFileSizeLimit,
bool BuildBlocks,
@@ -2020,7 +2021,7 @@ BuildContainer(CidStore& ChunkStore,
}
BlockSize += PayloadSize;
- if (BlockSize >= MaxBlockSize && (CurrentOpKey != LastOpKey))
+ if ((BlockSize >= MaxBlockSize || ChunksInBlock.size() > MaxChunksPerBlock) && (CurrentOpKey != LastOpKey))
{
NewBlock();
}
@@ -2079,7 +2080,7 @@ BuildContainer(CidStore& ChunkStore,
BlockSize += CompressedBuffer::GetHeaderSizeForNoneEncoder() + Source.Size;
if (BuildBlocks)
{
- if (BlockSize >= MaxBlockSize)
+ if (BlockSize >= MaxBlockSize || ChunksInBlock.size() > MaxChunksPerBlock)
{
NewBlock();
}
@@ -2286,6 +2287,7 @@ BuildContainer(CidStore& ChunkStore,
ProjectStore::Project& Project,
ProjectStore::Oplog& Oplog,
size_t MaxBlockSize,
+ size_t MaxChunksPerBlock,
size_t MaxChunkEmbedSize,
size_t ChunkFileSizeLimit,
bool BuildBlocks,
@@ -2303,6 +2305,7 @@ BuildContainer(CidStore& ChunkStore,
Project,
Oplog,
MaxBlockSize,
+ MaxChunksPerBlock,
MaxChunkEmbedSize,
ChunkFileSizeLimit,
BuildBlocks,
@@ -2325,6 +2328,7 @@ SaveOplog(CidStore& ChunkStore,
ProjectStore::Project& Project,
ProjectStore::Oplog& Oplog,
size_t MaxBlockSize,
+ size_t MaxChunksPerBlock,
size_t MaxChunkEmbedSize,
size_t ChunkFileSizeLimit,
bool EmbedLooseFiles,
@@ -2474,6 +2478,7 @@ SaveOplog(CidStore& ChunkStore,
Project,
Oplog,
MaxBlockSize,
+ MaxChunksPerBlock,
MaxChunkEmbedSize,
ChunkFileSizeLimit,
RemoteStoreInfo.CreateBlocks,
diff --git a/src/zenserver/projectstore/remoteprojectstore.h b/src/zenserver/projectstore/remoteprojectstore.h
index 1210afc7c..8e65bbd58 100644
--- a/src/zenserver/projectstore/remoteprojectstore.h
+++ b/src/zenserver/projectstore/remoteprojectstore.h
@@ -110,10 +110,12 @@ public:
struct RemoteStoreOptions
{
static const size_t DefaultMaxBlockSize = 64u * 1024u * 1024u;
+ static const size_t DefaultMaxChunksPerBlock = 4u * 1000u;
static const size_t DefaultMaxChunkEmbedSize = 3u * 512u * 1024u;
static const size_t DefaultChunkFileSizeLimit = 256u * 1024u * 1024u;
size_t MaxBlockSize = DefaultMaxBlockSize;
+ size_t MaxChunksPerBlock = DefaultMaxChunksPerBlock;
size_t MaxChunkEmbedSize = DefaultMaxChunkEmbedSize;
size_t ChunkFileSizeLimit = DefaultChunkFileSizeLimit;
};
@@ -125,6 +127,7 @@ RemoteProjectStore::LoadContainerResult BuildContainer(
ProjectStore::Project& Project,
ProjectStore::Oplog& Oplog,
size_t MaxBlockSize,
+ size_t MaxChunksPerBlock,
size_t MaxChunkEmbedSize,
size_t ChunkFileSizeLimit,
bool BuildBlocks,
@@ -151,6 +154,7 @@ RemoteProjectStore::Result SaveOplog(CidStore& ChunkStore,
ProjectStore::Project& Project,
ProjectStore::Oplog& Oplog,
size_t MaxBlockSize,
+ size_t MaxChunksPerBlock,
size_t MaxChunkEmbedSize,
size_t ChunkFileSizeLimit,
bool EmbedLooseFiles,