From b2444b8ad5c839a10c1594912d11033d93c00cd8 Mon Sep 17 00:00:00 2001 From: liunyl Date: Fri, 12 Jun 2026 09:18:53 +0000 Subject: [PATCH 1/4] chore: update submodule data_substrate for cc request bthread mutex deadlock fix Pulls in eloqdata/tx_service#491, which fixes the same deadlock class as the CkptTsCc hang (#483) in the remaining CC requests (ActiveTxMaxTsCc, WaitableCc, ClearCcNodeGroup, EscalateStandbyCcmCc, ClearTxCc, DbSizeCc, UploadBatchCc): a bthread::Mutex shared between tx processors (the brpc worker main stack) and bthread waiters can park the worker forever when the butex wake is routed to a bthread bound to that worker. For eloqkv this also covers the Redis dbsize command path. Also picks up the upstream standby replication protocol documentation commit (f62f0fa). Co-Authored-By: Claude Fable 5 --- data_substrate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_substrate b/data_substrate index 887e352a..302ef9a6 160000 --- a/data_substrate +++ b/data_substrate @@ -1 +1 @@ -Subproject commit 887e352ac7a00b782e1ed444e75277613c56c75b +Subproject commit 302ef9a6df44dbd945a0038e3f7f4251e30f8fd3 From a6f9fd4079b0d3ee507d652667fa0c280ccaac0c Mon Sep 17 00:00:00 2001 From: liunyl Date: Sun, 14 Jun 2026 01:53:15 +0000 Subject: [PATCH 2/4] fix: build eloqkv_to_rdb in the non-cloud (ROCKSDB) config eloqkv_to_rdb is built for WITH_DATA_STORE=ROCKSDB as well as the RocksDB-Cloud backends, but ParseSizeBytes and ShardProgressPrinter were defined only inside `#if ROCKSDB_CLOUD_EXPORT` while main() referenced ParseSizeBytes and ShardProgressPrinter::kMaxScanThreads unconditionally. In a non-cloud build (the cloud data-store macros are undefined, so ROCKSDB_CLOUD_EXPORT is undefined) those symbols do not exist and the tool fails to compile -- a latent regression since #485. ParseSizeBytes parses --write_block_size into write_block_size_bytes, which the non-cloud writer (ParseWorker / Rocksdb2RDB) also reads, so it must be available in both builds: move it (and its / includes) out of the cloud-only block and keep its validation in main() unconditional. ShardProgressPrinter is genuinely cloud-only, so guard only its kMaxScanThreads check with ROCKSDB_CLOUD_EXPORT. Verified with -fsyntax-only in both the non-cloud and cloud configs. Co-Authored-By: Claude Opus 4.8 --- src/tools/eloqkv2rdb/eloqkv2rdb.cpp | 121 +++++++++++++++------------- 1 file changed, 63 insertions(+), 58 deletions(-) diff --git a/src/tools/eloqkv2rdb/eloqkv2rdb.cpp b/src/tools/eloqkv2rdb/eloqkv2rdb.cpp index 45aac4d4..543ad72a 100644 --- a/src/tools/eloqkv2rdb/eloqkv2rdb.cpp +++ b/src/tools/eloqkv2rdb/eloqkv2rdb.cpp @@ -19,8 +19,10 @@ * . * */ +#include #include #include +#include #include #include #include @@ -64,7 +66,6 @@ #include #include -#include #include #endif extern "C" @@ -818,6 +819,66 @@ struct ParseWorker std::thread thd_; }; +// Parses a human-readable size string ("512KB", "1MB", "2GB", "1TB") into a +// byte count. Shared by both the cloud and non-cloud RDB writers as the +// write-buffer flush threshold, so it must be available regardless of +// ROCKSDB_CLOUD_EXPORT. +inline bool ParseSizeBytes(const std::string &size_str, uint64_t &bytes) +{ + if (size_str.size() <= 2) + { + return false; + } + + std::string number_part = size_str.substr(0, size_str.size() - 2); + std::string unit_part = size_str.substr(size_str.size() - 2); + std::transform(unit_part.begin(), + unit_part.end(), + unit_part.begin(), + [](unsigned char c) { return std::toupper(c); }); + + uint64_t multiplier = 0; + if (unit_part == "KB") + { + multiplier = 1024ULL; + } + else if (unit_part == "MB") + { + multiplier = 1024ULL * 1024ULL; + } + else if (unit_part == "GB") + { + multiplier = 1024ULL * 1024ULL * 1024ULL; + } + else if (unit_part == "TB") + { + multiplier = 1024ULL * 1024ULL * 1024ULL * 1024ULL; + } + else + { + return false; + } + + if (number_part.empty() || + !std::all_of(number_part.begin(), + number_part.end(), + [](unsigned char c) { return std::isdigit(c); })) + { + return false; + } + + try + { + bytes = std::stoull(number_part) * multiplier; + } + catch (...) + { + return false; + } + + return bytes > 0; +} + #if ROCKSDB_CLOUD_EXPORT struct S3UrlComponents @@ -1248,62 +1309,6 @@ class ShardProgressPrinter size_t last_line_size_{0}; }; -inline bool ParseSizeBytes(const std::string &size_str, uint64_t &bytes) -{ - if (size_str.size() <= 2) - { - return false; - } - - std::string number_part = size_str.substr(0, size_str.size() - 2); - std::string unit_part = size_str.substr(size_str.size() - 2); - std::transform(unit_part.begin(), - unit_part.end(), - unit_part.begin(), - [](unsigned char c) { return std::toupper(c); }); - - uint64_t multiplier = 0; - if (unit_part == "KB") - { - multiplier = 1024ULL; - } - else if (unit_part == "MB") - { - multiplier = 1024ULL * 1024ULL; - } - else if (unit_part == "GB") - { - multiplier = 1024ULL * 1024ULL * 1024ULL; - } - else if (unit_part == "TB") - { - multiplier = 1024ULL * 1024ULL * 1024ULL * 1024ULL; - } - else - { - return false; - } - - if (number_part.empty() || - !std::all_of(number_part.begin(), - number_part.end(), - [](unsigned char c) { return std::isdigit(c); })) - { - return false; - } - - try - { - bytes = std::stoull(number_part) * multiplier; - } - catch (...) - { - return false; - } - - return bytes > 0; -} - // DSS value format constants and helpers. // Value layout: [version_ts(8B, MSB=has_ttl)][ttl(8B optional)][record_data] constexpr uint64_t kTtlMsb = 1ULL << 63; @@ -2343,6 +2348,7 @@ int main(int argc, char *argv[]) return -1; } +#if ROCKSDB_CLOUD_EXPORT if (FLAGS_thread_count > EloqKV::Tools::ShardProgressPrinter::kMaxScanThreads) { @@ -2352,7 +2358,6 @@ int main(int argc, char *argv[]) return -1; } -#if ROCKSDB_CLOUD_EXPORT if (!EloqKV::Tools::ValidateRequiredCloudFlags()) { return -1; From aeb6d7af5eb7faaa70049bf65d30917641e6bc5a Mon Sep 17 00:00:00 2001 From: liunyl Date: Sun, 14 Jun 2026 09:15:12 +0000 Subject: [PATCH 3/4] chore: bump data_substrate to merged main (tx_service#491) tx_service#491 (bthread-mutex CC-request deadlock fix) was squash-merged to tx_service main as 4621885. Re-point the submodule from the now-merged feature-branch commit to that main commit. The squash also brings main forward to include tx_service#507 (test-only multi-process cluster harness, under tests/). Co-Authored-By: Claude Opus 4.8 --- data_substrate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_substrate b/data_substrate index 302ef9a6..4621885f 160000 --- a/data_substrate +++ b/data_substrate @@ -1 +1 @@ -Subproject commit 302ef9a6df44dbd945a0038e3f7f4251e30f8fd3 +Subproject commit 4621885faca0893bd490f36fa1b24ff453b3c960 From dce49a69db0fbc005f54d570f57e2938fac98e7e Mon Sep 17 00:00:00 2001 From: liunyl Date: Mon, 15 Jun 2026 02:40:53 +0000 Subject: [PATCH 4/4] rebase with main --- data_substrate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_substrate b/data_substrate index 4621885f..dc37e861 160000 --- a/data_substrate +++ b/data_substrate @@ -1 +1 @@ -Subproject commit 4621885faca0893bd490f36fa1b24ff453b3c960 +Subproject commit dc37e861e4b3ffbcc3eb320754c62c889f325126