This is an automated email from the ASF dual-hosted git repository.
hulk 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 3df90b37 Add RESP3 big number (#2034)
3df90b37 is described below
commit 3df90b3764da1767c5227969d14a7264de7efe4d
Author: hulk <[email protected]>
AuthorDate: Mon Jan 22 00:12:50 2024 +0800
Add RESP3 big number (#2034)
---
src/commands/cmd_server.cc | 4 ++-
src/server/redis_connection.h | 3 +++
src/storage/scripting.cc | 42 +++++++++++++++++++----------
tests/gocase/unit/debug/debug_test.go | 4 +++
tests/gocase/unit/protocol/protocol_test.go | 2 ++
5 files changed, 40 insertions(+), 15 deletions(-)
diff --git a/src/commands/cmd_server.cc b/src/commands/cmd_server.cc
index d34c5595..fb6ca8a4 100644
--- a/src/commands/cmd_server.cc
+++ b/src/commands/cmd_server.cc
@@ -623,6 +623,8 @@ class CommandDebug : public Commander {
*output += redis::Integer(i);
*output += conn->Bool(i == 1);
}
+ } else if (protocol_type_ == "bignum") {
+ *output = conn->BigNumber("1234567999999999999999999999999999999");
} else if (protocol_type_ == "true") {
*output = conn->Bool(true);
} else if (protocol_type_ == "false") {
@@ -631,7 +633,7 @@ class CommandDebug : public Commander {
*output = conn->NilString();
} else {
*output = redis::Error(
- "Wrong protocol type name. Please use one of the following:
string|int|array|set|true|false|null");
+ "Wrong protocol type name. Please use one of the following:
string|int|array|set|bignum|true|false|null");
}
} else {
return {Status::RedisInvalidCmd, "Unknown subcommand, should be DEBUG or
PROTOCOL"};
diff --git a/src/server/redis_connection.h b/src/server/redis_connection.h
index 7f622fe5..47b694a0 100644
--- a/src/server/redis_connection.h
+++ b/src/server/redis_connection.h
@@ -65,6 +65,9 @@ class Connection : public EvbufCallbackBase<Connection> {
RESP GetProtocolVersion() const { return protocol_version_; }
void SetProtocolVersion(RESP version) { protocol_version_ = version; }
std::string Bool(bool b) const;
+ std::string BigNumber(const std::string &n) const {
+ return protocol_version_ == RESP::v3 ? "(" + n + CRLF : BulkString(n);
+ }
std::string NilString() const { return redis::NilString(protocol_version_); }
std::string NilArray() const { return protocol_version_ == RESP::v3 ? "_"
CRLF : "*-1" CRLF; }
std::string MultiBulkString(const std::vector<std::string> &values, bool
output_nil_for_empty_string = true) const;
diff --git a/src/storage/scripting.cc b/src/storage/scripting.cc
index 4d94cd4a..8105d321 100644
--- a/src/storage/scripting.cc
+++ b/src/storage/scripting.cc
@@ -1080,6 +1080,7 @@ std::string ReplyToRedisReply(redis::Connection *conn,
lua_State *lua) {
std::string output;
const char *obj_s = nullptr;
size_t obj_len = 0;
+ int j = 0, mbulklen = 0;
int t = lua_type(lua, -1);
switch (t) {
@@ -1113,6 +1114,7 @@ std::string ReplyToRedisReply(redis::Connection *conn,
lua_State *lua) {
return output;
}
lua_pop(lua, 1); /* Discard field name pushed before. */
+
/* Handle status reply. */
lua_pushstring(lua, "ok");
lua_gettable(lua, -2);
@@ -1122,23 +1124,35 @@ std::string ReplyToRedisReply(redis::Connection *conn,
lua_State *lua) {
output = redis::BulkString(std::string(obj_s, obj_len));
lua_pop(lua, 1);
return output;
- } else {
- int j = 1, mbulklen = 0;
- lua_pop(lua, 1); /* Discard the 'ok' field value we popped */
- while (true) {
- lua_pushnumber(lua, j++);
- lua_gettable(lua, -2);
- t = lua_type(lua, -1);
- if (t == LUA_TNIL) {
- lua_pop(lua, 1);
- break;
- }
- mbulklen++;
- output += ReplyToRedisReply(conn, lua);
+ }
+ lua_pop(lua, 1); /* Discard the 'ok' field value we pushed */
+
+ /* Handle big number reply. */
+ lua_pushstring(lua, "big_number");
+ lua_gettable(lua, -2);
+ t = lua_type(lua, -1);
+ if (t == LUA_TSTRING) {
+ obj_s = lua_tolstring(lua, -1, &obj_len);
+ output = conn->BigNumber(std::string(obj_s, obj_len));
+ lua_pop(lua, 1);
+ return output;
+ }
+ lua_pop(lua, 1); /* Discard the 'big_number' field value we pushed */
+
+ j = 1, mbulklen = 0;
+ while (true) {
+ lua_pushnumber(lua, j++);
+ lua_gettable(lua, -2);
+ t = lua_type(lua, -1);
+ if (t == LUA_TNIL) {
lua_pop(lua, 1);
+ break;
}
- output = redis::MultiLen(mbulklen) + output;
+ mbulklen++;
+ output += ReplyToRedisReply(conn, lua);
+ lua_pop(lua, 1);
}
+ output = redis::MultiLen(mbulklen) + output;
break;
default:
output = conn->NilString();
diff --git a/tests/gocase/unit/debug/debug_test.go
b/tests/gocase/unit/debug/debug_test.go
index faa29811..1aae088f 100644
--- a/tests/gocase/unit/debug/debug_test.go
+++ b/tests/gocase/unit/debug/debug_test.go
@@ -21,6 +21,7 @@ package debug
import (
"context"
+ "math/big"
"testing"
"github.com/redis/go-redis/v9"
@@ -46,6 +47,7 @@ func TestDebugProtocolV2(t *testing.T) {
"array": []interface{}{int64(0), int64(1), int64(2)},
"set": []interface{}{int64(0), int64(1), int64(2)},
"map": []interface{}{int64(0), int64(0), int64(1),
int64(1), int64(2), int64(0)},
+ "bignum": "1234567999999999999999999999999999999",
"true": int64(1),
"false": int64(0),
}
@@ -83,12 +85,14 @@ func TestDebugProtocolV3(t *testing.T) {
defer func() { require.NoError(t, rdb.Close()) }()
t.Run("debug protocol type", func(t *testing.T) {
+ bignum, _ :=
big.NewInt(0).SetString("1234567999999999999999999999999999999", 10)
types := map[string]interface{}{
"string": "Hello World",
"integer": int64(12345),
"array": []interface{}{int64(0), int64(1), int64(2)},
"set": []interface{}{int64(0), int64(1), int64(2)},
"map": map[interface{}]interface{}{int64(0): false,
int64(1): true, int64(2): false},
+ "bignum": bignum,
"true": true,
"false": false,
}
diff --git a/tests/gocase/unit/protocol/protocol_test.go
b/tests/gocase/unit/protocol/protocol_test.go
index 7919bf77..33202c90 100644
--- a/tests/gocase/unit/protocol/protocol_test.go
+++ b/tests/gocase/unit/protocol/protocol_test.go
@@ -156,6 +156,7 @@ func TestProtocolRESP2(t *testing.T) {
"array": {"*3", ":0", ":1", ":2"},
"set": {"*3", ":0", ":1", ":2"},
"map": {"*6", ":0", ":0", ":1", ":1", ":2", ":0"},
+ "bignum": {"$37",
"1234567999999999999999999999999999999"},
"true": {":1"},
"false": {":0"},
"null": {"$-1"},
@@ -210,6 +211,7 @@ func TestProtocolRESP3(t *testing.T) {
"array": {"*3", ":0", ":1", ":2"},
"set": {"~3", ":0", ":1", ":2"},
"map": {"%3", ":0", "#f", ":1", "#t", ":2", "#f"},
+ "bignum": {"(1234567999999999999999999999999999999"},
"true": {"#t"},
"false": {"#f"},
"null": {"_"},