Skip to content

Commit

Permalink
chore(resp): extract RESP functions from Connection (#2406)
Browse files Browse the repository at this point in the history
  • Loading branch information
PragmaTwice authored Jul 13, 2024
1 parent 3206206 commit ffdce20
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 80 deletions.
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

0 comments on commit ffdce20

Please sign in to comment.