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 8f1d2add chore(error): unify error by adding Redis error codes for
Status (#2362)
8f1d2add is described below
commit 8f1d2add8836b5a70a313df8a4802fdcc1817741
Author: hulk <[email protected]>
AuthorDate: Sat Jun 15 11:43:33 2024 +0800
chore(error): unify error by adding Redis error codes for Status (#2362)
This PR introduces new error codes to identify Redis error prefixes,
and forces using status to unify Redis errors. You MUST convert
it to Status to send a Redis error response.
---
src/cluster/cluster.cc | 19 +++----
src/cluster/cluster_defs.h | 2 +-
src/cluster/replication.cc | 9 ++-
src/cluster/sync_migrate_context.cc | 2 +-
src/commands/cmd_bloom_filter.cc | 8 +--
src/commands/cmd_cluster.cc | 20 +++----
src/commands/cmd_hash.cc | 9 +--
src/commands/cmd_key.cc | 14 ++---
src/commands/cmd_list.cc | 6 +-
src/commands/cmd_replication.cc | 4 +-
src/commands/cmd_script.cc | 3 +-
src/commands/cmd_server.cc | 32 +++++------
src/commands/cmd_stream.cc | 24 +++-----
src/commands/cmd_txn.cc | 3 +-
src/commands/cmd_zset.cc | 20 ++-----
src/commands/error_constants.h | 6 +-
src/common/status.h | 14 ++++-
src/server/redis_connection.cc | 28 ++++-----
src/server/redis_reply.cc | 24 +++++++-
src/server/redis_reply.h | 6 +-
src/server/worker.cc | 5 +-
src/storage/rdb.cc | 109 ++++++++----------------------------
src/storage/scripting.cc | 11 ++--
src/types/json.h | 2 +-
24 files changed, 162 insertions(+), 218 deletions(-)
diff --git a/src/cluster/cluster.cc b/src/cluster/cluster.cc
index d080ed34..8d373e0d 100644
--- a/src/cluster/cluster.cc
+++ b/src/cluster/cluster.cc
@@ -363,7 +363,7 @@ Status Cluster::ImportSlot(redis::Connection *conn, int
slot, int state) {
Status Cluster::GetClusterInfo(std::string *cluster_infos) {
if (version_ < 0) {
- return {Status::ClusterDown, errClusterNoInitialized};
+ return {Status::RedisClusterDown, errClusterNoInitialized};
}
cluster_infos->clear();
@@ -421,7 +421,7 @@ Status Cluster::GetClusterInfo(std::string *cluster_infos) {
// ... continued until done
Status Cluster::GetSlotsInfo(std::vector<SlotInfo> *slots_infos) {
if (version_ < 0) {
- return {Status::ClusterDown, errClusterNoInitialized};
+ return {Status::RedisClusterDown, errClusterNoInitialized};
}
slots_infos->clear();
@@ -464,7 +464,7 @@ SlotInfo Cluster::genSlotNodeInfo(int start, int end, const
std::shared_ptr<Clus
// $version $connected $slot_range
Status Cluster::GetClusterNodes(std::string *nodes_str) {
if (version_ < 0) {
- return {Status::ClusterDown, errClusterNoInitialized};
+ return {Status::RedisClusterDown, errClusterNoInitialized};
}
*nodes_str = genNodesDescription();
@@ -473,7 +473,7 @@ Status Cluster::GetClusterNodes(std::string *nodes_str) {
StatusOr<std::string> Cluster::GetReplicas(const std::string &node_id) {
if (version_ < 0) {
- return {Status::ClusterDown, errClusterNoInitialized};
+ return {Status::RedisClusterDown, errClusterNoInitialized};
}
auto item = nodes_.find(node_id);
@@ -821,13 +821,13 @@ Status Cluster::CanExecByMySelf(const
redis::CommandAttributes *attributes, cons
int cur_slot = GetSlotIdFromKey(cmd_tokens[i]);
if (slot == -1) slot = cur_slot;
if (slot != cur_slot) {
- return {Status::RedisExecErr, "CROSSSLOT Attempted to access keys that
don't hash to the same slot"};
+ return {Status::RedisCrossSlot, "Attempted to access keys that don't
hash to the same slot"};
}
}
if (slot == -1) return Status::OK();
if (slots_nodes_[slot] == nullptr) {
- return {Status::ClusterDown, "CLUSTERDOWN Hash slot not served"};
+ return {Status::RedisClusterDown, "Hash slot not served"};
}
if (myself_ && myself_ == slots_nodes_[slot]) {
@@ -835,12 +835,12 @@ Status Cluster::CanExecByMySelf(const
redis::CommandAttributes *attributes, cons
// Server can't change the topology directly, so we record the migrated
slots
// to move the requests of the migrated slots to the destination node.
if (migrated_slots_.count(slot) > 0) { // I'm not serving the migrated
slot
- return {Status::RedisExecErr, fmt::format("MOVED {} {}", slot,
migrated_slots_[slot])};
+ return {Status::RedisMoved, fmt::format("{} {}", slot,
migrated_slots_[slot])};
}
// To keep data consistency, slot will be forbidden write while sending
the last incremental data.
// During this phase, the requests of the migrating slot has to be
rejected.
if ((attributes->flags & redis::kCmdWrite) && IsWriteForbiddenSlot(slot)) {
- return {Status::RedisExecErr, "TRYAGAIN Can't write to slot being
migrated which is in write forbidden phase"};
+ return {Status::RedisTryAgain, "Can't write to slot being migrated which
is in write forbidden phase"};
}
return Status::OK(); // I'm serving this slot
@@ -868,8 +868,7 @@ Status Cluster::CanExecByMySelf(const
redis::CommandAttributes *attributes, cons
return Status::OK(); // My master is serving this slot
}
- return {Status::RedisExecErr,
- fmt::format("MOVED {} {}:{}", slot, slots_nodes_[slot]->host,
slots_nodes_[slot]->port)};
+ return {Status::RedisMoved, fmt::format("{} {}:{}", slot,
slots_nodes_[slot]->host, slots_nodes_[slot]->port)};
}
// Only HARD mode is meaningful to the Kvrocks cluster,
diff --git a/src/cluster/cluster_defs.h b/src/cluster/cluster_defs.h
index 6638db88..0178ac75 100644
--- a/src/cluster/cluster_defs.h
+++ b/src/cluster/cluster_defs.h
@@ -36,7 +36,7 @@ inline constexpr const char *errSlotOutOfRange = "Slot is out
of range";
inline constexpr const char *errInvalidClusterVersion = "Invalid cluster
version";
inline constexpr const char *errSlotOverlapped = "Slot distribution is
overlapped";
inline constexpr const char *errNoMasterNode = "The node isn't a master";
-inline constexpr const char *errClusterNoInitialized = "CLUSTERDOWN The
cluster is not initialized";
+inline constexpr const char *errClusterNoInitialized = "The cluster is not
initialized";
inline constexpr const char *errInvalidClusterNodeInfo = "Invalid cluster
nodes info";
inline constexpr const char *errInvalidImportState = "Invalid import state";
diff --git a/src/cluster/replication.cc b/src/cluster/replication.cc
index a3567284..3de51a94 100644
--- a/src/cluster/replication.cc
+++ b/src/cluster/replication.cc
@@ -1000,15 +1000,18 @@ Status ReplicationThread::parseWriteBatch(const
std::string &batch_string) {
}
bool ReplicationThread::isRestoringError(std::string_view err) {
- return err == std::string(RESP_PREFIX_ERROR) + redis::errRestoringBackup;
+ // err doesn't contain the CRLF, so cannot use redis::Error here.
+ return err == RESP_PREFIX_ERROR +
redis::StatusToRedisErrorMsg({Status::RedisLoading, redis::errRestoringBackup});
}
bool ReplicationThread::isWrongPsyncNum(std::string_view err) {
- return err == std::string(RESP_PREFIX_ERROR) + redis::errWrongNumArguments;
+ // err doesn't contain the CRLF, so cannot use redis::Error here.
+ return err == RESP_PREFIX_ERROR +
redis::StatusToRedisErrorMsg({Status::NotOK, redis::errWrongNumArguments});
}
bool ReplicationThread::isUnknownOption(std::string_view err) {
- return err == fmt::format("{}ERR {}", RESP_PREFIX_ERROR,
redis::errUnknownOption);
+ // err doesn't contain the CRLF, so cannot use redis::Error here.
+ return err == RESP_PREFIX_ERROR +
redis::StatusToRedisErrorMsg({Status::NotOK, redis::errUnknownOption});
}
rocksdb::Status WriteBatchHandler::PutCF(uint32_t column_family_id, const
rocksdb::Slice &key,
diff --git a/src/cluster/sync_migrate_context.cc
b/src/cluster/sync_migrate_context.cc
index 3ba2806c..f1de89b6 100644
--- a/src/cluster/sync_migrate_context.cc
+++ b/src/cluster/sync_migrate_context.cc
@@ -68,7 +68,7 @@ void SyncMigrateContext::OnWrite(bufferevent *bev) {
if (migrate_result_) {
conn_->Reply(redis::SimpleString("OK"));
} else {
- conn_->Reply(redis::Error("ERR " + migrate_result_.Msg()));
+ conn_->Reply(redis::Error(migrate_result_));
}
timer_.reset();
diff --git a/src/commands/cmd_bloom_filter.cc b/src/commands/cmd_bloom_filter.cc
index f33979e3..bb2df94e 100644
--- a/src/commands/cmd_bloom_filter.cc
+++ b/src/commands/cmd_bloom_filter.cc
@@ -33,7 +33,7 @@ constexpr const char *errInvalidErrorRate = "error rate
should be between 0 and
constexpr const char *errInvalidCapacity = "capacity should be larger than 0";
constexpr const char *errInvalidExpansion = "expansion should be greater or
equal to 1";
constexpr const char *errNonscalingButExpand = "nonscaling filters cannot
expand";
-constexpr const char *errFilterFull = "ERR nonscaling filter is full";
+constexpr const char *errFilterFull = "nonscaling filter is full";
} // namespace
namespace redis {
@@ -119,7 +119,7 @@ class CommandBFAdd : public Commander {
*output = redis::Integer(0);
break;
case BloomFilterAddResult::kFull:
- *output = redis::Error(errFilterFull);
+ *output = redis::Error({Status::NotOK, errFilterFull});
break;
}
return Status::OK();
@@ -152,7 +152,7 @@ class CommandBFMAdd : public Commander {
*output += redis::Integer(0);
break;
case BloomFilterAddResult::kFull:
- *output += redis::Error(errFilterFull);
+ *output += redis::Error({Status::NotOK, errFilterFull});
break;
}
}
@@ -248,7 +248,7 @@ class CommandBFInsert : public Commander {
*output += redis::Integer(0);
break;
case BloomFilterAddResult::kFull:
- *output += redis::Error(errFilterFull);
+ *output += redis::Error({Status::NotOK, errFilterFull});
break;
}
}
diff --git a/src/commands/cmd_cluster.cc b/src/commands/cmd_cluster.cc
index 8ada4e8e..0f9b1760 100644
--- a/src/commands/cmd_cluster.cc
+++ b/src/commands/cmd_cluster.cc
@@ -90,7 +90,7 @@ class CommandCluster : public Commander {
}
}
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else if (subcommand_ == "nodes") {
std::string nodes_desc;
@@ -98,7 +98,7 @@ class CommandCluster : public Commander {
if (s.IsOK()) {
*output = conn->VerbatimString("txt", nodes_desc);
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else if (subcommand_ == "info") {
std::string cluster_info;
@@ -106,21 +106,21 @@ class CommandCluster : public Commander {
if (s.IsOK()) {
*output = conn->VerbatimString("txt", cluster_info);
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else if (subcommand_ == "import") {
Status s = srv->cluster->ImportSlot(conn, static_cast<int>(slot_),
state_);
if (s.IsOK()) {
*output = redis::SimpleString("OK");
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else if (subcommand_ == "reset") {
Status s = srv->cluster->Reset();
if (s.IsOK()) {
*output = redis::SimpleString("OK");
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else if (subcommand_ == "replicas") {
auto node_id = args_[2];
@@ -128,7 +128,7 @@ class CommandCluster : public Commander {
if (s.IsOK()) {
*output = conn->VerbatimString("txt", s.GetValue());
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else {
return {Status::RedisExecErr, "Invalid cluster command options"};
@@ -252,7 +252,7 @@ class CommandClusterX : public Commander {
need_persist_nodes_info = true;
*output = redis::SimpleString("OK");
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else if (subcommand_ == "setnodeid") {
Status s = srv->cluster->SetNodeId(args_[2]);
@@ -260,7 +260,7 @@ class CommandClusterX : public Commander {
need_persist_nodes_info = true;
*output = redis::SimpleString("OK");
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else if (subcommand_ == "setslot") {
Status s = srv->cluster->SetSlotRanges(slot_ranges_, args_[4],
set_version_);
@@ -268,7 +268,7 @@ class CommandClusterX : public Commander {
need_persist_nodes_info = true;
*output = redis::SimpleString("OK");
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else if (subcommand_ == "version") {
int64_t v = srv->cluster->GetVersion();
@@ -287,7 +287,7 @@ class CommandClusterX : public Commander {
}
*output = redis::SimpleString("OK");
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else {
return {Status::RedisExecErr, "Invalid cluster command options"};
diff --git a/src/commands/cmd_hash.cc b/src/commands/cmd_hash.cc
index 6db97f89..677f131e 100644
--- a/src/commands/cmd_hash.cc
+++ b/src/commands/cmd_hash.cc
@@ -326,16 +326,11 @@ class CommandHRangeByLex : public Commander {
return parser.InvalidSyntax();
}
}
- Status s;
if (spec_.reversed) {
- s = ParseRangeLexSpec(args[3], args[2], &spec_);
+ return ParseRangeLexSpec(args[3], args[2], &spec_);
} else {
- s = ParseRangeLexSpec(args[2], args[3], &spec_);
+ return ParseRangeLexSpec(args[2], args[3], &spec_);
}
- if (!s.IsOK()) {
- return {Status::RedisParseErr, s.Msg()};
- }
- return Status::OK();
}
Status Execute(Server *srv, Connection *conn, std::string *output) override {
diff --git a/src/commands/cmd_key.cc b/src/commands/cmd_key.cc
index 24d8fe29..d7219841 100644
--- a/src/commands/cmd_key.cc
+++ b/src/commands/cmd_key.cc
@@ -480,8 +480,7 @@ class CommandSort : public Commander {
}
if (type != RedisType::kRedisList && type != RedisType::kRedisSet && type
!= RedisType::kRedisZSet) {
- *output = Error("WRONGTYPE Operation against a key holding the wrong
kind of value");
- return Status::OK();
+ return {Status::RedisWrongType, "Operation against a key holding the
wrong kind of value"};
}
/* When sorting a set with no sort specified, we must sort the output
@@ -508,15 +507,12 @@ class CommandSort : public Commander {
switch (res) {
case Database::SortResult::UNKNOWN_TYPE:
- *output = redis::Error("Unknown Type");
- break;
+ return {Status::RedisErrorNoPrefix, "Unknown Type"};
case Database::SortResult::DOUBLE_CONVERT_ERROR:
- *output = redis::Error("One or more scores can't be converted into
double");
- break;
+ return {Status::RedisErrorNoPrefix, "One or more scores can't be
converted into double"};
case Database::SortResult::LIMIT_EXCEEDED:
- *output = redis::Error("The number of elements to be sorted exceeds
SORT_LENGTH_LIMIT = " +
- std::to_string(SORT_LENGTH_LIMIT));
- break;
+ return {Status::RedisErrorNoPrefix,
+ "The number of elements to be sorted exceeds SORT_LENGTH_LIMIT
= " + std::to_string(SORT_LENGTH_LIMIT)};
case Database::SortResult::DONE:
if (sort_argument_.storekey.empty()) {
std::vector<std::string> output_vec;
diff --git a/src/commands/cmd_list.cc b/src/commands/cmd_list.cc
index f354d64c..e9e17266 100644
--- a/src/commands/cmd_list.cc
+++ b/src/commands/cmd_list.cc
@@ -304,7 +304,7 @@ class CommandBPop : public BlockingCommander {
conn_->Reply(conn_->MultiBulkString({*last_key_ptr, std::move(elem)}));
}
} else if (!s.IsNotFound()) {
- conn_->Reply(redis::Error("ERR " + s.ToString()));
+ conn_->Reply(redis::Error({Status::NotOK, s.ToString()}));
}
return s;
@@ -414,7 +414,7 @@ class CommandBLMPop : public BlockingCommander {
conn_->Reply(redis::Array({redis::BulkString(chosen_key),
std::move(elems_bulk)}));
}
} else if (!s.IsNotFound()) {
- conn_->Reply(redis::Error("ERR " + s.ToString()));
+ conn_->Reply(redis::Error({Status::NotOK, s.ToString()}));
}
return s;
@@ -757,7 +757,7 @@ class CommandBLMove : public BlockingCommander {
std::string elem;
auto s = list_db.LMove(args_[1], args_[2], src_left_, dst_left_, &elem);
if (!s.ok() && !s.IsNotFound()) {
- conn_->Reply(redis::Error("ERR " + s.ToString()));
+ conn_->Reply(redis::Error({Status::NotOK, s.ToString()}));
return true;
}
diff --git a/src/commands/cmd_replication.cc b/src/commands/cmd_replication.cc
index 5ec6faa0..d3f3c0f2 100644
--- a/src/commands/cmd_replication.cc
+++ b/src/commands/cmd_replication.cc
@@ -102,7 +102,7 @@ class CommandPSync : public Commander {
srv->stats.IncrPSyncOKCount();
s = srv->AddSlave(conn, next_repl_seq_);
if (!s.IsOK()) {
- std::string err = redis::Error(s.Msg());
+ std::string err = redis::Error(s);
s = util::SockSend(conn->GetFD(), err, conn->GetBufferEvent());
if (!s.IsOK()) {
LOG(WARNING) << "failed to send error message to the replica: " <<
s.Msg();
@@ -230,7 +230,7 @@ class CommandFetchMeta : public Commander {
std::string files;
auto s =
engine::Storage::ReplDataManager::GetFullReplDataInfo(srv->storage, &files);
if (!s.IsOK()) {
- s = util::SockSend(repl_fd, redis::Error("can't create db
checkpoint"), bev);
+ s = util::SockSend(repl_fd, redis::Error({Status::RedisErrorNoPrefix,
"can't create db checkpoint"}), bev);
if (!s.IsOK()) {
LOG(WARNING) << "[replication] Failed to send error response: " <<
s.Msg();
}
diff --git a/src/commands/cmd_script.cc b/src/commands/cmd_script.cc
index 34a71837..2547c289 100644
--- a/src/commands/cmd_script.cc
+++ b/src/commands/cmd_script.cc
@@ -31,8 +31,7 @@ class CommandEvalImpl : public Commander {
public:
Status Execute(Server *srv, Connection *conn, std::string *output) override {
if (evalsha && args_[1].size() != 40) {
- *output = redis::Error(errNoMatchingScript);
- return Status::OK();
+ return {Status::RedisNoScript, errNoMatchingScript};
}
int64_t numkeys = GET_OR_RET(ParseInt<int64_t>(args_[2], 10));
diff --git a/src/commands/cmd_server.cc b/src/commands/cmd_server.cc
index 114eee15..d595875d 100644
--- a/src/commands/cmd_server.cc
+++ b/src/commands/cmd_server.cc
@@ -95,17 +95,17 @@ class CommandNamespace : public Commander {
}
} else if (args_.size() == 4 && sub_command == "set") {
Status s = srv->GetNamespace()->Set(args_[2], args_[3]);
- *output = s.IsOK() ? redis::SimpleString("OK") : redis::Error("ERR " +
s.Msg());
+ *output = s.IsOK() ? redis::SimpleString("OK") : redis::Error(s);
LOG(WARNING) << "Updated namespace: " << args_[2] << " with token: " <<
args_[3] << ", addr: " << conn->GetAddr()
<< ", result: " << s.Msg();
} else if (args_.size() == 4 && sub_command == "add") {
Status s = srv->GetNamespace()->Add(args_[2], args_[3]);
- *output = s.IsOK() ? redis::SimpleString("OK") : redis::Error("ERR " +
s.Msg());
+ *output = s.IsOK() ? redis::SimpleString("OK") : redis::Error(s);
LOG(WARNING) << "New namespace: " << args_[2] << " with token: " <<
args_[3] << ", addr: " << conn->GetAddr()
<< ", result: " << s.Msg();
} else if (args_.size() == 3 && sub_command == "del") {
Status s = srv->GetNamespace()->Del(args_[2]);
- *output = s.IsOK() ? redis::SimpleString("OK") : redis::Error("ERR " +
s.Msg());
+ *output = s.IsOK() ? redis::SimpleString("OK") : redis::Error(s);
LOG(WARNING) << "Deleted namespace: " << args_[2] << ", addr: " <<
conn->GetAddr() << ", result: " << s.Msg();
} else {
return {Status::RedisExecErr, "NAMESPACE subcommand must be one of GET,
SET, DEL, ADD"};
@@ -224,7 +224,7 @@ class CommandConfig : public Commander {
if (args_.size() == 2 && sub_command == "rewrite") {
Status s = config->Rewrite(srv->GetNamespace()->List());
- if (!s.IsOK()) return {Status::RedisExecErr, s.Msg()};
+ if (!s.IsOK()) return s;
*output = redis::SimpleString("OK");
LOG(INFO) << "# CONFIG REWRITE executed with success";
@@ -315,7 +315,7 @@ class CommandDBSize : public Commander {
if (s.IsOK()) {
*output = redis::SimpleString("OK");
} else {
- return {Status::RedisExecErr, s.Msg()};
+ return s;
}
} else {
return {Status::RedisExecErr, "DBSIZE subcommand only supports scan"};
@@ -630,9 +630,9 @@ class CommandDebug : public Commander {
} else if (protocol_type_ == "verbatim") { // verbatim string
*output = conn->VerbatimString("txt", "verbatim string");
} else {
- *output = redis::Error(
- "Wrong protocol type name. Please use one of the following: "
-
"string|integer|double|array|set|bignum|true|false|null|attrib|verbatim");
+ return {Status::RedisErrorNoPrefix,
+ "Wrong protocol type name. Please use one of the following: "
+
"string|integer|double|array|set|bignum|true|false|null|attrib|verbatim"};
}
} else if (subcommand_ == "dbsize-limit") {
srv->storage->SetDBSizeLimit(dbsize_limit_);
@@ -741,8 +741,7 @@ class CommandHello final : public Commander {
// kvrocks only supports REPL2 by now, but for supporting some
// `hello 3`, it will not report error when using 3.
if (protocol < 2 || protocol > 3) {
- conn->Reply(redis::Error("NOPROTO unsupported protocol version"));
- return Status::OK();
+ return {Status::RedisNoProto, "unsupported protocol version"};
}
}
@@ -986,9 +985,7 @@ class CommandSlaveOf : public Commander {
}
auto s = IsTryingToReplicateItself(srv, host_, port_);
- if (!s.IsOK()) {
- return {Status::RedisExecErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
s = srv->AddMaster(host_, port_, false);
if (s.IsOK()) {
*output = redis::SimpleString("OK");
@@ -1101,7 +1098,7 @@ class CommandRestore : public Commander {
auto stream_ptr = std::make_unique<RdbStringStream>(args_[3]);
RDB rdb(srv->storage, conn->GetNamespace(), std::move(stream_ptr));
auto s = rdb.Restore(args_[1], args_[3], ttl_ms_);
- if (!s.IsOK()) return {Status::RedisExecErr, s.Msg()};
+ if (!s.IsOK()) return s;
*output = redis::SimpleString("OK");
return Status::OK();
}
@@ -1215,9 +1212,8 @@ class CommandApplyBatch : public Commander {
auto options = svr->storage->DefaultWriteOptions();
options.low_pri = low_pri_;
auto s = svr->storage->ApplyWriteBatch(options, std::move(raw_batch_));
- if (!s.IsOK()) {
- return {Status::RedisExecErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
+
*output = redis::Integer(size);
return Status::OK();
}
@@ -1262,7 +1258,7 @@ class CommandDump : public Commander {
auto stream_ptr = std::make_unique<RdbStringStream>(result);
RDB rdb(srv->storage, conn->GetNamespace(), std::move(stream_ptr));
auto s = rdb.Dump(key, type);
- if (!s.IsOK()) return {Status::RedisExecErr, s.Msg()};
+ if (!s.IsOK()) return s;
CHECK(dynamic_cast<RdbStringStream *>(rdb.GetStream().get()) != nullptr);
*output = redis::BulkString(static_cast<RdbStringStream
*>(rdb.GetStream().get())->GetInput());
return Status::OK();
diff --git a/src/commands/cmd_stream.cc b/src/commands/cmd_stream.cc
index 7b3bf54e..ba4f7d98 100644
--- a/src/commands/cmd_stream.cc
+++ b/src/commands/cmd_stream.cc
@@ -39,9 +39,7 @@ class CommandXAck : public Commander {
StreamEntryID tmp_id;
for (size_t i = 3; i < args.size(); ++i) {
auto s = ParseStreamEntryID(args[i], &tmp_id);
- if (!s.IsOK()) {
- return {Status::RedisParseErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
entry_ids_.emplace_back(tmp_id);
}
@@ -130,9 +128,7 @@ class CommandXAdd : public Commander {
}
auto s = ParseStreamEntryID(args[min_id_idx], &min_id_);
- if (!s.IsOK()) {
- return {Status::RedisParseErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
with_min_id_ = true;
i += eq_sign_found ? 3 : 2;
@@ -145,9 +141,7 @@ class CommandXAdd : public Commander {
if (!entry_id_found) {
auto result = ParseNextStreamEntryIDStrategy(val);
- if (!result.IsOK()) {
- return {Status::RedisParseErr, result.Msg()};
- }
+ if (!result.IsOK()) return result;
next_id_strategy_ = std::move(*result);
@@ -1130,7 +1124,7 @@ class CommandXRead : public Commander,
std::vector<StreamEntry> result;
auto s = stream_db.Range(streams_[i], options, &result);
if (!s.ok() && !s.IsNotFound()) {
- conn_->Reply(redis::Error("ERR " + s.ToString()));
+ conn_->Reply(redis::Error({Status::NotOK, s.ToString()}));
return;
}
@@ -1423,7 +1417,7 @@ class CommandXReadGroup : public Commander,
auto s = stream_db.RangeWithPending(streams_[i], options, &result,
group_name_, consumer_name_, noack_,
latest_marks_[i]);
if (!s.ok() && !s.IsNotFound()) {
- conn_->Reply(redis::Error("ERR " + s.ToString()));
+ conn_->Reply(redis::Error({Status::NotOK, s.ToString()}));
return;
}
@@ -1599,9 +1593,7 @@ class CommandXSetId : public Commander {
stream_name_ = args[1];
auto s = redis::ParseStreamEntryID(args[2], &last_id_);
- if (!s.IsOK()) {
- return {Status::RedisParseErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
if (args.size() == 3) {
return Status::OK();
@@ -1619,9 +1611,7 @@ class CommandXSetId : public Commander {
} else if (util::EqualICase(args[i], "maxdeletedid") && i + 1 <
args.size()) {
StreamEntryID id;
s = redis::ParseStreamEntryID(args[i + 1], &id);
- if (!s.IsOK()) {
- return {Status::RedisParseErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
max_deleted_id_ = std::make_optional<StreamEntryID>(id.ms, id.seq);
i += 2;
diff --git a/src/commands/cmd_txn.cc b/src/commands/cmd_txn.cc
index fa1a47aa..130533fb 100644
--- a/src/commands/cmd_txn.cc
+++ b/src/commands/cmd_txn.cc
@@ -68,8 +68,7 @@ class CommandExec : public Commander {
auto reset_multiexec = MakeScopeExit([conn] { conn->ResetMultiExec(); });
if (conn->IsMultiError()) {
- *output = redis::Error("EXECABORT Transaction discarded");
- return Status::OK();
+ return {Status::RedisExecAbort, "Transaction discarded"};
}
if (srv->IsWatchedKeysModified(conn)) {
diff --git a/src/commands/cmd_zset.cc b/src/commands/cmd_zset.cc
index c32c976a..715747ab 100644
--- a/src/commands/cmd_zset.cc
+++ b/src/commands/cmd_zset.cc
@@ -136,9 +136,7 @@ class CommandZCount : public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
Status s = ParseRangeScoreSpec(args[2], args[3], &spec_);
- if (!s.IsOK()) {
- return {Status::RedisParseErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
return Commander::Parse(args);
}
@@ -204,9 +202,7 @@ class CommandZLexCount : public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
Status s = ParseRangeLexSpec(args[2], args[3], &spec_);
- if (!s.IsOK()) {
- return {Status::RedisParseErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
return Commander::Parse(args);
}
@@ -369,7 +365,7 @@ class CommandBZPop : public BlockingCommander {
redis::ZSet zset_db(srv_->storage, conn_->GetNamespace());
auto s = PopFromMultipleZsets(&zset_db, keys_, min_, 1, &user_key,
&member_scores);
if (!s.ok()) {
- conn_->Reply(redis::Error("ERR " + s.ToString()));
+ conn_->Reply(redis::Error({Status::NotOK, s.ToString()}));
return true;
}
@@ -548,7 +544,7 @@ class CommandBZMPop : public BlockingCommander {
redis::ZSet zset_db(srv_->storage, conn_->GetNamespace());
auto s = PopFromMultipleZsets(&zset_db, keys_, flag_ == ZSET_MIN, count_,
&user_key, &member_scores);
if (!s.ok()) {
- conn_->Reply(redis::Error("ERR " + s.ToString()));
+ conn_->Reply(redis::Error({Status::NotOK, s.ToString()}));
return true;
}
@@ -985,9 +981,7 @@ class CommandZRemRangeByScore : public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
Status s = ParseRangeScoreSpec(args[2], args[3], &spec_);
- if (!s.IsOK()) {
- return {Status::RedisParseErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
return Commander::Parse(args);
}
@@ -1014,9 +1008,7 @@ class CommandZRemRangeByLex : public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
Status s = ParseRangeLexSpec(args[2], args[3], &spec_);
- if (!s.IsOK()) {
- return {Status::RedisParseErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
return Commander::Parse(args);
}
diff --git a/src/commands/error_constants.h b/src/commands/error_constants.h
index 2074a705..ea2c38b7 100644
--- a/src/commands/error_constants.h
+++ b/src/commands/error_constants.h
@@ -40,10 +40,10 @@ inline constexpr const char *errLimitOptionNotAllowed =
inline constexpr const char *errZSetLTGTNX = "GT, LT, and/or NX options at the
same time are not compatible";
inline constexpr const char *errScoreIsNotValidFloat = "score is not a valid
float";
inline constexpr const char *errValueIsNotFloat = "value is not a valid float";
-inline constexpr const char *errNoMatchingScript = "NOSCRIPT No matching
script. Please use EVAL";
+inline constexpr const char *errNoMatchingScript = "No matching script. Please
use EVAL";
inline constexpr const char *errUnknownOption = "unknown option";
inline constexpr const char *errUnknownSubcommandOrWrongArguments = "Unknown
subcommand or wrong number of arguments";
-inline constexpr const char *errWrongNumArguments = "ERR wrong number of
arguments";
-inline constexpr const char *errRestoringBackup = "LOADING kvrocks is
restoring the db from backup";
+inline constexpr const char *errWrongNumArguments = "wrong number of
arguments";
+inline constexpr const char *errRestoringBackup = "kvrocks is restoring the db
from backup";
} // namespace redis
diff --git a/src/common/status.h b/src/common/status.h
index b425ea5b..d06c2f06 100644
--- a/src/common/status.h
+++ b/src/common/status.h
@@ -50,9 +50,21 @@ class [[nodiscard]] Status {
RedisInvalidCmd,
RedisParseErr,
RedisExecErr,
+ RedisErrorNoPrefix,
+ RedisNoProto,
+ RedisLoading,
+ RedisMasterDown,
+ RedisNoScript,
+ RedisNoAuth,
+ RedisWrongType,
+ RedisReadOnly,
+ RedisExecAbort,
+ RedisMoved,
+ RedisCrossSlot,
+ RedisTryAgain,
+ RedisClusterDown,
// Cluster
- ClusterDown,
ClusterInvalidInfo,
// Blocking
diff --git a/src/server/redis_connection.cc b/src/server/redis_connection.cc
index f3960a66..0457c71d 100644
--- a/src/server/redis_connection.cc
+++ b/src/server/redis_connection.cc
@@ -87,7 +87,7 @@ void Connection::OnRead(struct bufferevent *bev) {
auto s = req_.Tokenize(Input());
if (!s.IsOK()) {
EnableFlag(redis::Connection::kCloseAfterReply);
- Reply(redis::Error("ERR " + s.Msg()));
+ Reply(redis::Error(s));
LOG(INFO) << "[connection] Failed to tokenize the request. Error: " <<
s.Msg();
return;
}
@@ -432,7 +432,7 @@ void Connection::ExecuteCommands(std::deque<CommandTokens>
*to_process_cmds) {
auto cmd_s = Server::LookupAndCreateCommand(cmd_tokens.front());
if (!cmd_s.IsOK()) {
if (is_multi_exec) multi_error_ = true;
- Reply(redis::Error("ERR unknown command " + cmd_tokens.front()));
+ Reply(redis::Error({Status::NotOK, "unknown command " +
cmd_tokens.front()}));
continue;
}
auto current_cmd = std::move(*cmd_s);
@@ -444,7 +444,7 @@ void Connection::ExecuteCommands(std::deque<CommandTokens>
*to_process_cmds) {
if (GetNamespace().empty()) {
if (!password.empty()) {
if (cmd_name != "auth" && cmd_name != "hello") {
- Reply(redis::Error("NOAUTH Authentication required."));
+ Reply(redis::Error({Status::RedisNoAuth, "Authentication
required."}));
continue;
}
} else {
@@ -477,7 +477,7 @@ void Connection::ExecuteCommands(std::deque<CommandTokens>
*to_process_cmds) {
}
if (srv_->IsLoading() && !(cmd_flags & kCmdLoading)) {
- Reply(redis::Error(errRestoringBackup));
+ Reply(redis::Error({Status::RedisLoading, errRestoringBackup}));
if (is_multi_exec) multi_error_ = true;
continue;
}
@@ -485,7 +485,7 @@ void Connection::ExecuteCommands(std::deque<CommandTokens>
*to_process_cmds) {
int tokens = static_cast<int>(cmd_tokens.size());
if (!attributes->CheckArity(tokens)) {
if (is_multi_exec) multi_error_ = true;
- Reply(redis::Error("ERR wrong number of arguments"));
+ Reply(redis::Error({Status::NotOK, "wrong number of arguments"}));
continue;
}
@@ -493,12 +493,12 @@ void
Connection::ExecuteCommands(std::deque<CommandTokens> *to_process_cmds) {
auto s = current_cmd->Parse();
if (!s.IsOK()) {
if (is_multi_exec) multi_error_ = true;
- Reply(redis::Error("ERR " + s.Msg()));
+ Reply(redis::Error(s));
continue;
}
if (is_multi_exec && (cmd_flags & kCmdNoMulti)) {
- Reply(redis::Error("ERR Can't execute " + cmd_name + " in MULTI"));
+ Reply(redis::Error({Status::NotOK, "Can't execute " + cmd_name + " in
MULTI"}));
multi_error_ = true;
continue;
}
@@ -507,7 +507,7 @@ void Connection::ExecuteCommands(std::deque<CommandTokens>
*to_process_cmds) {
s = srv_->cluster->CanExecByMySelf(attributes, cmd_tokens, this);
if (!s.IsOK()) {
if (is_multi_exec) multi_error_ = true;
- Reply(redis::Error(s.Msg()));
+ Reply(redis::Error(s));
continue;
}
}
@@ -525,20 +525,20 @@ void
Connection::ExecuteCommands(std::deque<CommandTokens> *to_process_cmds) {
}
if (config->slave_readonly && srv_->IsSlave() && (cmd_flags & kCmdWrite)) {
- Reply(redis::Error("READONLY You can't write against a read only
slave."));
+ Reply(redis::Error({Status::RedisReadOnly, "You can't write against a
read only slave."}));
continue;
}
if ((cmd_flags & kCmdWrite) && !(cmd_flags & kCmdNoDBSizeCheck) &&
srv_->storage->ReachedDBSizeLimit()) {
- Reply(redis::Error("ERR write command not allowed when reached
max-db-size."));
+ Reply(redis::Error({Status::NotOK, "write command not allowed when
reached max-db-size."}));
continue;
}
if (!config->slave_serve_stale_data && srv_->IsSlave() && cmd_name !=
"info" && cmd_name != "slaveof" &&
srv_->GetReplicationState() != kReplConnected) {
- Reply(
- redis::Error("MASTERDOWN Link with MASTER is down "
- "and slave-serve-stale-data is set to 'no'."));
+ Reply(redis::Error({Status::RedisMasterDown,
+ "Link with MASTER is down "
+ "and slave-serve-stale-data is set to 'no'."}));
continue;
}
@@ -585,7 +585,7 @@ void Connection::ExecuteCommands(std::deque<CommandTokens>
*to_process_cmds) {
// Reply for MULTI
if (!s.IsOK()) {
- Reply(redis::Error("ERR " + s.Msg()));
+ Reply(redis::Error(s));
continue;
}
diff --git a/src/server/redis_reply.cc b/src/server/redis_reply.cc
index d2143b6a..20e15e51 100644
--- a/src/server/redis_reply.cc
+++ b/src/server/redis_reply.cc
@@ -20,15 +20,37 @@
#include "redis_reply.h"
+#include <map>
#include <numeric>
+const std::map<Status::Code, std::string> redisErrorPrefixMapping = {
+ {Status::RedisErrorNoPrefix, ""}, {Status::RedisNoProto,
"NOPROTO"},
+ {Status::RedisLoading, "LOADING"}, {Status::RedisMasterDown,
"MASTERDOWN"},
+ {Status::RedisNoScript, "NOSCRIPT"}, {Status::RedisNoAuth, "NOAUTH"},
+ {Status::RedisWrongType, "WRONGTYPE"}, {Status::RedisReadOnly,
"READONLY"},
+ {Status::RedisExecAbort, "EXECABORT"}, {Status::RedisMoved, "MOVED"},
+ {Status::RedisCrossSlot, "CROSSSLOT"}, {Status::RedisTryAgain,
"TRYAGAIN"},
+ {Status::RedisClusterDown, "CLUSTERDOWN"}};
+
namespace redis {
void Reply(evbuffer *output, const std::string &data) { evbuffer_add(output,
data.c_str(), data.length()); }
std::string SimpleString(const std::string &data) { return "+" + data + CRLF; }
-std::string Error(const std::string &err) { return "-" + err + CRLF; }
+std::string Error(const Status &s) { return RESP_PREFIX_ERROR +
StatusToRedisErrorMsg(s) + CRLF; }
+
+std::string StatusToRedisErrorMsg(const Status &s) {
+ CHECK(!s.IsOK());
+ std::string prefix = "ERR";
+ if (auto it = redisErrorPrefixMapping.find(s.GetCode()); it !=
redisErrorPrefixMapping.end()) {
+ prefix = it->second;
+ }
+ if (prefix.empty()) {
+ return s.Msg();
+ }
+ return prefix + " " + s.Msg();
+}
std::string BulkString(const std::string &data) { return "$" +
std::to_string(data.length()) + CRLF + data + CRLF; }
diff --git a/src/server/redis_reply.h b/src/server/redis_reply.h
index c7fd3b2a..f50c559d 100644
--- a/src/server/redis_reply.h
+++ b/src/server/redis_reply.h
@@ -25,6 +25,8 @@
#include <string>
#include <vector>
+#include "status.h"
+
#define CRLF "\r\n" // NOLINT
#define RESP_PREFIX_ERROR "-" // NOLINT
#define RESP_PREFIX_SIMPLE_STRING "+" // NOLINT
@@ -35,7 +37,9 @@ enum class RESP { v2, v3 };
void Reply(evbuffer *output, const std::string &data);
std::string SimpleString(const std::string &data);
-std::string Error(const std::string &err);
+
+std::string Error(const Status &s);
+std::string StatusToRedisErrorMsg(const Status &s);
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
std::string Integer(T data) {
diff --git a/src/server/worker.cc b/src/server/worker.cc
index 1e8fed37..22054e1f 100644
--- a/src/server/worker.cc
+++ b/src/server/worker.cc
@@ -167,7 +167,7 @@ void Worker::newTCPConnection(evconnlistener *listener,
evutil_socket_t fd, sock
s = AddConnection(conn);
if (!s.IsOK()) {
- std::string err_msg = redis::Error("ERR " + s.Msg());
+ std::string err_msg = redis::Error({Status::NotOK, s.Msg()});
s = util::SockSend(fd, err_msg, ssl);
if (!s.IsOK()) {
LOG(WARNING) << "Failed to send error response to socket: " << s.Msg();
@@ -200,8 +200,7 @@ void Worker::newUnixSocketConnection(evconnlistener
*listener, evutil_socket_t f
auto s = AddConnection(conn);
if (!s.IsOK()) {
- std::string err_msg = redis::Error("ERR " + s.Msg());
- s = util::SockSend(fd, err_msg);
+ s = util::SockSend(fd, redis::Error(s));
if (!s.IsOK()) {
LOG(WARNING) << "Failed to send error response to socket: " << s.Msg();
}
diff --git a/src/storage/rdb.cc b/src/storage/rdb.cc
index f513caca..31c56f00 100644
--- a/src/storage/rdb.cc
+++ b/src/storage/rdb.cc
@@ -688,9 +688,9 @@ Status RDB::Dump(const std::string &key, const RedisType
type) {
/* Serialize the object in an RDB-like format. It consist of an object type
* byte followed by the serialized object. This is understood by RESTORE. */
auto s = SaveObjectType(type);
- if (!s.IsOK()) return {Status::RedisExecErr, s.Msg()};
+ if (!s.IsOK()) return s;
s = SaveObject(key, type);
- if (!s.IsOK()) return {Status::RedisExecErr, s.Msg()};
+ if (!s.IsOK()) return s;
/* Write the footer, this is how it looks like:
* ----------------+---------------------+---------------+
@@ -705,21 +705,14 @@ Status RDB::Dump(const std::string &key, const RedisType
type) {
buf[0] = MinRDBVersion & 0xff;
buf[1] = (MinRDBVersion >> 8) & 0xff;
s = stream_->Write((const char *)buf, 2);
- if (!s.IsOK()) {
- return {Status::RedisExecErr, s.Msg()};
- }
+ if (!s.IsOK()) return s;
/* CRC64 */
CHECK(dynamic_cast<RdbStringStream *>(stream_.get()) != nullptr);
std::string &output = static_cast<RdbStringStream
*>(stream_.get())->GetInput();
uint64_t crc = crc64(0, (unsigned char *)(output.c_str()), output.length());
memrev64ifbe(&crc);
- s = stream_->Write((const char *)(&crc), 8);
- if (!s.IsOK()) {
- return {Status::RedisExecErr, s.Msg()};
- }
-
- return Status::OK();
+ return stream_->Write((const char *)(&crc), 8);
}
Status RDB::SaveObjectType(const RedisType type) {
@@ -797,48 +790,28 @@ Status RDB::RdbSaveLen(uint64_t len) {
if (len < (1 << 6)) {
/* Save a 6 bit len */
buf[0] = (len & 0xFF) | (RDB6BitLen << 6);
- auto status = stream_->Write((const char *)buf, 1);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
- return Status::OK();
+ return stream_->Write((const char *)buf, 1);
} else if (len < (1 << 14)) {
/* Save a 14 bit len */
buf[0] = ((len >> 8) & 0xFF) | (RDB14BitLen << 6);
buf[1] = len & 0xFF;
- auto status = stream_->Write((const char *)buf, 2);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
- return Status::OK();
+ return stream_->Write((const char *)buf, 2);
} else if (len <= UINT32_MAX) {
/* Save a 32 bit len */
buf[0] = RDB32BitLen;
auto status = stream_->Write((const char *)buf, 1);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
uint32_t len32 = htonl(len);
- status = stream_->Write((const char *)(&len32), 4);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
- return Status::OK();
+ return stream_->Write((const char *)(&len32), 4);
} else {
/* Save a 64 bit len */
buf[0] = RDB64BitLen;
auto status = stream_->Write((const char *)buf, 1);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
len = htonu64(len);
- status = stream_->Write((const char *)(&len), 8);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
- return Status::OK();
+ return stream_->Write((const char *)(&len), 8);
}
}
@@ -857,11 +830,7 @@ Status RDB::SaveStringObject(const std::string &value) {
// encode integer
enclen = rdbEncodeInteger(integer_value, buf);
if (enclen > 0) {
- auto status = stream_->Write((const char *)buf, enclen);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
- return Status::OK();
+ return stream_->Write((const char *)buf, enclen);
}
}
}
@@ -871,14 +840,9 @@ Status RDB::SaveStringObject(const std::string &value) {
/* Store verbatim */
auto status = RdbSaveLen(value.length());
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
if (value.length() > 0) {
- status = stream_->Write(value.c_str(), value.length());
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ return stream_->Write(value.c_str(), value.length());
}
return Status::OK();
}
@@ -886,15 +850,11 @@ Status RDB::SaveStringObject(const std::string &value) {
Status RDB::SaveListObject(const std::vector<std::string> &elems) {
if (elems.size() > 0) {
auto status = RdbSaveLen(elems.size());
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
for (const auto &elem : elems) {
auto status = rdbSaveZipListObject(elem);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
}
} else {
LOG(WARNING) << "the size of elems is zero";
@@ -906,15 +866,11 @@ Status RDB::SaveListObject(const std::vector<std::string>
&elems) {
Status RDB::SaveSetObject(const std::vector<std::string> &members) {
if (members.size() > 0) {
auto status = RdbSaveLen(members.size());
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
for (const auto &elem : members) {
status = SaveStringObject(elem);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
}
} else {
LOG(WARNING) << "the size of elems is zero";
@@ -926,20 +882,14 @@ Status RDB::SaveSetObject(const std::vector<std::string>
&members) {
Status RDB::SaveZSetObject(const std::vector<MemberScore> &member_scores) {
if (member_scores.size() > 0) {
auto status = RdbSaveLen(member_scores.size());
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
for (const auto &elem : member_scores) {
status = SaveStringObject(elem.member);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
status = rdbSaveBinaryDoubleValue(elem.score);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
}
} else {
LOG(WARNING) << "the size of member_scores is zero";
@@ -951,20 +901,14 @@ Status RDB::SaveZSetObject(const std::vector<MemberScore>
&member_scores) {
Status RDB::SaveHashObject(const std::vector<FieldValue> &field_values) {
if (field_values.size() > 0) {
auto status = RdbSaveLen(field_values.size());
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
for (const auto &p : field_values) {
status = SaveStringObject(p.field);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
status = SaveStringObject(p.value);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
+ if (!status.IsOK()) return status;
}
} else {
LOG(WARNING) << "the size of field_values is zero";
@@ -1024,10 +968,5 @@ Status RDB::rdbSaveZipListObject(const std::string &elem)
{
ZipList::SetZipListLength(zl_ptr, ziplist_size, 1);
zl_ptr[ziplist_size - 1] = zlEnd;
- auto status = SaveStringObject(zl_string);
- if (!status.IsOK()) {
- return {Status::RedisExecErr, status.Msg()};
- }
-
- return Status::OK();
+ return SaveStringObject(zl_string);
}
diff --git a/src/storage/scripting.cc b/src/storage/scripting.cc
index 409d5e19..5197eb5c 100644
--- a/src/storage/scripting.cc
+++ b/src/storage/scripting.cc
@@ -611,8 +611,7 @@ Status EvalGenericCommand(redis::Connection *conn, const
std::string &body_or_sh
auto s = srv->ScriptGet(funcname + 2, &body);
if (!s.IsOK()) {
lua_pop(lua, 1); /* remove the error handler from the stack. */
- *output = redis::Error(redis::errNoMatchingScript);
- return Status::OK();
+ return {Status::RedisNoScript, redis::errNoMatchingScript};
}
} else {
body = body_or_sha;
@@ -640,8 +639,8 @@ Status EvalGenericCommand(redis::Connection *conn, const
std::string &body_or_sh
SetGlobalArray(lua, "ARGV", argv);
if (lua_pcall(lua, 0, 1, -2)) {
- auto msg = fmt::format("ERR running script (call to {}): {}", funcname,
lua_tostring(lua, -1));
- *output = redis::Error(msg);
+ auto msg = fmt::format("running script (call to {}): {}", funcname,
lua_tostring(lua, -1));
+ *output = redis::Error({Status::NotOK, msg});
lua_pop(lua, 2);
} else {
*output = ReplyToRedisReply(conn, lua);
@@ -755,7 +754,7 @@ int RedisGenericCommand(lua_State *lua, int raise_error) {
if (config->cluster_enabled) {
auto s = srv->cluster->CanExecByMySelf(attributes, args, conn);
if (!s.IsOK()) {
- PushError(lua, s.Msg().c_str());
+ PushError(lua, redis::StatusToRedisErrorMsg(s).c_str());
return raise_error ? RaiseError(lua) : 1;
}
}
@@ -1192,7 +1191,7 @@ std::string ReplyToRedisReply(redis::Connection *conn,
lua_State *lua) {
lua_rawget(lua, -2);
t = lua_type(lua, -1);
if (t == LUA_TSTRING) {
- output = redis::Error(lua_tostring(lua, -1));
+ output = redis::Error({Status::RedisErrorNoPrefix, lua_tostring(lua,
-1)});
lua_pop(lua, 1);
return output;
}
diff --git a/src/types/json.h b/src/types/json.h
index 0ce88797..13abb5cc 100644
--- a/src/types/json.h
+++ b/src/types/json.h
@@ -238,7 +238,7 @@ struct JsonValue {
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
- if (!s) return {Status::NotOK, s.Msg()};
+ if (!s) return s;
return results;
}