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

chore(resp): extract RESP functions from Connection #2406

Merged
merged 4 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 0 additions & 52 deletions src/server/redis_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,58 +133,6 @@ void Connection::Reply(const std::string &msg) {
redis::Reply(bufferevent_get_output(bev_), msg);
}

std::string Connection::Bool(bool b) const {
if (protocol_version_ == RESP::v3) {
return b ? "#t" CRLF : "#f" CRLF;
}
return Integer(b ? 1 : 0);
}

std::string Connection::MultiBulkString(const std::vector<std::string> &values) const {
std::string result = MultiLen(values.size());
for (const auto &value : values) {
if (value.empty()) {
result += NilString();
} else {
result += BulkString(value);
}
}
return result;
}

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

std::string Connection::SetOfBulkStrings(const std::vector<std::string> &elems) const {
std::string result;
result += HeaderOfSet(elems.size());
for (const auto &elem : elems) {
result += BulkString(elem);
}
return result;
}

std::string Connection::MapOfBulkStrings(const std::vector<std::string> &elems) const {
CHECK(elems.size() % 2 == 0);

std::string result;
result += HeaderOfMap(elems.size() / 2);
for (const auto &elem : elems) {
result += BulkString(elem);
}
return result;
}

void Connection::SendFile(int fd) {
// NOTE: we don't need to close the fd, the libevent will do that
auto output = bufferevent_get_output(bev_);
Expand Down
49 changes: 22 additions & 27 deletions src/server/redis_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "commands/commander.h"
#include "event_util.h"
#include "redis_request.h"
#include "server/redis_reply.h"

class Worker;

Expand Down Expand Up @@ -66,46 +67,40 @@ class Connection : public EvbufCallbackBase<Connection> {
void Reply(const std::string &msg);
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 Double(double d) const {
return protocol_version_ == RESP::v3 ? "," + util::Float2String(d) + CRLF : BulkString(util::Float2String(d));
}
// ext is the extension of file to send, 'txt' for text file, 'md ' for markdown file
// at most 3 chars, padded with space
// if RESP is V2, treat verbatim string as blob string
// https://github.com/redis/redis/blob/7.2/src/networking.c#L1099
std::string Bool(bool b) const { return redis::Bool(protocol_version_, b); }
std::string BigNumber(const std::string &n) const { return redis::BigNumber(protocol_version_, n); }
std::string Double(double d) const { return redis::Double(protocol_version_, d); }
std::string VerbatimString(std::string ext, const std::string &data) const {
CHECK(ext.size() <= 3);
size_t padded_len = 3 - ext.size();
ext = ext + std::string(padded_len, ' ');
return protocol_version_ == RESP::v3 ? "=" + std::to_string(3 + 1 + data.size()) + CRLF + ext + ":" + data + CRLF
: BulkString(data);
return redis::VerbatimString(protocol_version_, std::move(ext), data);
}
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) const;
std::string NilArray() const { return redis::NilArray(protocol_version_); }
std::string MultiBulkString(const std::vector<std::string> &values) const {
return redis::MultiBulkString(protocol_version_, values);
}
std::string MultiBulkString(const std::vector<std::string> &values,
const std::vector<rocksdb::Status> &statuses) const;
const std::vector<rocksdb::Status> &statuses) const {
return redis::MultiBulkString(protocol_version_, values, statuses);
}
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
std::string HeaderOfSet(T len) const {
return protocol_version_ == RESP::v3 ? "~" + std::to_string(len) + CRLF : MultiLen(len);
return redis::HeaderOfSet(protocol_version_, len);
}
std::string SetOfBulkStrings(const std::vector<std::string> &elems) const {
return redis::SetOfBulkStrings(protocol_version_, elems);
}
std::string SetOfBulkStrings(const std::vector<std::string> &elems) const;
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
std::string HeaderOfMap(T len) const {
return protocol_version_ == RESP::v3 ? "%" + std::to_string(len) + CRLF : MultiLen(len * 2);
return redis::HeaderOfMap(protocol_version_, len);
}
std::string MapOfBulkStrings(const std::vector<std::string> &elems) const {
return redis::MapOfBulkStrings(protocol_version_, elems);
}
std::string MapOfBulkStrings(const std::vector<std::string> &elems) const;
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
std::string HeaderOfAttribute(T len) const {
return "|" + std::to_string(len) + CRLF;
}
std::string HeaderOfPush(int64_t len) const {
return protocol_version_ == RESP::v3 ? ">" + std::to_string(len) + CRLF : MultiLen(len);
return redis::HeaderOfAttribute(len);
}
std::string HeaderOfPush(int64_t len) const { return redis::HeaderOfPush(protocol_version_, len); }

