Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the command hello #881

Merged
merged 10 commits into from
Sep 18, 2022
47 changes: 47 additions & 0 deletions src/redis_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4132,6 +4132,52 @@ class CommandEcho : public Commander {
}
};

class CommandHello final : public Commander {
public:
Status Execute(Server *svr, Connection *conn, std::string *output) override {
std::cout << "Execute is called" << std::endl;
if (args_.size() == 2) {
int64_t protocol;
try {
protocol = std::stoll(args_[1]);
} catch (std::exception& e) {
// std::invalid_argument or std::out_of_range
*output = Redis::Error("Protocol version is not an integer or out of range");
return Status::OK();
}

// In redis, it will check protocol < 2 or protocol > 3,
// but kvrocks only supports REPL2 by now.
if (protocol != 2) {
*output = Redis::Error("-NOPROTO unsupported protocol version");
return Status::OK();
}
}

// TODO(mapleFU): do we need to implement auth and setname?

std::vector<std::string> output_list;
output_list.push_back(Redis::BulkString("server"));
output_list.push_back(Redis::BulkString("redis"));
output_list.push_back(Redis::BulkString("version"));
output_list.push_back(Redis::BulkString("")); // TODO(mapleFU): change it to the real redis version
output_list.push_back(Redis::BulkString("proto"));
output_list.push_back(Redis::Integer(2));
output_list.push_back(Redis::BulkString("id"));
output_list.push_back(Redis::Integer(2)); // TODO(mapleFU): fix this

output_list.push_back(Redis::BulkString("mode"));
// Note: sentinel is not supported.
if (svr->GetConfig()->cluster_enabled) {
output_list.push_back(Redis::BulkString("cluster"));
} else {
output_list.push_back(Redis::BulkString("standalone"));
}
*output = Redis::Array(output_list);
return Status::OK();
}
};

class CommandScanBase : public Commander {
public:
Status ParseMatchAndCountParam(const std::string &type, std::string value) {
Expand Down Expand Up @@ -5680,6 +5726,7 @@ CommandAttributes redisCommandTable[] = {
ADD_CMD("debug", -2, "read-only exclusive", 0, 0, 0, CommandDebug),
ADD_CMD("command", -1, "read-only", 0, 0, 0, CommandCommand),
ADD_CMD("echo", 2, "read-only", 0, 0, 0, CommandEcho),
ADD_CMD("hello", -1, "read-only", 0, 0, 0, CommandHello),

ADD_CMD("ttl", 2, "read-only", 1, 1, 1, CommandTTL),
ADD_CMD("pttl", 2, "read-only", 1, 1, 1, CommandPTTL),
Expand Down
29 changes: 18 additions & 11 deletions src/redis_reply.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,36 +45,43 @@ std::string MultiLen(int64_t len) {
return "*"+std::to_string(len)+"\r\n";
}

std::string MultiBulkString(std::vector<std::string> values, bool output_nil_for_empty_string) {
std::string MultiBulkString(const std::vector<std::string>& values, bool output_nil_for_empty_string) {
std::vector<std::string> copiedStrings;
copiedStrings.resize(values.size());
for (size_t i = 0; i < values.size(); i++) {
if (values[i].empty() && output_nil_for_empty_string) {
values[i] = NilString();
copiedStrings[i] = NilString();
} else {
values[i] = BulkString(values[i]);
copiedStrings[i] = BulkString(values[i]);
}
}
return Array(values);
return Array(copiedStrings);
}


std::string MultiBulkString(std::vector<std::string> values, const std::vector<rocksdb::Status> &statuses) {
std::string MultiBulkString(const std::vector<std::string>& values, const std::vector<rocksdb::Status> &statuses) {
std::vector<std::string> copiedStrings;
copiedStrings.resize(values.size());
for (size_t i = 0; i < values.size(); i++) {
if (i < statuses.size() && !statuses[i].ok()) {
values[i] = NilString();
copiedStrings[i] = NilString();
} else {
values[i] = BulkString(values[i]);
copiedStrings[i] = BulkString(values[i]);
}
}
return Array(values);
return Array(copiedStrings);
}
std::string Array(std::vector<std::string> list) {

std::string Array(const std::vector<std::string>& list) {
std::string::size_type n = std::accumulate(
list.begin(), list.end(), std::string::size_type(0),
[] ( std::string::size_type n, const std::string &s ) { return ( n += s.size() ); });
std::string result = "*" + std::to_string(list.size()) + CRLF;
result.reserve(n);
return std::accumulate(list.begin(), list.end(), result,
std::string::size_type final_size = result.size() + n;
result.reserve(final_size);
auto s = std::accumulate(list.begin(), list.end(), result,
[](std::string &dest, std::string const &item) -> std::string& {dest += item; return dest;});
return s;
}

std::string Command2RESP(const std::vector<std::string> &cmd_args) {
Expand Down
6 changes: 3 additions & 3 deletions src/redis_reply.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ std::string Integer(int64_t data);
std::string BulkString(const std::string &data);
std::string NilString();
std::string MultiLen(int64_t len);
std::string Array(std::vector<std::string> list);
std::string MultiBulkString(std::vector<std::string> values, bool output_nil_for_empty_string = true);
std::string MultiBulkString(std::vector<std::string> values, const std::vector<rocksdb::Status> &statuses);
std::string Array(const std::vector<std::string>& list);
std::string MultiBulkString(const std::vector<std::string>& values, bool output_nil_for_empty_string = true);
std::string MultiBulkString(const std::vector<std::string>& values, const std::vector<rocksdb::Status> &statuses);
std::string Command2RESP(const std::vector<std::string> &cmd_args);
} // namespace Redis
4 changes: 2 additions & 2 deletions src/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ Status DecimalStringToNum(const std::string &str, int64_t *n, int64_t min, int64
try {
*n = static_cast<int64_t>(std::stoll(str));
if (max > min && (*n < min || *n > max)) {
return Status(Status::NotOK, "value shoud between "+std::to_string(min)+" and "+std::to_string(max));
return Status(Status::NotOK, "value should between "+std::to_string(min)+" and "+std::to_string(max));
}
} catch (std::exception &e) {
return Status(Status::NotOK, "value is not an integer or out of range");
Expand All @@ -356,7 +356,7 @@ Status OctalStringToNum(const std::string &str, int64_t *n, int64_t min, int64_t
try {
*n = static_cast<int64_t>(std::stoll(str, nullptr, 8));
if (max > min && (*n < min || *n > max)) {
return Status(Status::NotOK, "value shoud between "+std::to_string(min)+" and "+std::to_string(max));
return Status(Status::NotOK, "value should between "+std::to_string(min)+" and "+std::to_string(max));
}
} catch (std::exception &e) {
return Status(Status::NotOK, "value is not an integer or out of range");
Expand Down