mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 10:25:47 +02:00
refactor(facade): Refactor reply builder (#991)
Refactor RedisReplyBuilder to simplify method overloads
This commit is contained in:
parent
ef4062d817
commit
72f67eddd8
12 changed files with 144 additions and 203 deletions
|
@ -160,6 +160,14 @@ void MCReplyBuilder::SendNotFound() {
|
|||
SendSimpleString("NOT_FOUND");
|
||||
}
|
||||
|
||||
size_t RedisReplyBuilder::WrappedStrSpan::Size() const {
|
||||
return visit([](auto arr) { return arr.size(); }, (const StrSpan&)*this);
|
||||
}
|
||||
|
||||
string_view RedisReplyBuilder::WrappedStrSpan::operator[](size_t i) const {
|
||||
return visit([i](auto arr) { return string_view{arr[i]}; }, (const StrSpan&)*this);
|
||||
}
|
||||
|
||||
char* RedisReplyBuilder::FormatDouble(double val, char* dest, unsigned dest_len) {
|
||||
StringBuilder sb(dest, dest_len);
|
||||
CHECK(dfly_conv.ToShortest(val, &sb));
|
||||
|
@ -329,12 +337,11 @@ void RedisReplyBuilder::SendMGetResponse(const OptResp* resp, uint32_t count) {
|
|||
SendRaw(res);
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::SendSimpleStrArr(const std::string_view* arr, uint32_t count) {
|
||||
string res = absl::StrCat("*", count, kCRLF);
|
||||
void RedisReplyBuilder::SendSimpleStrArr(absl::Span<const std::string_view> arr) {
|
||||
string res = absl::StrCat("*", arr.size(), kCRLF);
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
StrAppend(&res, "+", arr[i], kCRLF);
|
||||
}
|
||||
for (auto sv : arr)
|
||||
StrAppend(&res, "+", sv, kCRLF);
|
||||
|
||||
SendRaw(res);
|
||||
}
|
||||
|
@ -347,13 +354,33 @@ void RedisReplyBuilder::SendEmptyArray() {
|
|||
StartArray(0);
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::SendStringArr(absl::Span<const std::string_view> arr) {
|
||||
if (arr.empty()) {
|
||||
void RedisReplyBuilder::SendStringArr(StrSpan arr, CollectionType type) {
|
||||
WrappedStrSpan warr{arr};
|
||||
|
||||
if (type == ARRAY && warr.Size() == 0) {
|
||||
SendRaw("*0\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SendStringCollection(arr.data(), arr.size(), CollectionType::ARRAY);
|
||||
SendStringArrInternal(warr, type);
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::StartArray(unsigned len) {
|
||||
StartCollection(len, ARRAY);
|
||||
}
|
||||
|
||||
constexpr static string_view START_SYMBOLS[] = {"*", "~", "%"};
|
||||
static_assert(START_SYMBOLS[RedisReplyBuilder::MAP] == "%" &&
|
||||
START_SYMBOLS[RedisReplyBuilder::SET] == "~");
|
||||
|
||||
void RedisReplyBuilder::StartCollection(unsigned len, CollectionType type) {
|
||||
if (!is_resp3_) { // Flatten for Resp2
|
||||
if (type == MAP)
|
||||
len *= 2;
|
||||
type = ARRAY;
|
||||
}
|
||||
|
||||
SendRaw(absl::StrCat(START_SYMBOLS[type], len, kCRLF));
|
||||
}
|
||||
|
||||
// This implementation a bit complicated because it uses vectorized
|
||||
|
@ -361,62 +388,15 @@ void RedisReplyBuilder::SendStringArr(absl::Span<const std::string_view> arr) {
|
|||
// to low numbers (around 1024). Therefore, to make it robust we send the array in batches.
|
||||
// We limit the vector length to 256 and when it fills up we flush it to the socket and continue
|
||||
// iterating.
|
||||
void RedisReplyBuilder::SendStringArr(absl::Span<const string> arr) {
|
||||
SendStringCollection(arr.data(), arr.size(), CollectionType::ARRAY);
|
||||
}
|
||||
void RedisReplyBuilder::SendStringArrInternal(WrappedStrSpan arr, CollectionType type) {
|
||||
size_t size = arr.Size();
|
||||
|
||||
void RedisReplyBuilder::SendStringArrayAsMap(absl::Span<const std::string_view> arr) {
|
||||
SendStringCollection(arr.data(), arr.size(), CollectionType::MAP);
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::SendStringArrayAsMap(absl::Span<const std::string> arr) {
|
||||
SendStringCollection(arr.data(), arr.size(), CollectionType::MAP);
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::SendStringArrayAsSet(absl::Span<const std::string_view> arr) {
|
||||
SendStringCollection(arr.data(), arr.size(), CollectionType::SET);
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::SendStringArrayAsSet(absl::Span<const std::string> arr) {
|
||||
SendStringCollection(arr.data(), arr.size(), CollectionType::SET);
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::StartArray(unsigned len) {
|
||||
SendRaw(absl::StrCat("*", len, kCRLF));
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::StartMap(unsigned num_pairs) {
|
||||
size_t header_len = size;
|
||||
string_view type_char = "*";
|
||||
if (is_resp3_) {
|
||||
SendRaw(absl::StrCat("%", num_pairs, kCRLF));
|
||||
return;
|
||||
}
|
||||
// Flatten for Resp2.
|
||||
StartArray(num_pairs * 2);
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::StartSet(unsigned num_elements) {
|
||||
if (is_resp3_) {
|
||||
SendRaw(absl::StrCat("~", num_elements, kCRLF));
|
||||
}
|
||||
// Flatten for Resp2.
|
||||
StartArray(num_elements);
|
||||
}
|
||||
|
||||
void RedisReplyBuilder::SendStringCollection(StrPtr str_ptr, uint32_t len, CollectionType type) {
|
||||
string type_char = "*";
|
||||
size_t header_len = len;
|
||||
if (is_resp3_) {
|
||||
switch (type) {
|
||||
case CollectionType::ARRAY:
|
||||
break;
|
||||
case CollectionType::MAP:
|
||||
type_char[0] = '%';
|
||||
header_len = 0.5 * len; // Each key value pair counts as one.
|
||||
break;
|
||||
case CollectionType::SET:
|
||||
type_char[0] = '~';
|
||||
break;
|
||||
}
|
||||
type_char = START_SYMBOLS[type];
|
||||
if (type == MAP)
|
||||
header_len /= 2; // Each key value pair counts as one.
|
||||
}
|
||||
|
||||
if (header_len == 0) {
|
||||
|
@ -425,7 +405,7 @@ void RedisReplyBuilder::SendStringCollection(StrPtr str_ptr, uint32_t len, Colle
|
|||
}
|
||||
|
||||
// When vector length is too long, Send returns EMSGSIZE.
|
||||
size_t vec_len = std::min<size_t>(256u, len);
|
||||
size_t vec_len = std::min<size_t>(256u, size);
|
||||
|
||||
absl::FixedArray<iovec, 16> vec(vec_len * 2 + 2);
|
||||
absl::FixedArray<char, 64> meta((vec_len + 1) * 16);
|
||||
|
@ -440,12 +420,8 @@ void RedisReplyBuilder::SendStringCollection(StrPtr str_ptr, uint32_t len, Colle
|
|||
|
||||
unsigned vec_indx = 1;
|
||||
string_view src;
|
||||
for (unsigned i = 0; i < len; ++i) {
|
||||
if (holds_alternative<const string_view*>(str_ptr)) {
|
||||
src = get<const string_view*>(str_ptr)[i];
|
||||
} else {
|
||||
src = get<const string*>(str_ptr)[i];
|
||||
}
|
||||
for (unsigned i = 0; i < size; ++i) {
|
||||
src = arr[i];
|
||||
*next++ = '$';
|
||||
next = absl::numbers_internal::FastIntToBuffer(src.size(), next);
|
||||
*next++ = '\r';
|
||||
|
@ -463,7 +439,7 @@ void RedisReplyBuilder::SendStringCollection(StrPtr str_ptr, uint32_t len, Colle
|
|||
++vec_indx;
|
||||
|
||||
if (vec_indx + 1 >= vec.size()) {
|
||||
if (i < len - 1 || vec_indx == vec.size()) {
|
||||
if (i < size - 1 || vec_indx == vec.size()) {
|
||||
Send(vec.data(), vec_indx);
|
||||
if (ec_)
|
||||
return;
|
||||
|
|
|
@ -12,6 +12,16 @@
|
|||
namespace facade {
|
||||
|
||||
class SinkReplyBuilder {
|
||||
public:
|
||||
struct ResponseValue {
|
||||
std::string_view key;
|
||||
std::string value;
|
||||
uint64_t mc_ver = 0; // 0 means we do not output it (i.e has not been requested).
|
||||
uint32_t mc_flag = 0;
|
||||
};
|
||||
|
||||
using OptResp = std::optional<ResponseValue>;
|
||||
|
||||
public:
|
||||
SinkReplyBuilder(const SinkReplyBuilder&) = delete;
|
||||
void operator=(const SinkReplyBuilder&) = delete;
|
||||
|
@ -21,6 +31,20 @@ class SinkReplyBuilder {
|
|||
virtual ~SinkReplyBuilder() {
|
||||
}
|
||||
|
||||
virtual void SendError(std::string_view str, std::string_view type = {}) = 0; // MC and Redis
|
||||
|
||||
virtual void SendStored() = 0; // Reply for set commands.
|
||||
virtual void SendSetSkipped() = 0;
|
||||
|
||||
virtual void SendMGetResponse(const OptResp* resp, uint32_t count) = 0;
|
||||
|
||||
virtual void SendLong(long val) = 0;
|
||||
virtual void SendSimpleString(std::string_view str) = 0;
|
||||
|
||||
void SendOk() {
|
||||
SendSimpleString("OK");
|
||||
}
|
||||
|
||||
// In order to reduce interrupt rate we allow coalescing responses together using
|
||||
// Batch mode. It is controlled by Connection state machine because it makes sense only
|
||||
// when pipelined requests are arriving.
|
||||
|
@ -53,36 +77,10 @@ class SinkReplyBuilder {
|
|||
return err_count_;
|
||||
}
|
||||
|
||||
//! Sends a string as is without any formatting. raw should be encoded according to the protocol.
|
||||
void SendRaw(std::string_view str);
|
||||
protected:
|
||||
void SendRaw(std::string_view str); // Sends raw without any formatting.
|
||||
void SendRawVec(absl::Span<const std::string_view> msg_vec);
|
||||
|
||||
// Common for both MC and Redis.
|
||||
virtual void SendError(std::string_view str, std::string_view type = std::string_view{}) = 0;
|
||||
|
||||
virtual void SendSimpleString(std::string_view str) = 0;
|
||||
|
||||
void SendOk() {
|
||||
SendSimpleString("OK");
|
||||
}
|
||||
|
||||
struct ResponseValue {
|
||||
std::string_view key;
|
||||
std::string value;
|
||||
uint64_t mc_ver = 0; // 0 means we do not output it (i.e has not been requested).
|
||||
uint32_t mc_flag = 0;
|
||||
};
|
||||
|
||||
using OptResp = std::optional<ResponseValue>;
|
||||
|
||||
virtual void SendMGetResponse(const OptResp* resp, uint32_t count) = 0;
|
||||
virtual void SendLong(long val) = 0;
|
||||
|
||||
// Reply for set commands.
|
||||
virtual void SendStored() = 0;
|
||||
virtual void SendSetSkipped() = 0;
|
||||
|
||||
protected:
|
||||
void Send(const iovec* v, uint32_t len);
|
||||
|
||||
std::string batch_;
|
||||
|
@ -100,6 +98,8 @@ class MCReplyBuilder : public SinkReplyBuilder {
|
|||
public:
|
||||
MCReplyBuilder(::io::Sink* stream);
|
||||
|
||||
using SinkReplyBuilder::SendRaw;
|
||||
|
||||
void SendError(std::string_view str, std::string_view type = std::string_view{}) final;
|
||||
|
||||
// void SendGetReply(std::string_view key, uint32_t flags, std::string_view value) final;
|
||||
|
@ -116,44 +116,37 @@ class MCReplyBuilder : public SinkReplyBuilder {
|
|||
|
||||
class RedisReplyBuilder : public SinkReplyBuilder {
|
||||
public:
|
||||
enum CollectionType { ARRAY, SET, MAP };
|
||||
|
||||
using StrSpan = std::variant<absl::Span<const std::string>, absl::Span<const std::string_view>>;
|
||||
|
||||
RedisReplyBuilder(::io::Sink* stream);
|
||||
|
||||
void SetResp3(bool is_resp3);
|
||||
|
||||
void SendError(std::string_view str, std::string_view type = std::string_view{}) override;
|
||||
void SendError(std::string_view str, std::string_view type = {}) override;
|
||||
void SendMGetResponse(const OptResp* resp, uint32_t count) override;
|
||||
void SendSimpleString(std::string_view str) override;
|
||||
|
||||
void SendStored() override;
|
||||
void SendLong(long val) override;
|
||||
void SendSetSkipped() override;
|
||||
virtual void SendError(OpStatus status);
|
||||
|
||||
void SendError(OpStatus status);
|
||||
|
||||
virtual void SendSimpleStrArr(const std::string_view* arr, uint32_t count);
|
||||
// Send *-1
|
||||
virtual void SendNullArray();
|
||||
// Send *0
|
||||
virtual void SendEmptyArray();
|
||||
|
||||
virtual void SendStringArr(absl::Span<const std::string_view> arr);
|
||||
virtual void SendStringArr(absl::Span<const std::string> arr);
|
||||
virtual void SendStringArrayAsMap(absl::Span<const std::string_view> arr);
|
||||
virtual void SendStringArrayAsMap(absl::Span<const std::string> arr);
|
||||
virtual void SendStringArrayAsSet(absl::Span<const std::string_view> arr);
|
||||
virtual void SendStringArrayAsSet(absl::Span<const std::string> arr);
|
||||
virtual void SendNullArray(); // Send *-1
|
||||
virtual void SendEmptyArray(); // Send *0
|
||||
virtual void SendSimpleStrArr(absl::Span<const std::string_view> arr);
|
||||
virtual void SendStringArr(StrSpan arr, CollectionType type = ARRAY);
|
||||
|
||||
virtual void SendNull();
|
||||
void SendLong(long val) override;
|
||||
virtual void SendDouble(double val);
|
||||
void SendSimpleString(std::string_view str) override;
|
||||
|
||||
virtual void SendBulkString(std::string_view str);
|
||||
virtual void SendScoredArray(const std::vector<std::pair<std::string, double>>& arr,
|
||||
bool with_scores);
|
||||
|
||||
virtual void SendDouble(double val);
|
||||
|
||||
virtual void SendBulkString(std::string_view str);
|
||||
|
||||
virtual void StartArray(unsigned len);
|
||||
virtual void StartMap(unsigned num_pairs);
|
||||
virtual void StartSet(unsigned num_elements);
|
||||
void StartArray(unsigned len); // StartCollection(len, ARRAY)
|
||||
virtual void StartCollection(unsigned len, CollectionType type);
|
||||
|
||||
static char* FormatDouble(double val, char* dest, unsigned dest_len);
|
||||
|
||||
|
@ -161,18 +154,18 @@ class RedisReplyBuilder : public SinkReplyBuilder {
|
|||
// into the string that would be sent
|
||||
static std::string_view StatusToMsg(OpStatus status);
|
||||
|
||||
private:
|
||||
enum CollectionType {
|
||||
ARRAY,
|
||||
SET,
|
||||
MAP,
|
||||
protected:
|
||||
struct WrappedStrSpan : public StrSpan {
|
||||
size_t Size() const;
|
||||
std::string_view operator[](size_t index) const;
|
||||
};
|
||||
|
||||
using StrPtr = std::variant<const std::string_view*, const std::string*>;
|
||||
void SendStringCollection(StrPtr str_ptr, uint32_t len, CollectionType type);
|
||||
private:
|
||||
void SendStringArrInternal(WrappedStrSpan arr, CollectionType type);
|
||||
|
||||
const char* NullString();
|
||||
|
||||
bool is_resp3_ = false;
|
||||
const char* NullString();
|
||||
};
|
||||
|
||||
class ReqSerializer {
|
||||
|
|
|
@ -357,7 +357,7 @@ TEST_F(RedisReplyBuilderTest, SendSimpleStrArr) {
|
|||
// random values
|
||||
"+++", "---", "$$$", "~~~~", "@@@", "^^^", "1234", "foo"};
|
||||
const std::size_t kArrayLen = sizeof(kArrayMessage) / sizeof(kArrayMessage[0]);
|
||||
builder_->SendSimpleStrArr(kArrayMessage, kArrayLen);
|
||||
builder_->SendSimpleStrArr(kArrayMessage);
|
||||
ASSERT_TRUE(builder_->err_count().empty());
|
||||
// Tokenize the message and verify content
|
||||
std::vector<std::string_view> message_tokens = TokenizeMessage();
|
||||
|
@ -674,13 +674,13 @@ TEST_F(RedisReplyBuilderTest, TestSendStringArrayAsMap) {
|
|||
const std::vector<std::string> map_array{"k1", "v1", "k2", "v2"};
|
||||
|
||||
builder_->SetResp3(false);
|
||||
builder_->SendStringArrayAsMap(map_array);
|
||||
builder_->SendStringArr(map_array, builder_->MAP);
|
||||
ASSERT_TRUE(builder_->err_count().empty());
|
||||
ASSERT_EQ(TakePayload(), "*4\r\n$2\r\nk1\r\n$2\r\nv1\r\n$2\r\nk2\r\n$2\r\nv2\r\n")
|
||||
<< "SendStringArrayAsMap Resp2 Failed.";
|
||||
|
||||
builder_->SetResp3(true);
|
||||
builder_->SendStringArrayAsMap(map_array);
|
||||
builder_->SendStringArr(map_array, builder_->MAP);
|
||||
ASSERT_TRUE(builder_->err_count().empty());
|
||||
ASSERT_EQ(TakePayload(), "%2\r\n$2\r\nk1\r\n$2\r\nv1\r\n$2\r\nk2\r\n$2\r\nv2\r\n")
|
||||
<< "SendStringArrayAsMap Resp3 Failed.";
|
||||
|
@ -690,13 +690,13 @@ TEST_F(RedisReplyBuilderTest, TestSendStringArrayAsSet) {
|
|||
const std::vector<std::string> set_array{"e1", "e2", "e3"};
|
||||
|
||||
builder_->SetResp3(false);
|
||||
builder_->SendStringArrayAsSet(set_array);
|
||||
builder_->SendStringArr(set_array, builder_->SET);
|
||||
ASSERT_TRUE(builder_->err_count().empty());
|
||||
ASSERT_EQ(TakePayload(), "*3\r\n$2\r\ne1\r\n$2\r\ne2\r\n$2\r\ne3\r\n")
|
||||
<< "SendStringArrayAsSet Resp2 Failed.";
|
||||
|
||||
builder_->SetResp3(true);
|
||||
builder_->SendStringArrayAsSet(set_array);
|
||||
builder_->SendStringArr(set_array, builder_->SET);
|
||||
ASSERT_TRUE(builder_->err_count().empty());
|
||||
ASSERT_EQ(TakePayload(), "~3\r\n$2\r\ne1\r\n$2\r\ne2\r\n$2\r\ne3\r\n")
|
||||
<< "SendStringArrayAsSet Resp3 Failed.";
|
||||
|
|
|
@ -117,7 +117,7 @@ void DebugCmd::Run(CmdArgList args) {
|
|||
"HELP",
|
||||
" Prints this help.",
|
||||
};
|
||||
return (*cntx_)->SendSimpleStrArr(help_arr, ABSL_ARRAYSIZE(help_arr));
|
||||
return (*cntx_)->SendSimpleStrArr(help_arr);
|
||||
}
|
||||
|
||||
VLOG(1) << "subcmd " << subcmd;
|
||||
|
|
|
@ -1012,11 +1012,9 @@ void GenericFamily::Sort(CmdArgList args, ConnectionContext* cntx) {
|
|||
end_it = entries.begin() + std::min(bounds->first + bounds->second, entries.size());
|
||||
}
|
||||
|
||||
if (result_type == OBJ_SET || result_type == OBJ_ZSET) {
|
||||
(*cntx)->StartSet(std::distance(start_it, end_it));
|
||||
} else {
|
||||
(*cntx)->StartArray(std::distance(start_it, end_it));
|
||||
}
|
||||
bool is_set = (result_type == OBJ_SET || result_type == OBJ_ZSET);
|
||||
(*cntx)->StartCollection(std::distance(start_it, end_it),
|
||||
is_set ? RedisReplyBuilder::SET : RedisReplyBuilder::ARRAY);
|
||||
|
||||
for (auto it = start_it; it != end_it; ++it) {
|
||||
(*cntx)->SendBulkString(it->key);
|
||||
|
|
|
@ -697,11 +697,9 @@ void HGetGeneric(CmdArgList args, ConnectionContext* cntx, uint8_t getall_mask)
|
|||
OpResult<vector<string>> result = cntx->transaction->ScheduleSingleHopT(std::move(cb));
|
||||
|
||||
if (result) {
|
||||
if (getall_mask == (VALUES | FIELDS)) {
|
||||
(*cntx)->SendStringArrayAsMap(absl::Span<const string>{*result});
|
||||
} else {
|
||||
(*cntx)->SendStringArr(absl::Span<const string>{*result});
|
||||
}
|
||||
bool is_map = (getall_mask == (VALUES | FIELDS));
|
||||
(*cntx)->SendStringArr(absl::Span<const string>{*result},
|
||||
is_map ? RedisReplyBuilder::MAP : RedisReplyBuilder::ARRAY);
|
||||
} else {
|
||||
(*cntx)->SendError(result.status());
|
||||
}
|
||||
|
|
|
@ -206,20 +206,15 @@ class InterpreterReplier : public RedisReplyBuilder {
|
|||
InterpreterReplier(ObjectExplorer* explr) : RedisReplyBuilder(nullptr), explr_(explr) {
|
||||
}
|
||||
|
||||
void SendError(std::string_view str, std::string_view type = std::string_view{}) override;
|
||||
void SendStored() override;
|
||||
void SendError(std::string_view str, std::string_view type = std::string_view{}) final;
|
||||
void SendStored() final;
|
||||
|
||||
void SendSimpleString(std::string_view str) final;
|
||||
void SendMGetResponse(const OptResp* resp, uint32_t count) final;
|
||||
void SendSimpleStrArr(const string_view* arr, uint32_t count) final;
|
||||
void SendStringArrayAsMap(absl::Span<const std::string_view> arr) final;
|
||||
void SendStringArrayAsMap(absl::Span<const std::string> arr) final;
|
||||
void SendStringArrayAsSet(absl::Span<const std::string_view> arr) final;
|
||||
void SendStringArrayAsSet(absl::Span<const std::string> arr) final;
|
||||
void SendSimpleStrArr(absl::Span<const string_view> arr) final;
|
||||
void SendNullArray() final;
|
||||
|
||||
void SendStringArr(absl::Span<const string_view> arr) final;
|
||||
void SendStringArr(absl::Span<const string> arr) final;
|
||||
void SendStringArr(StrSpan arr, CollectionType type) final;
|
||||
void SendNull() final;
|
||||
|
||||
void SendLong(long val) final;
|
||||
|
@ -227,7 +222,7 @@ class InterpreterReplier : public RedisReplyBuilder {
|
|||
|
||||
void SendBulkString(std::string_view str) final;
|
||||
|
||||
void StartArray(unsigned len) final;
|
||||
void StartCollection(unsigned len, CollectionType type) final;
|
||||
|
||||
private:
|
||||
void PostItem();
|
||||
|
@ -335,45 +330,24 @@ void InterpreterReplier::SendMGetResponse(const OptResp* resp, uint32_t count) {
|
|||
explr_->OnArrayEnd();
|
||||
}
|
||||
|
||||
void InterpreterReplier::SendSimpleStrArr(const string_view* arr, uint32_t count) {
|
||||
explr_->OnArrayStart(count);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
explr_->OnString(arr[i]);
|
||||
}
|
||||
void InterpreterReplier::SendSimpleStrArr(absl::Span<const string_view> arr) {
|
||||
explr_->OnArrayStart(arr.size());
|
||||
for (auto sv : arr)
|
||||
explr_->OnString(sv);
|
||||
explr_->OnArrayEnd();
|
||||
}
|
||||
|
||||
void InterpreterReplier::SendStringArrayAsMap(absl::Span<const string_view> arr) {
|
||||
SendStringArr(arr);
|
||||
}
|
||||
|
||||
void InterpreterReplier::SendStringArrayAsMap(absl::Span<const string> arr) {
|
||||
SendStringArr(arr);
|
||||
}
|
||||
|
||||
void InterpreterReplier::SendStringArrayAsSet(absl::Span<const string_view> arr) {
|
||||
SendStringArr(arr);
|
||||
}
|
||||
|
||||
void InterpreterReplier::SendStringArrayAsSet(absl::Span<const string> arr) {
|
||||
SendStringArr(arr);
|
||||
}
|
||||
|
||||
void InterpreterReplier::SendNullArray() {
|
||||
SendSimpleStrArr(nullptr, 0);
|
||||
SendSimpleStrArr({});
|
||||
PostItem();
|
||||
}
|
||||
|
||||
void InterpreterReplier::SendStringArr(absl::Span<const string_view> arr) {
|
||||
SendSimpleStrArr(arr.data(), arr.size());
|
||||
PostItem();
|
||||
}
|
||||
|
||||
void InterpreterReplier::SendStringArr(absl::Span<const string> arr) {
|
||||
explr_->OnArrayStart(arr.size());
|
||||
for (uint32_t i = 0; i < arr.size(); ++i) {
|
||||
explr_->OnString(arr[i]);
|
||||
}
|
||||
void InterpreterReplier::SendStringArr(StrSpan arr, CollectionType) {
|
||||
WrappedStrSpan warr{arr};
|
||||
size_t size = warr.Size();
|
||||
explr_->OnArrayStart(size);
|
||||
for (size_t i = 0; i < size; i++)
|
||||
explr_->OnString(warr[i]);
|
||||
explr_->OnArrayEnd();
|
||||
PostItem();
|
||||
}
|
||||
|
@ -398,7 +372,7 @@ void InterpreterReplier::SendBulkString(string_view str) {
|
|||
PostItem();
|
||||
}
|
||||
|
||||
void InterpreterReplier::StartArray(unsigned len) {
|
||||
void InterpreterReplier::StartCollection(unsigned len, CollectionType) {
|
||||
explr_->OnArrayStart(len);
|
||||
|
||||
if (len == 0) {
|
||||
|
@ -1519,7 +1493,7 @@ void Service::Pubsub(CmdArgList args, ConnectionContext* cntx) {
|
|||
"HELP",
|
||||
"\tPrints this help."};
|
||||
|
||||
(*cntx)->SendSimpleStrArr(help_arr, ABSL_ARRAYSIZE(help_arr));
|
||||
(*cntx)->SendSimpleStrArr(help_arr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ void MemoryCmd::Run(CmdArgList args) {
|
|||
"USAGE",
|
||||
" (not implemented).",
|
||||
};
|
||||
return (*cntx_)->SendSimpleStrArr(help_arr, ABSL_ARRAYSIZE(help_arr));
|
||||
return (*cntx_)->SendSimpleStrArr(help_arr);
|
||||
};
|
||||
|
||||
if (sub_cmd == "USAGE") {
|
||||
|
|
|
@ -71,7 +71,7 @@ void ScriptMgr::Run(CmdArgList args, ConnectionContext* cntx) {
|
|||
" Prints latency histograms in usec for every called function.",
|
||||
"HELP"
|
||||
" Prints this help."};
|
||||
return (*cntx)->SendSimpleStrArr(kHelp, ABSL_ARRAYSIZE(kHelp));
|
||||
return (*cntx)->SendSimpleStrArr(kHelp);
|
||||
}
|
||||
|
||||
if (subcmd == "EXISTS" && args.size() > 1)
|
||||
|
|
|
@ -1208,7 +1208,7 @@ void ServerFamily::Cluster(CmdArgList args, ConnectionContext* cntx) {
|
|||
"HELP",
|
||||
" Prints this help.",
|
||||
};
|
||||
return (*cntx)->SendSimpleStrArr(help_arr, ABSL_ARRAYSIZE(help_arr));
|
||||
return (*cntx)->SendSimpleStrArr(help_arr);
|
||||
}
|
||||
|
||||
if (sub_cmd == "SLOTS") {
|
||||
|
@ -1320,7 +1320,7 @@ void ServerFamily::Config(CmdArgList args, ConnectionContext* cntx) {
|
|||
string_view param = ArgS(args, 2);
|
||||
string_view res[2] = {param, "tbd"};
|
||||
|
||||
return (*cntx)->SendStringArrayAsMap(res);
|
||||
return (*cntx)->SendStringArr(res, RedisReplyBuilder::MAP);
|
||||
} else if (sub_cmd == "RESETSTAT") {
|
||||
shard_set->pool()->Await([](auto*) {
|
||||
auto* stats = ServerState::tl_connection_stats();
|
||||
|
@ -1713,7 +1713,7 @@ void ServerFamily::Hello(CmdArgList args, ConnectionContext* cntx) {
|
|||
(*cntx)->SetResp3(false);
|
||||
}
|
||||
|
||||
(*cntx)->StartMap(7);
|
||||
(*cntx)->StartCollection(7, RedisReplyBuilder::MAP);
|
||||
(*cntx)->SendBulkString("server");
|
||||
(*cntx)->SendBulkString("redis");
|
||||
(*cntx)->SendBulkString("version");
|
||||
|
|
|
@ -27,6 +27,8 @@ ABSL_DECLARE_FLAG(bool, use_set2);
|
|||
|
||||
namespace dfly {
|
||||
|
||||
using namespace facade;
|
||||
|
||||
using namespace std;
|
||||
using absl::GetFlag;
|
||||
|
||||
|
@ -1205,7 +1207,7 @@ void SPop(CmdArgList args, ConnectionContext* cntx) {
|
|||
(*cntx)->SendBulkString(result.value().front());
|
||||
}
|
||||
} else { // SPOP key cnt
|
||||
(*cntx)->SendStringArrayAsSet(*result);
|
||||
(*cntx)->SendStringArr(*result, RedisReplyBuilder::SET);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1241,7 +1243,7 @@ void SDiff(CmdArgList args, ConnectionContext* cntx) {
|
|||
if (cntx->conn_state.script_info) { // sort under script
|
||||
sort(arr.begin(), arr.end());
|
||||
}
|
||||
(*cntx)->SendStringArrayAsSet(arr);
|
||||
(*cntx)->SendStringArr(arr, RedisReplyBuilder::SET);
|
||||
}
|
||||
|
||||
void SDiffStore(CmdArgList args, ConnectionContext* cntx) {
|
||||
|
@ -1309,7 +1311,7 @@ void SMembers(CmdArgList args, ConnectionContext* cntx) {
|
|||
if (cntx->conn_state.script_info) { // sort under script
|
||||
sort(svec.begin(), svec.end());
|
||||
}
|
||||
(*cntx)->SendStringArrayAsSet(*result);
|
||||
(*cntx)->SendStringArr(*result, RedisReplyBuilder::SET);
|
||||
} else {
|
||||
(*cntx)->SendError(result.status());
|
||||
}
|
||||
|
@ -1331,7 +1333,7 @@ void SInter(CmdArgList args, ConnectionContext* cntx) {
|
|||
if (cntx->conn_state.script_info) { // sort under script
|
||||
sort(arr.begin(), arr.end());
|
||||
}
|
||||
(*cntx)->SendStringArrayAsSet(arr);
|
||||
(*cntx)->SendStringArr(arr, RedisReplyBuilder::SET);
|
||||
} else {
|
||||
(*cntx)->SendError(result.status());
|
||||
}
|
||||
|
@ -1394,7 +1396,7 @@ void SUnion(CmdArgList args, ConnectionContext* cntx) {
|
|||
if (cntx->conn_state.script_info) { // sort under script
|
||||
sort(arr.begin(), arr.end());
|
||||
}
|
||||
(*cntx)->SendStringArrayAsSet(arr);
|
||||
(*cntx)->SendStringArr(arr, RedisReplyBuilder::SET);
|
||||
} else {
|
||||
(*cntx)->SendError(unionset.status());
|
||||
}
|
||||
|
|
|
@ -666,7 +666,7 @@ void StreamFamily::XGroup(CmdArgList args, ConnectionContext* cntx) {
|
|||
"SETID <key> <groupname> <id|$>",
|
||||
" Set the current group ID.",
|
||||
};
|
||||
return (*cntx)->SendSimpleStrArr(help_arr, ABSL_ARRAYSIZE(help_arr));
|
||||
return (*cntx)->SendSimpleStrArr(help_arr);
|
||||
}
|
||||
|
||||
if (args.size() >= 3) {
|
||||
|
@ -709,7 +709,7 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) {
|
|||
"STREAM <key> [FULL [COUNT <count>]",
|
||||
" Show information about the stream.",
|
||||
};
|
||||
return (*cntx)->SendSimpleStrArr(help_arr, ABSL_ARRAYSIZE(help_arr));
|
||||
return (*cntx)->SendSimpleStrArr(help_arr);
|
||||
}
|
||||
|
||||
if (args.size() >= 3) {
|
||||
|
@ -734,7 +734,7 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) {
|
|||
string_view arr[8] = {"name", ginfo.name, "consumers", an1.Piece(),
|
||||
"pending", an2.Piece(), "last-delivered-id", last_id};
|
||||
|
||||
(*cntx)->SendStringArrayAsMap(absl::Span<string_view>{arr, 8});
|
||||
(*cntx)->SendStringArr(absl::Span<string_view>{arr, 8}, RedisReplyBuilder::MAP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue