From b729cc18ac8913fc42a6a79250553f474b67ceaa Mon Sep 17 00:00:00 2001 From: mzygdeaq Date: Sat, 27 Jun 2026 14:15:13 +0800 Subject: [PATCH 1/4] [Store] Externalize S3 client config via environment variables Add four new env vars to control S3Helper behavior at runtime: - MOONCAKE_AWS_S3_USE_HTTPS (bool, default true) Switch between HTTPS and HTTP scheme. - MOONCAKE_AWS_LOG_LEVEL (off/fatal/error/warn/info/debug/trace, default error) Control AWS SDK log verbosity. - MOONCAKE_AWS_S3_REQUEST_CHECKSUM (when_supported/when_required, default when_supported) When set to when_required, avoids the new checksum trailer behavior that breaks compatibility with MinIO and some other S3-compatible backends. - MOONCAKE_AWS_S3_RESPONSE_CHECKSUM (when_supported/when_required, default when_supported) Same purpose as above for response validation. All defaults preserve backward compatibility with existing behavior. connection_info_ log line updated to include the new values for easier debugging. Co-Authored-By: Claude --- mooncake-store/src/utils/s3_helper.cpp | 89 +++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/mooncake-store/src/utils/s3_helper.cpp b/mooncake-store/src/utils/s3_helper.cpp index f951d4bbee..3cb5c2c614 100644 --- a/mooncake-store/src/utils/s3_helper.cpp +++ b/mooncake-store/src/utils/s3_helper.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include "utils/type_util.h" #include "fmt/format.h" @@ -50,6 +52,14 @@ struct S3Env { bool use_virtual_addressing = true; + bool use_https = true; + + Aws::Client::RequestChecksumCalculation request_checksum = + Aws::Client::RequestChecksumCalculation::WHEN_SUPPORTED; + + Aws::Client::ResponseChecksumValidation response_checksum = + Aws::Client::ResponseChecksumValidation::WHEN_SUPPORTED; + int64_t connect_timeout_ms = kDefaultS3ConnectTimeoutMs; int64_t request_timeout_ms = kDefaultS3RequestTimeoutMs; @@ -92,6 +102,46 @@ void AssignTimeoutFromEnv(const char *env_name, int64_t default_value, target = default_value; } +Aws::Utils::Logging::LogLevel ParseLogLevel(const std::string &value) { + if (value == "off") return Aws::Utils::Logging::LogLevel::Off; + if (value == "fatal") return Aws::Utils::Logging::LogLevel::Fatal; + if (value == "warn") return Aws::Utils::Logging::LogLevel::Warn; + if (value == "info") return Aws::Utils::Logging::LogLevel::Info; + if (value == "debug") return Aws::Utils::Logging::LogLevel::Debug; + if (value == "trace") return Aws::Utils::Logging::LogLevel::Trace; + if (!value.empty()) { + LOG(WARNING) << "Invalid MOONCAKE_AWS_LOG_LEVEL value: " << value + << ", falling back to Error"; + } + return Aws::Utils::Logging::LogLevel::Error; +} + +Aws::Client::RequestChecksumCalculation ParseRequestChecksum( + const std::string &value) { + if (value == "when_required") { + return Aws::Client::RequestChecksumCalculation::WHEN_REQUIRED; + } + if (!value.empty()) { + LOG(WARNING) + << "Invalid MOONCAKE_AWS_S3_REQUEST_CHECKSUM value: " << value + << ", falling back to when_supported"; + } + return Aws::Client::RequestChecksumCalculation::WHEN_SUPPORTED; +} + +Aws::Client::ResponseChecksumValidation ParseResponseChecksum( + const std::string &value) { + if (value == "when_required") { + return Aws::Client::ResponseChecksumValidation::WHEN_REQUIRED; + } + if (!value.empty()) { + LOG(WARNING) + << "Invalid MOONCAKE_AWS_S3_RESPONSE_CHECKSUM value: " << value + << ", falling back to when_supported"; + } + return Aws::Client::ResponseChecksumValidation::WHEN_SUPPORTED; +} + } // namespace bool S3Helper::aws_initialized = false; @@ -113,6 +163,24 @@ void S3Helper::InitAPI() { AssignBoolFromEnv("MOONCAKE_AWS_USE_VIRTUAL_ADDRESSING", s3_env.use_virtual_addressing); + AssignBoolFromEnv("MOONCAKE_AWS_S3_USE_HTTPS", s3_env.use_https); + + { + std::string tmp; + AssignStringFromEnv("MOONCAKE_AWS_LOG_LEVEL", tmp); + options_.loggingOptions.logLevel = ParseLogLevel(tmp); + } + { + std::string tmp; + AssignStringFromEnv("MOONCAKE_AWS_S3_REQUEST_CHECKSUM", tmp); + s3_env.request_checksum = ParseRequestChecksum(tmp); + } + { + std::string tmp; + AssignStringFromEnv("MOONCAKE_AWS_S3_RESPONSE_CHECKSUM", tmp); + s3_env.response_checksum = ParseResponseChecksum(tmp); + } + AssignTimeoutFromEnv("MOONCAKE_AWS_CONNECT_TIMEOUT_MS", kDefaultS3ConnectTimeoutMs, s3_env.connect_timeout_ms); AssignTimeoutFromEnv("MOONCAKE_AWS_REQUEST_TIMEOUT_MS", @@ -132,7 +200,10 @@ S3Helper::S3Helper(const std::string &endpoint, const std::string &bucket, config.connectTimeoutMs = s3_env.connect_timeout_ms; config.requestTimeoutMs = s3_env.request_timeout_ms; - config.scheme = Aws::Http::Scheme::HTTPS; + config.scheme = s3_env.use_https ? Aws::Http::Scheme::HTTPS + : Aws::Http::Scheme::HTTP; + config.checksumConfig.requestChecksumCalculation = s3_env.request_checksum; + config.checksumConfig.responseChecksumValidation = s3_env.response_checksum; if (!region.empty()) { config.region = region; @@ -163,7 +234,10 @@ S3Helper::S3Helper(const std::string &endpoint, const std::string &bucket, "requestTimeoutMs={} " "scheme={} " "credentials={}/{} " - "useVirtualAddressing={}", + "useVirtualAddressing={} " + "logLevel={} " + "requestChecksum={} " + "responseChecksum={}", config.region.empty() ? "unset" : config.region, config.endpointOverride.empty() ? "unset" : config.endpointOverride, bucket_.empty() ? "unset" : bucket_, config.connectTimeoutMs, @@ -171,7 +245,16 @@ S3Helper::S3Helper(const std::string &endpoint, const std::string &bucket, config.scheme == Aws::Http::Scheme::HTTPS ? "HTTPS" : "HTTP", !s3_env.access_key.empty() ? "set" : "unset", !s3_env.secret_key.empty() ? "set" : "unset", - s3_env.use_virtual_addressing ? "true" : "false"); + s3_env.use_virtual_addressing ? "true" : "false", + Aws::Utils::Logging::GetLogLevelName(options_.loggingOptions.logLevel), + s3_env.request_checksum == + Aws::Client::RequestChecksumCalculation::WHEN_SUPPORTED + ? "when_supported" + : "when_required", + s3_env.response_checksum == + Aws::Client::ResponseChecksumValidation::WHEN_SUPPORTED + ? "when_supported" + : "when_required"); s3_client_ = Aws::S3::S3Client( credentials, config, From ca43c7eb1e585fca2645656494969c9ed75bc706 Mon Sep 17 00:00:00 2001 From: mzygdeaq Date: Sat, 27 Jun 2026 14:44:39 +0800 Subject: [PATCH 2/4] [Store] Drop MOONCAKE_AWS_LOG_LEVEL and trim connection_info_ - Remove MOONCAKE_AWS_LOG_LEVEL env var, ParseLogLevel function, and the corresponding include. The underlying use case (changing AWS SDK log verbosity at runtime) is rarely needed in practice and adds an extra knob to maintain. - Remove logLevel / requestChecksum / responseChecksum fields from the connection_info_ log line to reduce startup log noise. Co-Authored-By: Claude --- mooncake-store/src/utils/s3_helper.cpp | 36 ++------------------------ 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/mooncake-store/src/utils/s3_helper.cpp b/mooncake-store/src/utils/s3_helper.cpp index 3cb5c2c614..f71825c64b 100644 --- a/mooncake-store/src/utils/s3_helper.cpp +++ b/mooncake-store/src/utils/s3_helper.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include "utils/type_util.h" #include "fmt/format.h" @@ -102,20 +101,6 @@ void AssignTimeoutFromEnv(const char *env_name, int64_t default_value, target = default_value; } -Aws::Utils::Logging::LogLevel ParseLogLevel(const std::string &value) { - if (value == "off") return Aws::Utils::Logging::LogLevel::Off; - if (value == "fatal") return Aws::Utils::Logging::LogLevel::Fatal; - if (value == "warn") return Aws::Utils::Logging::LogLevel::Warn; - if (value == "info") return Aws::Utils::Logging::LogLevel::Info; - if (value == "debug") return Aws::Utils::Logging::LogLevel::Debug; - if (value == "trace") return Aws::Utils::Logging::LogLevel::Trace; - if (!value.empty()) { - LOG(WARNING) << "Invalid MOONCAKE_AWS_LOG_LEVEL value: " << value - << ", falling back to Error"; - } - return Aws::Utils::Logging::LogLevel::Error; -} - Aws::Client::RequestChecksumCalculation ParseRequestChecksum( const std::string &value) { if (value == "when_required") { @@ -165,11 +150,6 @@ void S3Helper::InitAPI() { AssignBoolFromEnv("MOONCAKE_AWS_S3_USE_HTTPS", s3_env.use_https); - { - std::string tmp; - AssignStringFromEnv("MOONCAKE_AWS_LOG_LEVEL", tmp); - options_.loggingOptions.logLevel = ParseLogLevel(tmp); - } { std::string tmp; AssignStringFromEnv("MOONCAKE_AWS_S3_REQUEST_CHECKSUM", tmp); @@ -234,10 +214,7 @@ S3Helper::S3Helper(const std::string &endpoint, const std::string &bucket, "requestTimeoutMs={} " "scheme={} " "credentials={}/{} " - "useVirtualAddressing={} " - "logLevel={} " - "requestChecksum={} " - "responseChecksum={}", + "useVirtualAddressing={}", config.region.empty() ? "unset" : config.region, config.endpointOverride.empty() ? "unset" : config.endpointOverride, bucket_.empty() ? "unset" : bucket_, config.connectTimeoutMs, @@ -245,16 +222,7 @@ S3Helper::S3Helper(const std::string &endpoint, const std::string &bucket, config.scheme == Aws::Http::Scheme::HTTPS ? "HTTPS" : "HTTP", !s3_env.access_key.empty() ? "set" : "unset", !s3_env.secret_key.empty() ? "set" : "unset", - s3_env.use_virtual_addressing ? "true" : "false", - Aws::Utils::Logging::GetLogLevelName(options_.loggingOptions.logLevel), - s3_env.request_checksum == - Aws::Client::RequestChecksumCalculation::WHEN_SUPPORTED - ? "when_supported" - : "when_required", - s3_env.response_checksum == - Aws::Client::ResponseChecksumValidation::WHEN_SUPPORTED - ? "when_supported" - : "when_required"); + s3_env.use_virtual_addressing ? "true" : "false"); s3_client_ = Aws::S3::S3Client( credentials, config, From a173d78c0d17356291d4d6b740a0974cf1d12218 Mon Sep 17 00:00:00 2001 From: mzygdeaq Date: Sat, 27 Jun 2026 15:01:52 +0800 Subject: [PATCH 3/4] [Store] Apply clang-format to s3_helper.cpp Wrap LOG(WARNING) stream chains and the config.scheme ternary to match the project's column-width style. Add trailing newline. Co-Authored-By: Claude --- mooncake-store/src/utils/s3_helper.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/mooncake-store/src/utils/s3_helper.cpp b/mooncake-store/src/utils/s3_helper.cpp index f71825c64b..786ac6a4f6 100644 --- a/mooncake-store/src/utils/s3_helper.cpp +++ b/mooncake-store/src/utils/s3_helper.cpp @@ -107,9 +107,8 @@ Aws::Client::RequestChecksumCalculation ParseRequestChecksum( return Aws::Client::RequestChecksumCalculation::WHEN_REQUIRED; } if (!value.empty()) { - LOG(WARNING) - << "Invalid MOONCAKE_AWS_S3_REQUEST_CHECKSUM value: " << value - << ", falling back to when_supported"; + LOG(WARNING) << "Invalid MOONCAKE_AWS_S3_REQUEST_CHECKSUM value: " + << value << ", falling back to when_supported"; } return Aws::Client::RequestChecksumCalculation::WHEN_SUPPORTED; } @@ -120,9 +119,8 @@ Aws::Client::ResponseChecksumValidation ParseResponseChecksum( return Aws::Client::ResponseChecksumValidation::WHEN_REQUIRED; } if (!value.empty()) { - LOG(WARNING) - << "Invalid MOONCAKE_AWS_S3_RESPONSE_CHECKSUM value: " << value - << ", falling back to when_supported"; + LOG(WARNING) << "Invalid MOONCAKE_AWS_S3_RESPONSE_CHECKSUM value: " + << value << ", falling back to when_supported"; } return Aws::Client::ResponseChecksumValidation::WHEN_SUPPORTED; } @@ -180,8 +178,8 @@ S3Helper::S3Helper(const std::string &endpoint, const std::string &bucket, config.connectTimeoutMs = s3_env.connect_timeout_ms; config.requestTimeoutMs = s3_env.request_timeout_ms; - config.scheme = s3_env.use_https ? Aws::Http::Scheme::HTTPS - : Aws::Http::Scheme::HTTP; + config.scheme = + s3_env.use_https ? Aws::Http::Scheme::HTTPS : Aws::Http::Scheme::HTTP; config.checksumConfig.requestChecksumCalculation = s3_env.request_checksum; config.checksumConfig.responseChecksumValidation = s3_env.response_checksum; @@ -923,4 +921,4 @@ tl::expected S3Helper::DeleteObjectsWithPrefix( return DeleteObjects(object_keys); } -} // namespace mooncake \ No newline at end of file +} // namespace mooncake From 491951f6f6467133364f0f16523d251fad39b93b Mon Sep 17 00:00:00 2001 From: mzygdeaq Date: Sat, 27 Jun 2026 15:14:06 +0800 Subject: [PATCH 4/4] [Store] Fix false 'invalid value' warning for when_supported checksum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ParseRequestChecksum / ParseResponseChecksum logged a warning whenever value != "when_required" and value was non-empty. This incorrectly flagged the valid value "when_supported" as invalid. - Add an explicit "when_supported" branch before the warning. - Lowercase the input via std::transform + std::tolower for case-insensitive comparison (matching the convention already used in real_client.cpp / ssd_register_client.cpp). - Collapse the two near-identical functions into a single ParseChecksumMode() template — both AWS SDK enum classes share the WHEN_REQUIRED / WHEN_SUPPORTED enumerator names. Co-Authored-By: Claude --- mooncake-store/src/utils/s3_helper.cpp | 41 +++++++++++--------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/mooncake-store/src/utils/s3_helper.cpp b/mooncake-store/src/utils/s3_helper.cpp index 786ac6a4f6..d26f37b594 100644 --- a/mooncake-store/src/utils/s3_helper.cpp +++ b/mooncake-store/src/utils/s3_helper.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -101,28 +102,18 @@ void AssignTimeoutFromEnv(const char *env_name, int64_t default_value, target = default_value; } -Aws::Client::RequestChecksumCalculation ParseRequestChecksum( - const std::string &value) { - if (value == "when_required") { - return Aws::Client::RequestChecksumCalculation::WHEN_REQUIRED; - } - if (!value.empty()) { - LOG(WARNING) << "Invalid MOONCAKE_AWS_S3_REQUEST_CHECKSUM value: " - << value << ", falling back to when_supported"; - } - return Aws::Client::RequestChecksumCalculation::WHEN_SUPPORTED; -} - -Aws::Client::ResponseChecksumValidation ParseResponseChecksum( - const std::string &value) { - if (value == "when_required") { - return Aws::Client::ResponseChecksumValidation::WHEN_REQUIRED; - } - if (!value.empty()) { - LOG(WARNING) << "Invalid MOONCAKE_AWS_S3_RESPONSE_CHECKSUM value: " - << value << ", falling back to when_supported"; - } - return Aws::Client::ResponseChecksumValidation::WHEN_SUPPORTED; +template +T ParseChecksumMode(const std::string &value) { + std::string lower = value; + std::transform(lower.begin(), lower.end(), lower.begin(), + [](unsigned char ch) { return std::tolower(ch); }); + if (lower == "when_required") return T::WHEN_REQUIRED; + if (lower == "when_supported") return T::WHEN_SUPPORTED; + if (!lower.empty()) { + LOG(WARNING) << "Invalid value: " << value + << ", falling back to when_supported"; + } + return T::WHEN_SUPPORTED; } } // namespace @@ -151,12 +142,14 @@ void S3Helper::InitAPI() { { std::string tmp; AssignStringFromEnv("MOONCAKE_AWS_S3_REQUEST_CHECKSUM", tmp); - s3_env.request_checksum = ParseRequestChecksum(tmp); + s3_env.request_checksum = + ParseChecksumMode(tmp); } { std::string tmp; AssignStringFromEnv("MOONCAKE_AWS_S3_RESPONSE_CHECKSUM", tmp); - s3_env.response_checksum = ParseResponseChecksum(tmp); + s3_env.response_checksum = + ParseChecksumMode(tmp); } AssignTimeoutFromEnv("MOONCAKE_AWS_CONNECT_TIMEOUT_MS",