This is an automated email from the ASF dual-hosted git repository.
twice pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 5d287de0 feat(config): allow to change the max length of the bulk
string (#2444)
5d287de0 is described below
commit 5d287de082faaf84a04272cc00ed7919aac59c7b
Author: hulk <[email protected]>
AuthorDate: Thu Jul 25 13:46:06 2024 +0800
feat(config): allow to change the max length of the bulk string (#2444)
---
kvrocks.conf | 5 +++++
src/config/config.cc | 1 +
src/config/config.h | 1 +
src/config/config_type.h | 1 +
src/server/redis_request.cc | 2 +-
src/server/redis_request.h | 1 -
src/types/redis_string.cc | 3 +--
tests/gocase/unit/config/config_test.go | 24 ++++++++++++++++++++++++
8 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/kvrocks.conf b/kvrocks.conf
index 57b347fd..4d953c38 100644
--- a/kvrocks.conf
+++ b/kvrocks.conf
@@ -61,6 +61,11 @@ cluster-enabled no
# Default: no
repl-namespace-enabled no
+# By default, the max length of bulk string is limited to 512MB. If you want to
+# change this limit to a different value(must >= 1MiB), you can use the
following configuration.
+#
+# proto-max-bulk-len 536870912
+
# Persist the cluster nodes topology in local file($dir/nodes.conf). This
configuration
# takes effect only if the cluster mode was enabled.
#
diff --git a/src/config/config.cc b/src/config/config.cc
index 98770ef6..58a15594 100644
--- a/src/config/config.cc
+++ b/src/config/config.cc
@@ -187,6 +187,7 @@ Config::Config() {
{"redis-cursor-compatible", false, new
YesNoField(&redis_cursor_compatible, true)},
{"resp3-enabled", false, new YesNoField(&resp3_enabled, false)},
{"repl-namespace-enabled", false, new
YesNoField(&repl_namespace_enabled, false)},
+ {"proto-max-bulk-len", false, new UInt64Field(&proto_max_bulk_len, 512 *
MiB, 1 * MiB, UINT64_MAX)},
{"json-max-nesting-depth", false, new IntField(&json_max_nesting_depth,
1024, 0, INT_MAX)},
{"json-storage-format", false,
new EnumField<JsonStorageFormat>(&json_storage_format,
json_storage_formats, JsonStorageFormat::JSON)},
diff --git a/src/config/config.h b/src/config/config.h
index 73936de3..83f0090e 100644
--- a/src/config/config.h
+++ b/src/config/config.h
@@ -96,6 +96,7 @@ struct Config {
int max_backup_keep_hours = 24;
int slowlog_log_slower_than = 100000;
int slowlog_max_len = 128;
+ uint64_t proto_max_bulk_len = 512 * 1024 * 1024;
bool daemonize = false;
SupervisedMode supervised_mode = kSupervisedNone;
bool slave_readonly = true;
diff --git a/src/config/config_type.h b/src/config/config_type.h
index d84ce1cb..2b0d2deb 100644
--- a/src/config/config_type.h
+++ b/src/config/config_type.h
@@ -46,6 +46,7 @@ class IntegerField;
using IntField = IntegerField<int>;
using UInt32Field = IntegerField<uint32_t>;
using Int64Field = IntegerField<int64_t>;
+using UInt64Field = IntegerField<uint64_t>;
template <typename Enum>
struct ConfigEnum {
diff --git a/src/server/redis_request.cc b/src/server/redis_request.cc
index 32aee34d..f1e2eb99 100644
--- a/src/server/redis_request.cc
+++ b/src/server/redis_request.cc
@@ -108,7 +108,7 @@ Status Request::Tokenize(evbuffer *input) {
}
bulk_len_ = *parse_result;
- if (bulk_len_ > PROTO_BULK_MAX_SIZE) {
+ if (bulk_len_ > srv_->GetConfig()->proto_max_bulk_len) {
return {Status::NotOK, "Protocol error: invalid bulk length"};
}
diff --git a/src/server/redis_request.h b/src/server/redis_request.h
index bb2d0554..0af1965f 100644
--- a/src/server/redis_request.h
+++ b/src/server/redis_request.h
@@ -33,7 +33,6 @@ class Server;
namespace redis {
constexpr size_t PROTO_INLINE_MAX_SIZE = 16 * 1024L;
-constexpr size_t PROTO_BULK_MAX_SIZE = 512 * 1024L * 1024L;
constexpr size_t PROTO_MULTI_MAX_SIZE = 1024 * 1024L;
using CommandTokens = std::vector<std::string>;
diff --git a/src/types/redis_string.cc b/src/types/redis_string.cc
index 43cf2a30..dca9b326 100644
--- a/src/types/redis_string.cc
+++ b/src/types/redis_string.cc
@@ -27,7 +27,6 @@
#include <string>
#include "parse_util.h"
-#include "server/redis_request.h"
#include "storage/redis_metadata.h"
#include "time_util.h"
@@ -553,7 +552,7 @@ rocksdb::Status String::LCS(const std::string &user_key1,
const std::string &use
// Allocate the LCS table.
uint64_t dp_size = (alen + 1) * (blen + 1);
uint64_t bulk_size = dp_size * sizeof(uint32_t);
- if (bulk_size > PROTO_BULK_MAX_SIZE || bulk_size / dp_size !=
sizeof(uint32_t)) {
+ if (bulk_size > storage_->GetConfig()->proto_max_bulk_len || bulk_size /
dp_size != sizeof(uint32_t)) {
return rocksdb::Status::Aborted("Insufficient memory, transient memory for
LCS exceeds proto-max-bulk-len");
}
std::vector<uint32_t> dp(dp_size, 0);
diff --git a/tests/gocase/unit/config/config_test.go
b/tests/gocase/unit/config/config_test.go
index d2643c2c..a902bb89 100644
--- a/tests/gocase/unit/config/config_test.go
+++ b/tests/gocase/unit/config/config_test.go
@@ -245,3 +245,27 @@ func TestDynamicChangeWorkerThread(t *testing.T) {
require.Equal(t, "bar", rdb.Get(ctx, "foo").Val())
})
}
+
+func TestChangeProtoMaxBulkLen(t *testing.T) {
+ configs := map[string]string{}
+ srv := util.StartServer(t, configs)
+ defer srv.Close()
+
+ ctx := context.Background()
+ rdb := srv.NewClient()
+ defer func() { require.NoError(t, rdb.Close()) }()
+
+ // Default value is 512MB
+ vals, err := rdb.ConfigGet(ctx, "proto-max-bulk-len").Result()
+ require.NoError(t, err)
+ require.EqualValues(t, "536870912", vals["proto-max-bulk-len"])
+
+ // Change to 2MB
+ require.NoError(t, rdb.ConfigSet(ctx, "proto-max-bulk-len",
"2097152").Err())
+ vals, err = rdb.ConfigGet(ctx, "proto-max-bulk-len").Result()
+ require.NoError(t, err)
+ require.EqualValues(t, "2097152", vals["proto-max-bulk-len"])
+
+ // Must be >= 1MB
+ require.Error(t, rdb.ConfigSet(ctx, "proto-max-bulk-len", "1024").Err())
+}