using UnsubscribeCallback = std::function<void(std::string, int)>;
void SubscribeChannel(const std::string &channel);
Expand Down
52 changes: 52 additions & 0 deletions src/server/redis_reply.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,56 @@ std::string ArrayOfBulkStrings(const std::vector<std::string> &elems) {
return result;
}

std::string Bool(RESP ver, bool b) {
if (ver == RESP::v3) {
return b ? "#t" CRLF : "#f" CRLF;
}
return Integer(b ? 1 : 0);
}

std::string MultiBulkString(RESP ver, const std::vector<std::string> &values) {
std::string result = MultiLen(values.size());
for (const auto &value : values) {
if (value.empty()) {
result += NilString(ver);
} else {
result += BulkString(value);
}
}
return result;
}

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

std::string SetOfBulkStrings(RESP ver, const std::vector<std::string> &elems) {
std::string result;
result += HeaderOfSet(ver, elems.size());
for (const auto &elem : elems) {
result += BulkString(elem);
}
return result;
}

std::string MapOfBulkStrings(RESP ver, const std::vector<std::string> &elems) {
CHECK(elems.size() % 2 == 0);

std::string result;
result += HeaderOfMap(ver, elems.size() / 2);
for (const auto &elem : elems) {
result += BulkString(elem);
}
return result;
}

} // namespace redis
47 changes: 46 additions & 1 deletion src/server/redis_reply.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
#include <string>
#include <vector>

#include "rocksdb/status.h"
#include "status.h"
#include "string_util.h"

#define CRLF "\r\n" // NOLINT
#define RESP_PREFIX_ERROR "-" // NOLINT
Expand All @@ -46,7 +48,7 @@ std::string Integer(T data) {
return ":" + std::to_string(data) + CRLF;
}

inline std::string NilString(const RESP ver) {
inline std::string NilString(RESP ver) {
if (ver == RESP::v3) {
return "_" CRLF;
}
Expand All @@ -63,4 +65,47 @@ std::string MultiLen(T len) {
std::string Array(const std::vector<std::string> &list);
std::string ArrayOfBulkStrings(const std::vector<std::string> &elements);

std::string Bool(RESP ver, bool b);
inline std::string BigNumber(RESP ver, const std::string &n) {
return ver == RESP::v3 ? "(" + n + CRLF : BulkString(n);
}
inline std::string Double(RESP ver, double d) {
return ver == RESP::v3 ? "," + util::Float2String(d) + CRLF : BulkString(util::Float2String(d));
}
// ext is the extension of file to send, 'txt' for text file, 'md ' for markdown file
// at most 3 chars, padded with space
// if RESP is V2, treat verbatim string as blob string
// https://github.com/redis/redis/blob/7.2/src/networking.c#L1099
inline std::string VerbatimString(RESP ver, std::string ext, const std::string &data) {
CHECK(ext.size() <= 3);
size_t padded_len = 3 - ext.size();
ext = ext + std::string(padded_len, ' ');
return ver == RESP::v3 ? "=" + std::to_string(3 + 1 + data.size()) + CRLF + ext + ":" + data + CRLF
: BulkString(data);
}

inline std::string NilArray(RESP ver) { return ver == RESP::v3 ? "_" CRLF : "*-1" CRLF; }
std::string MultiBulkString(RESP ver, const std::vector<std::string> &values);
std::string MultiBulkString(RESP ver, const std::vector<std::string> &values,
const std::vector<rocksdb::Status> &statuses);

template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
std::string HeaderOfSet(RESP ver, T len) {
return ver == RESP::v3 ? "~" + std::to_string(len) + CRLF : MultiLen(len);
}
std::string SetOfBulkStrings(RESP ver, const std::vector<std::string> &elems);
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
std::string HeaderOfMap(RESP ver, T len) {
return ver == RESP::v3 ? "%" + std::to_string(len) + CRLF : MultiLen(len * 2);
}
std::string MapOfBulkStrings(RESP ver, const std::vector<std::string> &elems);
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
std::string HeaderOfAttribute(T len) {
return "|" + std::to_string(len) + CRLF;
}
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
std::string HeaderOfPush(RESP ver, T len) {
return ver == RESP::v3 ? ">" + std::to_string(len) + CRLF : MultiLen(len);
}

} // namespace redis
Loading