aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md12
-rw-r--r--VERSION.txt2
-rw-r--r--src/zenhttp/clients/asynchttpclient.cpp36
-rw-r--r--src/zenhttp/include/zenhttp/asynchttpclient.h6
-rw-r--r--src/zenserver/storage/objectstore/objectstore.cpp35
-rw-r--r--src/zenserver/storage/storageconfig.cpp2
6 files changed, 54 insertions, 39 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4a88753bc..39972aa8c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
##
- Feature: Hub bulk deprovision endpoint (`POST /hub/deprovision`) tears down all provisioned and hibernated modules in a single request
+- Feature: Hub instance forwarding options for memory allocator and tracing
+ - `--hub-instance-malloc` selects the memory allocator for child instances
+ - `--hub-instance-trace` sets trace channels for child instances
+ - `--hub-instance-tracehost` sets the trace streaming host for child instances
+ - `--hub-instance-tracefile` sets the trace output file for child instances; supports `{moduleid}` and `{port}` placeholders
- Improvement: Replaced archived `http_parser` library with `llhttp` for HTTP request parsing
- Improvement: HTTP range responses (RFC 7233) are now fully compliant across the object store and build store
- 206 Partial Content responses now include a `Content-Range` header; previously absent for single-range requests, which broke `HttpClient::GetRanges()`
@@ -17,13 +22,8 @@
- Improvement: `--consul-register-hub` option to disable hub parent service Consul registration while keeping instance registration active
- Bugfix: Added logic to shared memory instance state management to ensure unclean shutdown followed by restart with identical pid doesn't lead to errors. Particularly likely to happen when running on k8s
- Improvement: Dashboard service stats panes are now always visible on service pages (projects, cache, builds, workspaces) rather than hidden until data arrives
-- Feature: Hub instance forwarding options for memory allocator and tracing
- - `--hub-instance-malloc` selects the memory allocator for child instances
- - `--hub-instance-trace` sets trace channels for child instances
- - `--hub-instance-tracehost` sets the trace streaming host for child instances
- - `--hub-instance-tracefile` sets the trace output file for child instances; supports `{moduleid}` and `{port}` placeholders
-- Bugfix: Dashboard stats tiles no longer flicker on page load when WebSocket updates arrive before all stats are available
- Improvement: Updated vendored MinIO test server from RELEASE.2025-07-23 to RELEASE.2025-09-07 (HTTP listener bugfixes, ListObject fix)
+- Bugfix: Dashboard stats tiles no longer flicker on page load when WebSocket updates arrive before all stats are available
## 5.8.3
- Feature: Incremental CAS-based hydration/dehydration replacing the previous full-copy approach
diff --git a/VERSION.txt b/VERSION.txt
index f05e61d96..b61055bc9 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-5.8.3 \ No newline at end of file
+5.8.4-pre0 \ No newline at end of file
diff --git a/src/zenhttp/clients/asynchttpclient.cpp b/src/zenhttp/clients/asynchttpclient.cpp
index bdf7f160c..4b189af36 100644
--- a/src/zenhttp/clients/asynchttpclient.cpp
+++ b/src/zenhttp/clients/asynchttpclient.cpp
@@ -100,7 +100,7 @@ struct AsyncHttpClient::Impl
{
// Clean up curl state on the strand where all curl_multi operations
// are serialized. Use a promise to block until the cleanup handler
- // has actually executed — essential for the external io_context case
+ // has actually executed - essential for the external io_context case
// where we don't own the run loop.
std::promise<void> Done;
std::future<void> DoneFuture = Done.get_future();
@@ -109,7 +109,7 @@ struct AsyncHttpClient::Impl
m_ShuttingDown = true;
m_Timer.cancel();
- // Release all tracked sockets (don't close — curl owns the fds).
+ // Release all tracked sockets (don't close - curl owns the fds).
for (auto& [Fd, Info] : m_Sockets)
{
if (Info->Socket.is_open())
@@ -178,7 +178,7 @@ struct AsyncHttpClient::Impl
}
}
- // ── Handle pool ─────────────────────────────────────────────────────
+ // -- Handle pool -----------------------------------------------------
CURL* AllocHandle()
{
@@ -199,7 +199,7 @@ struct AsyncHttpClient::Impl
void ReleaseHandle(CURL* Handle) { m_HandlePool.push_back(Handle); }
- // ── Configure a handle with common settings ─────────────────────────
+ // -- Configure a handle with common settings -------------------------
// Called only from DoAsync* lambdas running on the strand.
void ConfigureHandle(CURL* Handle, std::string_view ResourcePath, const HttpClient::KeyValueMap& Parameters)
@@ -258,7 +258,7 @@ struct AsyncHttpClient::Impl
}
}
- // ── Access token ────────────────────────────────────────────────────
+ // -- Access token ----------------------------------------------------
std::optional<std::string> GetAccessToken()
{
@@ -293,7 +293,7 @@ struct AsyncHttpClient::Impl
return {};
}
- // ── Submit a transfer ───────────────────────────────────────────────
+ // -- Submit a transfer -----------------------------------------------
void SubmitTransfer(CURL* Handle, std::unique_ptr<TransferContext> Ctx)
{
@@ -323,7 +323,7 @@ struct AsyncHttpClient::Impl
}
}
- // ── Socket-action integration ───────────────────────────────────────
+ // -- Socket-action integration ---------------------------------------
//
// curl_multi drives I/O via two callbacks:
// - SocketCallback: curl tells us which sockets to watch for read/write
@@ -341,7 +341,7 @@ struct AsyncHttpClient::Impl
explicit SocketInfo(asio::io_context& IoContext) : Socket(IoContext) {}
};
- // Static thunks registered with curl_multi ────────────────────────────
+ // Static thunks registered with curl_multi ----------------------------
static int CurlSocketCallback(CURL* Easy, curl_socket_t Fd, int Action, void* UserPtr, void* SocketPtr)
{
@@ -367,7 +367,7 @@ struct AsyncHttpClient::Impl
curl_multi_setopt(m_Multi, CURLMOPT_TIMERDATA, this);
}
- // Called by curl when socket watch state changes ──────────────────────
+ // Called by curl when socket watch state changes ---------------------
void OnCurlSocket(curl_socket_t Fd, int Action, SocketInfo* Info)
{
@@ -389,7 +389,7 @@ struct AsyncHttpClient::Impl
if (!Info)
{
- // New socket — wrap the native fd in an ASIO socket.
+ // New socket - wrap the native fd in an ASIO socket.
auto [It, Inserted] = m_Sockets.emplace(Fd, std::make_unique<SocketInfo>(m_IoContext));
Info = It->second.get();
@@ -458,7 +458,7 @@ struct AsyncHttpClient::Impl
}
}
- // Called by curl when it wants a timeout ──────────────────────────────
+ // Called by curl when it wants a timeout ------------------------------
void OnCurlTimer(long TimeoutMs)
{
@@ -472,7 +472,7 @@ struct AsyncHttpClient::Impl
if (TimeoutMs == 0)
{
- // curl wants immediate action — run it directly on the strand.
+ // curl wants immediate action - run it directly on the strand.
asio::post(m_Strand, [this]() {
if (m_ShuttingDown)
{
@@ -498,7 +498,7 @@ struct AsyncHttpClient::Impl
}));
}
- // Drain completed transfers from curl_multi ──────────────────────────
+ // Drain completed transfers from curl_multi --------------------------
void CheckCompleted()
{
@@ -605,7 +605,7 @@ struct AsyncHttpClient::Impl
});
}
- // ── Async verb implementations ──────────────────────────────────────
+ // -- Async verb implementations --------------------------------------
void DoAsyncGet(std::string Url,
AsyncHttpCallback Callback,
@@ -816,7 +816,7 @@ struct AsyncHttpClient::Impl
});
}
- // ── Members ─────────────────────────────────────────────────────────
+ // -- Members ---------------------------------------------------------
std::string m_BaseUri;
HttpClientSettings m_Settings;
@@ -824,7 +824,7 @@ struct AsyncHttpClient::Impl
std::string m_SessionId;
std::string m_UnixSocketPathUtf8;
- // io_context and strand — all curl_multi operations are serialized on the
+ // io_context and strand - all curl_multi operations are serialized on the
// strand, making this safe even when the io_context has multiple threads.
std::unique_ptr<asio::io_context> m_OwnedIoContext;
asio::io_context& m_IoContext;
@@ -861,7 +861,7 @@ AsyncHttpClient::AsyncHttpClient(std::string_view BaseUri, asio::io_context& IoC
AsyncHttpClient::~AsyncHttpClient() = default;
-// ── Callback-based API ──────────────────────────────────────────────────
+// -- Callback-based API --------------------------------------------------
void
AsyncHttpClient::AsyncGet(std::string_view Url,
@@ -925,7 +925,7 @@ AsyncHttpClient::AsyncPut(std::string_view Url, AsyncHttpCallback Callback, cons
m_Impl->DoAsyncPutNoPayload(std::string(Url), std::move(Callback), Parameters);
}
-// ── Future-based API ────────────────────────────────────────────────────
+// -- Future-based API ----------------------------------------------------
std::future<HttpClient::Response>
AsyncHttpClient::Get(std::string_view Url, const KeyValueMap& AdditionalHeader, const KeyValueMap& Parameters)
diff --git a/src/zenhttp/include/zenhttp/asynchttpclient.h b/src/zenhttp/include/zenhttp/asynchttpclient.h
index 58429349d..cb41626b9 100644
--- a/src/zenhttp/include/zenhttp/asynchttpclient.h
+++ b/src/zenhttp/include/zenhttp/asynchttpclient.h
@@ -21,7 +21,7 @@ using AsyncHttpCallback = std::function<void(HttpClient::Response)>;
/** Asynchronous HTTP client backed by curl_multi and ASIO.
*
- * Uses curl_multi_perform() driven by an ASIO steady_timer to process
+ * Uses curl_multi_socket_action() driven by ASIO socket async_wait to process
* transfers without blocking the caller. All curl_multi operations are
* serialized on an internal strand; callers may issue requests from any
* thread, and the io_context may have multiple threads.
@@ -53,7 +53,7 @@ public:
AsyncHttpClient(const AsyncHttpClient&) = delete;
AsyncHttpClient& operator=(const AsyncHttpClient&) = delete;
- // ── Callback-based API ──────────────────────────────────────────────
+ // -- Callback-based API ----------------------------------------------
void AsyncGet(std::string_view Url,
AsyncHttpCallback Callback,
@@ -85,7 +85,7 @@ public:
void AsyncPut(std::string_view Url, AsyncHttpCallback Callback, const KeyValueMap& Parameters = {});
- // ── Future-based API ────────────────────────────────────────────────
+ // -- Future-based API ------------------------------------------------
[[nodiscard]] std::future<Response> Get(std::string_view Url,
const KeyValueMap& AdditionalHeader = {},
diff --git a/src/zenserver/storage/objectstore/objectstore.cpp b/src/zenserver/storage/objectstore/objectstore.cpp
index bab9df06d..1115c1cd6 100644
--- a/src/zenserver/storage/objectstore/objectstore.cpp
+++ b/src/zenserver/storage/objectstore/objectstore.cpp
@@ -669,24 +669,39 @@ HttpObjectStoreService::GetObject(HttpRouterRequest& Request, const std::string_
NiceBytes(FileBuf.GetSize()),
NiceBytes(TotalServed));
}
- else if (Ranges.size() == 1)
+ else
{
- const uint64_t TotalSize = FileBuf.GetSize();
- const uint64_t RangeEnd = (Ranges[0].End != ~uint64_t(0)) ? Ranges[0].End : TotalSize - 1;
- if (RangeEnd < TotalSize && Ranges[0].Start <= RangeEnd)
+ const uint64_t TotalSize = FileBuf.GetSize();
+ uint64_t ServedBytes = 0;
+ for (const HttpRange& Range : Ranges)
{
- const uint64_t RangeSize = 1 + (RangeEnd - Ranges[0].Start);
- const uint64_t TotalServed = m_TotalBytesServed.fetch_add(RangeSize) + RangeSize;
+ const uint64_t RangeEnd = (Range.End != ~uint64_t(0)) ? Range.End : TotalSize - 1;
+ if (RangeEnd < TotalSize && Range.Start <= RangeEnd)
+ {
+ ServedBytes += 1 + (RangeEnd - Range.Start);
+ }
+ }
+ if (ServedBytes > 0)
+ {
+ const uint64_t TotalServed = m_TotalBytesServed.fetch_add(ServedBytes) + ServedBytes;
ZEN_LOG_DEBUG(LogObj,
- "GET - '{}/{}' (Range: {}-{}) ({}/{}) [OK] (Served: {})",
+ "GET - '{}/{}' (Ranges: {}) ({}/{}) [OK] (Served: {})",
BucketName,
RelativeBucketPath,
- Ranges[0].Start,
- RangeEnd,
- NiceBytes(RangeSize),
+ Ranges.size(),
+ NiceBytes(ServedBytes),
NiceBytes(TotalSize),
NiceBytes(TotalServed));
}
+ else
+ {
+ ZEN_LOG_DEBUG(LogObj,
+ "GET - '{}/{}' (Ranges: {}) [416] ({})",
+ BucketName,
+ RelativeBucketPath,
+ Ranges.size(),
+ NiceBytes(TotalSize));
+ }
}
Request.ServerRequest().WriteResponse(HttpContentType::kBinary, FileBuf, Ranges);
}
diff --git a/src/zenserver/storage/storageconfig.cpp b/src/zenserver/storage/storageconfig.cpp
index 0dbb45164..b615af280 100644
--- a/src/zenserver/storage/storageconfig.cpp
+++ b/src/zenserver/storage/storageconfig.cpp
@@ -477,7 +477,7 @@ ZenStorageServerConfigurator::AddConfigOptions(LuaConfig::Options& LuaOptions)
ServerOptions.GcConfig.CompactBlockUsageThresholdPercent,
"gc-compactblock-threshold"sv);
LuaOptions.AddOption("gc.verbose"sv, ServerOptions.GcConfig.Verbose, "gc-verbose"sv);
- LuaOptions.AddOption("gc.single-threaded"sv, ServerOptions.GcConfig.SingleThreaded, "gc-single-threaded"sv);
+ LuaOptions.AddOption("gc.singlethreaded"sv, ServerOptions.GcConfig.SingleThreaded, "gc-single-threaded"sv);
LuaOptions.AddOption("gc.cache.attachment.store"sv, ServerOptions.GcConfig.StoreCacheAttachmentMetaData, "gc-cache-attachment-store");
LuaOptions.AddOption("gc.projectstore.attachment.store"sv,
ServerOptions.GcConfig.StoreProjectAttachmentMetaData,